awslabs / aws-mobile-appsync-sdk-js

JavaScript library files for Offline, Sync, Sigv4. includes support for React Native
Apache License 2.0
916 stars 265 forks source link

Subscriptions are disconnected after background/lock and unlock the app in React-Native #740

Open juanch0x opened 1 year ago

juanch0x commented 1 year ago

Do you want to request a feature or report a bug?

Bug

What is the current behavior?

I'm using React Native, and after background the application or lock the phone, when you focus it again all the subscriptions are disconnected and they are not receving events anymore (both useSubscription and subscribeToMore)

If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem.

What is the expected behavior?

After background the app or lock and unlock the phone keep receiving the subscription events

Which versions and which environment (browser, react-native, nodejs) / OS are affected by this issue? Did this work in previous versions?

"aws-appsync-auth-link": "^3.0.7",
"aws-appsync-subscription-link": "^3.1.2",
"@apollo/client": "^3.7.4",
"react-native": "0.70.3",
dylan-westbury commented 1 year ago

Also error message shows "Connection closed", where subscription events are no longer received. Any idea how to re-connect? Currently use useSubscription and subscribeToMore.

I believe Amplify Graphql client manages reconnects, not sure if that applies to this sdk also

https://docs.amplify.aws/lib/graphqlapi/subscribe-data/q/platform/js/#using-amplify-graphql-client

On simulator less prone to the subscription closing. But on real device with an .ipa installed, locking the screen / idle for a period of time the subscription does not resusbcribe

n8downs commented 1 year ago

We found the subscriptions using aws-appsync-subscription-link on web to be too unreliable to use in production. They seem to work just enough to be dangerous, but we kept hitting this issue as well as #684.

I wanted to stick with Apollo, so I ended up replacing our subscriptions with essentially:

const apolloClient = useApolloClient();
useEffect(() => {
  const newRoutineSubscription = API.graphql(
    graphqlOperation(SubscribeToNewRoutineBySession, { sessionId })
  ).subscribe({
    next: ({ provider, value }) => {
      const routine = value.data.subscribeToNewRoutineBySession;
      apolloClient.writeFragment({
        id: cacheIdForNode(routine),
        fragment: NewRoutineFragment,
        fragmentName: 'NewRoutineFragment',
        data: routine,
      });
    },
    error: (error) => {
      // do something sensible
    },
  });
  return () => newRoutineSubscription.unsubscribe();
}, [sessionId, apolloClient]);

One big caveat is that you'll need to add __typenames explicitly to your fragments, otherwise the Apollo cache won't know how to handle the subscription data if they're not provided (Apollo adds these automatically when you use useQuery).

Hope that helps somebody!

pepemiso16 commented 1 year ago

I am also encountering this issue @juanch0x and looks like there's no update for a long time with this SDK. Is there any workaround that you did from your end?

pepemiso16 commented 1 year ago

We found the subscriptions using aws-appsync-subscription-link on web to be too unreliable to use in production. They seem to work just enough to be dangerous, but we kept hitting this issue as well as #684.

I wanted to stick with Apollo, so I ended up replacing our subscriptions with essentially:

const apolloClient = useApolloClient();
useEffect(() => {
  const newRoutineSubscription = API.graphql(
    graphqlOperation(SubscribeToNewRoutineBySession, { sessionId })
  ).subscribe({
    next: ({ provider, value }) => {
      const routine = value.data.subscribeToNewRoutineBySession;
      apolloClient.writeFragment({
        id: cacheIdForNode(routine),
        fragment: NewRoutineFragment,
        fragmentName: 'NewRoutineFragment',
        data: routine,
      });
    },
    error: (error) => {
      // do something sensible
    },
  });
  return () => newRoutineSubscription.unsubscribe();
}, [sessionId, apolloClient]);

One big caveat is that you'll need to add __typenames explicitly to your fragments, otherwise the Apollo cache won't know how to handle the subscription data if they're not provided (Apollo adds these automatically when you use useQuery).

Hope that helps somebody!

@n8downs, are you also using apollo client? If you are using apollo client as well, did you change the configuration and did you remove aws-appsync-subscription-link. On your given code, how can you use subscription? I mean, are you still using createSubscriptionHandshakeLink?

juanch0x commented 1 year ago

I am also encountering this issue @juanch0x and looks like there's no update for a long time with this SDK. Is there any workaround that you did from your end?

Sadly, the only workaround that I found was disconnect the "subscribeToMore" when the app is moved to background or lost internet connection, and subscribe it again and fetch the info from the query when the app comes to foreground or get internet connection again

pepemiso16 commented 1 year ago

I am also encountering this issue @juanch0x and looks like there's no update for a long time with this SDK. Is there any workaround that you did from your end?

Sadly, the only workaround that I found was disconnect the "subscribeToMore" when the app is moved to background or lost internet connection, and subscribe it again and fetch the info from the query when the app comes to foreground or get internet connection again

Does it mean you're reloading the app?

n8downs commented 1 year ago

@n8downs, are you also using apollo client? If you are using apollo client as well, did you change the configuration and did you remove aws-appsync-subscription-link. On your given code, how can you use subscription? I mean, are you still using createSubscriptionHandshakeLink?

Yes, we're using apollo client, and yes, we removed the aws-appsync-subscription-link entirely from our codebase.

objectiveSee commented 8 months ago

@n8downs did you find that the Apollo client has a method for re-connecting a subscription websocket? Could you provide any code snippet of how your fixed this re-connect issue in GraphQL subscriptions?