-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Apollo v3 subscriptions not working on React Native Android only. #6520
Comments
I am testing on Android right now. It does work for me. What's your setup? |
I'm also experiencing this issue. I'm using the basic setup from the docs:
the split is working as expected but when using |
Can you try different beta/RC versions ( |
@benjamn You're right,it's a regression! Just tried a few beta and RC versions, on 3.0.0-beta.23 it works as expected. My setup: let persistor
export const wsClient = new SubscriptionClient(WS_URI, {
lazy: true,
reconnect: true,
connectionParams: async () => {
const token = await AsyncStorage.getItem(authToken)
return {
Authorization: token ? `Bearer ${token}` : null
}
}
})
const wsLink = new WebSocketLink(wsClient)
export const setupApollo = async () => {
const retryLink = new RetryLink({
attempts: (count, operation, error) => {
const isMutation =
operation &&
operation.query &&
operation.query.definitions &&
Array.isArray(operation.query.definitions) &&
operation.query.definitions.some(
(def) =>
def.kind === 'OperationDefinition' && def.operation === 'mutation'
)
if (isMutation) {
return !!error && count < 25
}
return !!error && count < 6
}
})
const httpLink = new HttpLink({
uri: GRAPHQL_URI,
credentials: 'include'
})
const splitLink = split(
({ query }) => {
const definition = getMainDefinition(query)
return (
definition.kind === 'OperationDefinition' &&
definition.operation === 'subscription'
)
},
wsLink,
httpLink
)
const errorLink = onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors)
graphQLErrors.map(({ message, locations, path }) => {
console.log(
`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`
)
})
if (networkError) console.log(`[Network error]: ${networkError}`)
})
const authLink = setContext(async (_, { headers }) => {
const token = await AsyncStorage.getItem(authToken)
return {
headers: {
...headers,
authorization: token ? `Bearer ${token}` : null
}
}
})
const cache = new InMemoryCache({
possibleTypes: introspectionResult.possibleTypes
})
persistor = new CachePersistor({
cache,
storage: AsyncStorage as PersistentStorage<
PersistedData<NormalizedCacheObject>
>,
maxSize: 2048000,
// debug: true,
trigger: 'background'
})
const currentVersion = await AsyncStorage.getItem(SCHEMA_VERSION_KEY)
try {
if (currentVersion === SCHEMA_VERSION) {
// If the current version matches the latest version,
// we're good to go and can restore the cache.
await persistor.restore()
} else {
// Otherwise, we'll want to purge the outdated persisted cache
// and mark ourselves as having updated to the latest version.
await persistor.purge()
await AsyncStorage.setItem(SCHEMA_VERSION_KEY, SCHEMA_VERSION)
}
} catch (err) {
// CachePersistor failed - purge
await persistor.purge()
}
return new ApolloClient({
link: from([errorLink, authLink, retryLink, splitLink]),
cache,
assumeImmutableResults: true,
queryDeduplication: true,
defaultOptions: {
watchQuery: {
fetchPolicy: 'cache-and-network',
errorPolicy: 'none'
},
query: {
fetchPolicy: 'cache-first',
errorPolicy: 'all'
}
}
})
} |
@benjamn Lastest working beta is beta.45, i hope it helps. |
@immortalx is correct, beta.46 is the first one where it breaks |
@immortalx Any chance you could put your code into a runnable (React Native) reproduction repo/sandbox? I wish I could link you to a simple RN/Apollo starter project, but I don't know of one off-hand. Presumably https://expo.io/ is the easiest way to get started, and maybe you can find a "snack" that uses Note that AC3 is slated to be released tomorrow, so this might not get fixed before then, but that doesn't mean we won't fix it. |
@benjamn sure, can you point me to any public graphql api with subscriptions so i can use it to test? |
Thanks for bringing this up @immortalx, I was starting to go nuts. I can confirm that this is still broken in the latest 3.1.1 version, and I'm now using @apollo/client^3.0.0-beta.45 to get subscriptions working on android |
Same in v3.1.3. Same Subscriptions code that worked fine in v2 on both {iOS, Android} is now broken on Android. The |
Worth noting that when rn's Debug mode is enabled, causing JS to be parsed in the browser context (as opposed to the "device" or bridge), subscriptions work just fine. |
Some useful insight: turning off Hermes engine actually fixed the issue. This definitely smells like a js engine change/issue, rather than Apollo client problem. |
My subscription hook is just returning loading as response. I am using "subscriptions-transport-ws": "^0.9.18". Do you guys have any idea about how to fix it? @schonfeld @benjamn @immortalx @martimalek |
If this only happens on Android for you, my solution was turning off Herms engine in project.ext.react = [
entryFile: "index.js",
enableHermes: false
] If the issue also occurs on an iPhone sim (or device), your problem might not relate to this specific issue... |
My subscription hook is just returning loading as response. I am using "subscriptions-transport-ws": "^0.9.18". Do you guys have any idea about how to fix it? @schonfeld @benjamn @immortalx @martimalek No, it is happening in both ios and android and I haven't enable hermes too |
Having the same problem with hermes. It's only working in debug mode because of the different js engine... damn... |
Any updates? Subscription is still broken on Hermes engine. |
Any news at all? This issue is blocking our Android app, would love to start using v3 but this is a huge blocker :( Thanks! |
Also experiencing this issue, works on iOS. Using hermes engine for android.
|
I already have hermes disabled by default. NEVER USED IT. I managed to get it back working. In my case, the error seems to have been that one of my susbscriptions didn't have an
This was fixed by giving it an
In my case it just so happened that this subscription was the first one ever called and so for whatever reason it broke everything subscription-related after it, even when other subscriptions did have an For whatever reason Apollo 3 now requires all subscriptions to have an OperationName, which definitely was never the case in 2.X. This was never mentioned anywhere, and let's just say I am upset about the time I had to waste. |
The error persists for me on Apollo v3, even when giving the subscription an const MESSAGE_ADDED_SUBSCRIPTION = gql`
subscription messageAdded($chatIds: [ID]!) {
messageAdded(chatIds: $chatIds) {
_id
createdAt
senderId
chatId
content
}
}
`; The issue happens only on Android when Hermes engine is enabled. |
same thing here, Apollo v3, can't get subscription working (thinking moving to socket.io or pusher) |
Hi @dvirben123, This one is not related to the issue but can I use Subscriptions for push notifications on mobile? is the app going to still receive data after subscribing when the app is in the background or killed? and what strategy is used to push pending notifications after device is turned on? You may or may not have the answers to all of these but I really want to understand the concept here so any clarifications would be appreciated. Thank you :) |
Hi, basically I want to get notifications only when the app is live or in the background, I know that using Apple or Google services for push notification is a better approach, I want to know what is the maximum that I get can from Apollo |
subscription is inconsistent sometimes data is present and sometimes it is not returning data , and when in debug mode sometimes subscription doesn't return data.in apk file also it is not showing any new data. I have operation name too in my subscription. @zakthedev @dvirben123 @rarenatoe @Rieranthony @immortalx @benjamn .any idea on how to solve this, or how did you guys fix this? |
I always use the latest versions if it works. package.json
ApolloClient (basic)
build.gradle
Not sure what else would be relevant to you ? |
@nikosmonaut if you are using Apollo 3, you should probably drop all those link packages since they are now included in the main Apollo Client (check https://www.apollographql.com/docs/react/migrating/apollo-client-3-migration/ ) |
@Dunos is subscription working perfectly in your application, if it is can you share your apollo setup and package imported so that I can replicate it and test it |
@kirantripathi I created a gist for you with my working setup. It seems to be working very well and stable so far. (As long as I do not use hermes engine). https://gist.github.com/happyfloat/c0ddfc933cfa6a40f71947ae0ff49767 |
@Dunos @nikosmonaut , one thing I am getting in subscription query response is regarding token expire , so if our token is expire , how can I reconnect the web socket with new token. any idea on that? |
@kirantripathi the approach we use for authentication on websockets is to use a query parameter with the token in the WS uri, and refreshing the token and the uri using the "onError" events of the SubscriptionClient. |
@Dunos can you provide me example ? |
@kirantripathi It's not really important to have a stale token in subscriptions. Because the connection is done only once the first time. Nevertheless if you want to reconnect you'll have to send a new token. First of all check this library subscriptions-transport-ws because it's behind all of it. If you have followed the template from graphql docs, you would already have a base. Then use a function as connectionParams
Then when you get a expired token message replace your variable YOURTOKEN by the new one and reconnect your socket.
Edit: Beware it's a broken library. issue. So don't rely only on the onConnect callback serverside. But check your context in resolvers aswell |
Tried many many different versions, just got it working on 3.0.0 beta 45, any version after that doesn't seem to work on android using hermes. |
@nikosmonaut I try without updating token , and it is working , so we won't need to update token after session expire. One thing is I am not able to find is the reason for inconsistency , however when I close the app and open again maybe it will reconnect again so that's why it start to work again, but sometimes even though I get information as reconnecting and reconnected the subscription don't work , and it only work after reloading the app. any idea on how can I tackle it . |
@kirantripathi I can't say for sure. But when you go background with your app the connection gets disconnected no matter what after some time (~1min). So when you go active again the connection is initiated once more. Imagine you have an expired token it will not work. |
re: #6520 (comment) @nikosmonaut You're looking at code in the
Apollo Client has one However, I'm having trouble guessing anything more about the problem, because Hermes purposefully does not implement I realize this was a complicated explanation that probably sounds borderline unhinged if you aren't familiar with the ECMAScript specification, but hopefully it inspires someone here to dig a little deeper into whatever React Native is doing with |
An attempt to address the problems I speculated about in #6520 (comment) Theory: in the Hermes JS engine, Symbol.species is not defined, so Object.defineProperty was not called, but perhaps "@@species" was getting set somewhere else by a polyfill library, causing the zen-observable library to fall back to "@@species" instead of using/ignoring the nonexistent Symbol.species symbol.
I had got to read it 3 times, but finally I got it. Your suppositions are right. I think it's core-js that add @@species prop to Symbol => core-js observable which is indeed used by react-native => @react-native-community/cli => metro => metro-babel-register -> core-js |
An attempt to address the problems I speculated about in #6520 (comment) Theory: in the Hermes JS engine, Symbol.species is not defined, so Object.defineProperty was not called, but perhaps "@@species" was getting set somewhere else by a polyfill library, causing the zen-observable library to fall back to "@@species" instead of using/ignoring the nonexistent Symbol.species symbol.
An attempt to address the problems I speculated about in #6520 (comment) Theory: in the Hermes JS engine, Symbol.species is not defined, so Object.defineProperty was not called, but perhaps "@@species" was getting set somewhere else by a polyfill library, causing the zen-observable library to fall back to "@@species" instead of using/ignoring the nonexistent Symbol.species symbol.
Alright everybody, if you run |
Of course, if you're updating to v3.4 from v3.0.0-beta.45, you may want to read through the |
@benjamn yes. this beta fixed my issue in android (hermes enabled) with version |
From |
Same here 👋 works now
|
An attempt to address the problems I speculated about in #6520 (comment) Theory: in the Hermes JS engine, Symbol.species is not defined, so Object.defineProperty was not called, but perhaps "@@species" was getting set somewhere else by a polyfill library, causing the zen-observable library to fall back to "@@species" instead of using/ignoring the nonexistent Symbol.species symbol.
The |
For some reason, subcription not working for me =( loading state true, data and error are undefined. Im using apollo client 3.3.8. Im got data on playground however |
Having the same issue
|
Just trying to upgrade to v3.
Everything is working fine, just subscriptions on React Native android doesn't work at all. On iOS is working fine as expected.
On v2, both iOS and Android works fine.
Intended outcome:
Subscriptions should work on both iOS and Android while using React Native.
Actual outcome:
Subscriptions only works in iOS. On android nothing happens, no errors or warnings.
Versions
npmPackages:
@apollo/client: ^3.0.0-rc.9 => 3.0.0-rc.9
@apollo/link-context: ^2.0.0-beta.3 => 2.0.0-beta.3
@apollo/link-error: ^2.0.0-beta.3 => 2.0.0-beta.3
@apollo/link-retry: ^2.0.0-beta.3 => 2.0.0-beta.3
@apollo/link-ws: ^2.0.0-beta.3 => 2.0.0-beta.3
apollo-cache-persist: ^0.1.1 => 0.1.1
The text was updated successfully, but these errors were encountered: