Skip to content
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

No callback/promise returned when subscription is removed and when socket connection is disconnected. #9818

Closed
3 tasks done
shashika-v opened this issue Apr 18, 2022 · 8 comments
Assignees
Labels
GraphQL Related to GraphQL API issues React Native React Native related issue

Comments

@shashika-v
Copy link

Before opening, please confirm:

JavaScript Framework

React Native

Amplify APIs

GraphQL API

Amplify Categories

api

Environment information

# Put output below this line

System:
    OS: macOS 11.6
    CPU: (4) x64 Intel(R) Core(TM) i7-7660U CPU @ 2.50GHz
    Memory: 3.34 GB / 16.00 GB
    Shell: 5.8 - /bin/zsh
  Binaries:
    Node: 14.4.0 - /usr/local/bin/node
    Yarn: 1.22.4 - /usr/local/bin/yarn
    npm: 6.14.4 - /usr/local/bin/npm
    Watchman: 4.9.0 - /usr/local/bin/watchman
  Browsers:
    Chrome: 100.0.4896.88
    Safari: 15.0
  npmPackages:
    @apollo/client: ^3.3.6 => 3.3.6 
    @apollo/client/cache:  undefined ()
    @apollo/client/core:  undefined ()
    @apollo/client/errors:  undefined ()
    @apollo/client/link/batch:  undefined ()
    @apollo/client/link/batch-http:  undefined ()
    @apollo/client/link/context:  undefined ()
    @apollo/client/link/core:  undefined ()
    @apollo/client/link/error:  undefined ()
    @apollo/client/link/http:  undefined ()
    @apollo/client/link/persisted-queries:  undefined ()
    @apollo/client/link/retry:  undefined ()
    @apollo/client/link/schema:  undefined ()
    @apollo/client/link/utils:  undefined ()
    @apollo/client/link/ws:  undefined ()
    @apollo/client/react:  undefined ()
    @apollo/client/react/components:  undefined ()
    @apollo/client/react/context:  undefined ()
    @apollo/client/react/data:  undefined ()
    @apollo/client/react/hoc:  undefined ()
    @apollo/client/react/hooks:  undefined ()
    @apollo/client/react/parser:  undefined ()
    @apollo/client/react/ssr:  undefined ()
    @apollo/client/testing:  undefined ()
    @apollo/client/utilities:  undefined ()
    @babel/core: ^7.12.9 => 7.12.9 
    @babel/runtime: ^7.12.5 => 7.12.5 
    @react-native-async-storage/async-storage: ^1.13.2 => 1.13.2 
    @react-native-community/art: ^1.2.0 => 1.2.0 
    @react-native-community/eslint-config: ^2.0.0 => 2.0.0 
    @react-native-community/hooks: ^2.6.0 => 2.6.0 
    @react-native-community/masked-view: ^0.1.10 => 0.1.11 
    @react-native-community/netinfo: ^5.9.10 => 5.9.10 
    @react-native-community/progress-bar-android: ^1.0.4 => 1.0.4 
    @react-native-community/progress-view: ^1.2.4 => 1.3.1 
    @react-navigation/bottom-tabs: ^5.11.10 => 5.11.10 
    @react-navigation/native: ^5.8.10 => 5.8.10 (3.8.4)
    @react-navigation/stack: ^5.12.8 => 5.12.8 
    ContextAPIMixpanel:  0.0.1 
    HelloWorld:  0.0.1 
    MixpanelDemo:  0.0.1 
    PDFExample:  0.0.1 
    ReactNativeOrientationDemo:  2.0.0 
    SimpleMixpanel:  0.0.1 
    accordion-collapse-react-native: ^1.0.1 => 1.0.1 
    apollo3-cache-persist: ^0.12.1 => 0.12.1 
    appcenter: 4.3.0 => 4.3.0 
    appcenter-analytics: 4.3.0 => 4.3.0 
    appcenter-crashes: 4.3.0 => 4.3.0 
    aws-amplify: ^4.3.19 => 4.3.19 
    aws-appsync: ^4.1.4 => 4.1.4 
    aws-appsync-subscription-link: ^3.0.9 => 3.0.9 (2.2.6)
    axios: ^0.21.0 => 0.21.0 (0.21.4)
    babel-jest: ^26.6.3 => 26.6.3 
    eslint: ^7.14.0 => 7.14.0 
    graphql: ^15.4.0 => 15.4.0 (15.8.0)
    hermes-inspector-msggen:  1.0.0 
    husky: ^7.0.4 => 7.0.4 
    jest: ^26.6.3 => 26.6.3 
    jwt-decode: ^3.1.2 => 3.1.2 
    lint-staged: ^12.3.3 => 12.3.3 
    metro-react-native-babel-preset: ^0.64.0 => 0.64.0 (0.59.0, 0.58.0)
    mixpanel-react-native: ^1.3.1 => 1.3.1 
    moment: ^2.29.1 => 2.29.1 
    prettier: 2.5.1 => 2.5.1 
    qs: ^6.9.4 => 6.9.4 (6.5.2)
    react: 16.13.1 => 16.13.1 
    react-animated:  0.1.0 
    react-native: 0.63.3 => 0.63.3 
    react-native-awesome-alerts: ^1.4.2 => 1.4.2 
    react-native-base64: ^0.2.1 => 0.2.1 
    react-native-calendar-picker: ^7.1.2 => 7.1.2 
    react-native-cookie: ^0.3.0 => 0.3.0 
    react-native-device-info: ^8.4.9 => 8.4.9 
    react-native-easy-grid: ^0.2.2 => 0.2.2 
    react-native-gesture-handler: ^1.9.0 => 1.9.0 
    react-native-inappbrowser-reborn: 3.6.3 => 3.6.3 
    react-native-keep-awake: ^4.0.0 => 4.0.0 
    react-native-keyboard-aware-scroll-view: ^0.9.4 => 0.9.4 
    react-native-linear-gradient: ^2.5.6 => 2.5.6 
    react-native-markdown-display: ^7.0.0-alpha.2 => 7.0.0-alpha.2 
    react-native-media-controls: ^2.2.0 => 2.2.0 
    react-native-onesignal: ^4.3.1 => 4.3.1 
    react-native-orientation: ^3.1.3 => 3.1.3 
    react-native-pdf: ^6.3.0 => 6.3.0 
    react-native-percentage-circle: ^1.0.7 => 1.0.7 
    react-native-popover-view: ^5.0.0 => 5.0.1 
    react-native-progress: github:abhaydee/react-native-progress#feature/imageCirclev3 => 5.0.0 
    react-native-progress-circle: ^2.1.0 => 2.1.0 
    react-native-rename: ^2.6.0 => 2.6.0 
    react-native-responsive-screen: ^1.4.1 => 1.4.1 
    react-native-safe-area-context: ^3.1.9 => 3.1.9 
    react-native-screens: ^2.15.0 => 2.16.1 
    react-native-segmented-control-tab: ^3.4.1 => 3.4.1 
    react-native-simple-radio-button: ^2.7.4 => 2.7.4 
    react-native-slider: ^0.11.0 => 0.11.0 
    react-native-snap-carousel: ^3.9.1 => 3.9.1 
    react-native-splash-screen: ^3.2.0 => 3.2.0 
    react-native-svg: ^12.1.1 => 12.1.1 
    react-native-svg-animated-linear-gradient: ^0.4.0 => 0.4.0 
    react-native-swiper: ^1.6.0-rc.3 => 1.6.0-rc.3 
    react-native-track-player: github:abhaydee/react-native-track-player#android-12-fix => 2.1.2 
    react-native-uuid: ^2.0.1 => 2.0.1 
    react-native-vector-icons: ^7.1.0 => 7.1.0 
    react-native-video: ^5.1.1 => 5.1.1 
    react-native-video-player: ^0.10.1 => 0.10.1 
    react-native-webview: ^11.2.3 => 11.2.3 
    react-navigation: ^4.4.4 => 4.4.4 
    react-test-renderer: 16.13.1 => 16.13.1 
    responsive-screen:  0.1.0 
    responsive-screen-orientation-change:  0.1.0 
    responsive-screen-styled-components:  0.1.0 
    rn-fetch-blob: ^0.12.0 => 0.12.0 
    tsutils: 3.20.0 => 3.20.0 
    url-search-params-polyfill: ^8.1.0 => 8.1.0 
    uuid: ^8.3.2 => 8.3.2 (3.4.0, 3.3.2)
  npmGlobalPackages:
    appcenter-cli: 2.10.0
    graphql-schema-utilities: 1.1.3
    graphql: 15.6.1
    ios-deploy: 1.10.0
    npm: 6.14.4
    react-native-cli: 2.0.1
    serverless: 2.62.0

Describe the bug

This is an issue with the subscription socket connection with the Amplify SDK. The issue happens on iOS build when the app goes to the inactive state and resume back it throws out an error message "AWSAppSyncRealTimeProvider - Disconnect error: Timeout disconnect". This happens in android when there is very long duration of inactivity.

When we tried multiple implementation setup including unsubscribing from all the subscriptions on the error to disconnecting the socket and tried resubscribing, which still throws out the error.

Currently, after unsubscribing, giving a timeout of 10 seconds to reestablish the connection works but again that is just a work-around which can fail on network issues etc. We need to exactly know when the connection is disconnected or at least when the unsubscribing is successful. There is no callback/promise for either unsubscribing or when connection ends.

Expected behavior

Callback present or promise returned on unsubscribing or when socket connection ends.

Reproduction steps

  1. Install the package aws-amplify

  2. Configure it to connect to GraphQL endpoints.

  3. We are following the pattern for subscribing/unsubscribing as per official Amplify documentation( API and graphqlOperation are imported from "aws-amplify" package

After unsubscribing, there is no promise/callback. Also, we are unsubscribing from all subscriptions to end the connection. But again, there is no way to get notified/callback when the connection ends currently.

Code Snippet

// Put your code below this line.

For configuring amplify, 
const appSyncConfig = {
  aws_appsync_graphqlEndpoint: ***********,
  aws_appsync_region: ************,
  aws_appsync_authenticationType: ************,
};
Amplify.configure(appSyncConfig);

For subscribing, 
 const subscription = API.graphql(
      graphqlOperation(<name>, { <params> })
    ).subscribe({
      next: ({ provider, value }) => {
       // calling some internal methods
        }
      },
      error: (error) => console.error(error),
    });


For unsubscribing,
subscription.unsubscribe(); 

Log output

// Put your logs below this line

[DEBUG] 36:09.646 AWSAppSyncRealTimeProvider - Disconnect error: Timeout disconnect
ERROR    {"error": {"errors": [[Object]]}, "provider": {"_config": {"aws_appsync_authenticationType": "OPENID_CONNECT", "aws_appsync_graphqlEndpoint": "*****", "aws_appsync_region": "us-east-1"}, "awsRealTimeSocket": {"CLOSED": 3, "CLOSING": 2, "CONNECTING": 0, "OPEN": 1, "_eventEmitter": [NativeEventEmitter], "_socketId": 2, "_subscriptions": [Array], "protocol": "graphql-ws", "readyState": 1}, "keepAliveTimeout": 300000, "keepAliveTimeoutId": 2707, "promiseArray": [], "socketStatus": 1, "subscriptionObserverMap": Map {"*****" => [Object], "*****" => [Object], "*****" => [Object]}}}
LOG      [DEBUG] 36:11.293 AWSAppSyncRealTimeProvider - subscription message from AWS AppSync RealTime: {"type":"ka"}
LOG      [DEBUG] 36:11.299 AWSAppSyncRealTimeProvider {"id": "", "observer": null, "query": "", "variables": {}}
LOG      [DEBUG] 36:11.303 AWSAppSyncRealTimeProvider - subscription message from AWS AppSync RealTime: {"type":"ka"}
LOG      [DEBUG] 36:11.308 AWSAppSyncRealTimeProvider {"id": "", "observer": null, "query": "", "variables": {}}
LOG      [DEBUG] 36:11.342 AWSAppSyncRealTimeProvider - subscription message from AWS AppSync RealTime: {"type":"ka"}
LOG      [DEBUG] 36:11.343 AWSAppSyncRealTimeProvider {"id": "", "observer": null, "query": "", "variables": {}}
LOG      [DEBUG] 36:11.352 AWSAppSyncRealTimeProvider - subscription message from AWS AppSync RealTime: {"type":"ka"}
LOG      [DEBUG] 36:11.354 AWSAppSyncRealTimeProvider {"id": "", "observer": null, "query": "", "variables": {}}
LOG      [DEBUG] 36:11.357 AWSAppSyncRealTimeProvider - subscription message from AWS AppSync RealTime: {"type":"ka"}
LOG      [DEBUG] 36:11.358 AWSAppSyncRealTimeProvider {"id": "", "observer": null, "query": "", "variables": {}}
LOG      [DEBUG] 36:11.372 AWSAppSyncRealTimeProvider - subscription message from AWS AppSync RealTime: {"type":"ka"}
LOG      [DEBUG] 36:11.374 AWSAppSyncRealTimeProvider {"id": "", "observer": null, "query": "", "variables": {}}
LOG      [DEBUG] 36:11.397 AsyncStorageCache - Get item: key is federatedInfo with options undefined
LOG      [DEBUG] 36:11.677 AsyncStorageCache - Set item: key is federatedInfo, value is [object Object] with options: undefined
 LOG      [DEBUG] 36:11.872 AsyncStorageCache - Get item: key is federatedInfo with options undefined
 LOG      [DEBUG] 36:11.879 RestClient - POST *****graphql_endpoint*****
 LOG      [DEBUG] 36:12.274 AWSAppSyncRealTimeProvider - closing WebSocket...

aws-exports.js

No response

Manual configuration

const appSyncConfig = {
aws_appsync_graphqlEndpoint: ***********,
aws_appsync_region: ************,
aws_appsync_authenticationType: ************,
};
Amplify.configure(appSyncConfig);

Additional configuration

No response

Mobile Device

All iOS for less time of inactivity and android for longer time of inactivity

Mobile Operating System

iOS 15, Android 10

Mobile Browser

No response

Mobile Browser Version

No response

Additional information and screenshots

No response

@shashika-v shashika-v changed the title No callback/promise returned when subscription is removed and when connection is unestablished. No callback/promise returned when subscription is removed and when socket connection is disconnected. Apr 18, 2022
@chrisbonifacio chrisbonifacio added React Native React Native related issue GraphQL Related to GraphQL API issues pending-triage Issue is pending triage labels Apr 18, 2022
@chrisbonifacio chrisbonifacio added the good first issue Good for newcomers label Apr 18, 2022
@vyomr13
Copy link

vyomr13 commented Apr 18, 2022

@shashika-v .Thank you for opening this issue.
Could you give us a sample code of how you are using this in your App?

@vyomr13
Copy link

vyomr13 commented Apr 19, 2022

Screen Shot 2022-04-19 at 1 31 29 PM

Hi @shashika-v You should be able to get the timeout message and use check for the error message. You can use the error callback from the subscription (observer) to respond to the timeout appropriately.

@vyomr13 vyomr13 added pending-response and removed pending-triage Issue is pending triage labels Apr 19, 2022
@shashika-v
Copy link
Author

shashika-v commented Apr 20, 2022

@vyomr13 - As quoted earlier, we are getting the callback for error and based on that, we are removing all the subscriptions and after 10 seconds of that, trying to re-establish the connection. But our issue is we aren't getting any callback/promise after unsubscribing is successful or connection is lost. You can read through the entire description and the expected behaviour too.

@chrisbonifacio
Copy link
Member

chrisbonifacio commented Apr 20, 2022

@shashika-v This sounds more like a feature request than a bug, so I'm going to label it as such. Can you provide an example of what that functionality might look like for you ideally?

EDIT: I've added this issue to a feature request we're going to use for tracking issues related to subscriptions and WebSockets to consolidate them and see where we can focus our efforts to improve developer experience.

@Jordan-Eckowitz
Copy link

I came across this in the docs for error handling (relevant code snippet below): https://docs.amplify.aws/lib/graphqlapi/offline/q/platform/js/#error-handling

I'm not using AWSAppSyncClient to initialize the client, Amplify is handling that, but it looks like being able to access offlineConfig/callback would resolve this issue.

Is there a way to do that currently via Amplify or would I need to rewire things so that I initialize the client directly?

const client = new AWSAppSyncClient({
  url: awsconfig.aws_appsync_graphqlEndpoint,
  region: awsconfig.aws_appsync_region,
  auth: {
    type: AUTH_TYPE.API_KEY,
    apiKey: awsconfig.aws_appsync_apiKey,
  },
  offlineConfig: {
    callback: (err, succ) => {
      if(err) {
        const { mutation, variables } = err;

        console.warn(`ERROR for ${mutation}`, err);
      } else {
        const { mutation, variables } = succ;

        console.info(`SUCCESS for ${mutation}`, succ);
      }
    },
  },
});

@chrisbonifacio
Copy link
Member

chrisbonifacio commented Jul 12, 2022

@Jordan-Eckowitz This is not exposed through Amplify's API library so you would have to use the AppSync client manually. We are currently working on improving handling for socket connection status in Amplify. You can track the work the team is doing on this PR: #10063

@chrisbonifacio
Copy link
Member

@shashika-v @Jordan-Eckowitz We recently implemented some improvements to our subscriptions. Please upgrade to the latest version of aws-amplify and let us know if you are still experiencing this issue.

@chrisbonifacio chrisbonifacio added pending-response and removed good first issue Good for newcomers labels Oct 7, 2022
@Jordan-Eckowitz
Copy link

@shashika-v @Jordan-Eckowitz We recently implemented some improvements to our subscriptions. Please upgrade to the latest version of aws-amplify and let us know if you are still experiencing this issue.

Thanks @chrisbonifacio, I upgraded a few weeks back and all seems to be working now!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
GraphQL Related to GraphQL API issues React Native React Native related issue
Projects
None yet
Development

No branches or pull requests

4 participants