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

PubSub reconnect #3039

Closed
leantorres73 opened this issue Apr 8, 2019 · 64 comments
Closed

PubSub reconnect #3039

leantorres73 opened this issue Apr 8, 2019 · 64 comments
Assignees
Labels
investigating This issue is being investigated PubSub Related to PubSub category

Comments

@leantorres73
Copy link

Related to #1844, if I close the websocket connections and try to resubscribe does not reconnect the connection.

To Reproduce
Steps to reproduce the behavior:

  1. Subscribe to a topic, then close the connection and then try to resubscribe to the same topic again.

Describe the solution you'd like
There should be a way to reconnect to a closed websocket connection.

A method like removePlugabble must be included to fix and have the ability to unsubscribe and start over again.

@alebiavati alebiavati added feature-request Request a new feature needs-discussion Used for internal discussions PubSub Related to PubSub category labels Apr 11, 2019
@kirkryan
Copy link

kirkryan commented Jun 14, 2019

We also need this. If you lose signal on a portable device you're left without a valid clean method of re-establishing a connection.

@timoteialbu
Copy link

Why are none of the maintainers acknowledging this and offering some support? We had to do some very complex reconnect functionality which is a little frail and always needs fine tuning. I believe the PubSub module should handle these scenarios that are very common (signal drops)

@kirkryan
Copy link

Worst thing is that MQTT.js DOES have this functionality and that the AWS IoT client that is built on top of it simply ignores it for some reason. I’ve heard that the AWS team are working on a new release that will improve this but would like to see a comment here from the team.

As it stands - the smallest blip in connectivity for longer than a few seconds will cause the AWS IoT provider to disconnect and there is no way to reconnect it or tests its current state.

@elorzafe
Copy link
Contributor

elorzafe commented Aug 30, 2019

@leantorres73 I tried this code on a react-native app

import React, { useEffect, useState } from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';
import Amplify, { Analytics, API, PubSub } from 'aws-amplify';
import { AWSIoTProvider } from "@aws-amplify/pubsub/lib/Providers";

Analytics.disable();

Amplify.configure({
  Auth: {
    identityPoolId: "us-west-2:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx",
    region: 'us-west-2'
  }
});
Amplify.addPluggable(new AWSIoTProvider({
  aws_pubsub_region: 'us-west-2',
  aws_pubsub_endpoint: 'wss://xxxxxxxxxxxx-ats.iot.us-west-2.amazonaws.com/mqtt',
}));

let subscription;

function App() {
  const [message, setMessage] = useState('Open up App.js to start working on your app!');
  useEffect(() => {
    connect();
  }, []);
  
  
  function connect() {
    subscription = PubSub.subscribe('myTopic').subscribe({
      next: data => setMessage(JSON.stringify(data, null, 2)),
      error: error => setMessage(JSON.stringify(error, null, 2)),
      close: () => setMessage('Done'),
    });
  };

  function disconnect() {
    subscription.unsubscribe();
  };

  return (
    <View style={styles.container}>
      <Button title="connect" onPress={connect}></Button>
      <Button title="disconnect" onPress={disconnect}></Button>
      <Text>{message}</Text>
    </View>
  );
}

export default App;

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

I was able to subscribe to the same topic without issues.

@elorzafe
Copy link
Contributor

@timoteialbu @kirkryan sorry for the late response, for errors on connection on observer I merge a pr this week that solves that problem (pr #3890) so you can reconnect from there, can you try latest unstable version.

@kirkryan
Copy link

@timoteialbu @kirkryan sorry for the late response, for errors on connection on observer I merge a pr this week that solves that problem (pr #3890) so you can reconnect from there, can you try latest unstable version.

Hi @elorzafe - we’ll try it out this week thank you. I believe this will fix part 1 of the overall issue (detection of a disconnect), however there is still no clean way of re-establishing a connection. Simply running addPluggable restablishes the existing connection AND a new connection resulting in two client IDs and duplicate messages, what we really need is a method of either:

1: IOTpluggabke reconnect
Or
2. IOTremovepluggable so that we can clear the old stale connection then run an addPluggable again

Does that clarify the issue?

@elorzafe
Copy link
Contributor

elorzafe commented Sep 3, 2019

@kirkryan if you try to subscribe to the same topic (without adding the plugin) for me some reasion this not working for you? Let me know how it goes.

@kirkryan
Copy link

kirkryan commented Sep 3, 2019

@elorzafe - this doesn't work as the WebSocket itself is disconnected at this point and therefore there is no way to re-activate it, other than running an addPluggable - which then adds a new WebSocket but you then have 2 client ID's subscribed and start to receive duplicate messages!

What we really need is:

  1. A method to check the state of the WebSocket connection (pluggableState?)
  2. A method to reconnect (or auto-reconnect?) the WebSocket connection (reconnectPluggable?)
  3. A method to disconnect or remove the existing connection added by addPluggable, so that we can run it again and not have duplicate messages

Does that make sense?

@kirkryan
Copy link

kirkryan commented Sep 9, 2019

Hi @elorzafe - I upgraded our amplify to the latest version as of today. I can confirm that when the client kills the WebSocket (after approx 2 mins if you lock your phone), the app shows a code 7: Socket error undefined when you bring it back to the foreground (expected as the app is suspended therefore the client will hit timeout and the connection becomes invalid.

image

If you resubscribe to a topic it looks like the WebSocket is re-connected (without having to run an addPluggable command).

Therefore this leaves the final piece of the puzzle, how do we check the state of the client so that we can cleanly handle having to resubscribe to all relevant topics?

@mevert
Copy link

mevert commented Sep 17, 2019

I think that we have similar issue (using aws-amplify v. 1.1.40
). For example, if I subscribe to two topics:

subscriptions = PubSub.subscribe([‘topic1’, ‘topic2’]).subscribe({
      next: data => setMessage(JSON.stringify(data, null, 2)),
      error: error => setMessage(JSON.stringify(error, null, 2)),
      close: () => setMessage('Done'),
    })

And then

subscriptions.unsubscribe()

When I try to subscribe again to ‘topic1’, I can no longer receive its messages. What is the recommended way to subscribe topics again with aws-amplify? @elorzafe ?

Edit: fixed typing error in my example.

@mevert
Copy link

mevert commented Sep 17, 2019

I think that we have similar issue (using aws-amplify v. 1.1.40
). For example, if I subscribe to two topics:

subscriptions = PubSub.subscribe(‘topic1’, ‘topic2’).subscribe({
      next: data => setMessage(JSON.stringify(data, null, 2)),
      error: error => setMessage(JSON.stringify(error, null, 2)),
      close: () => setMessage('Done'),
    })

And then

subscriptions.unsubscribe()

When I try to subscribe again to ‘topic1’, I can no longer receive its messages. What is the recommended way to subscribe topics again with aws-amplify? @elorzafe ?

I just noticed that subscribing again to old topics after unsubscribing used to work with aws-amplify v. 1.1.30 but does not work anymore with the latest v. 1.1.40. Is it possible that there is some breaking change between these version? @elorzafe So I will have to use the old version. Edit: Did not get it working again even with 1.1.30 when I deleted my package-lock.json, node_modules and reinstalled everything. Perhaps I had some old version hanging or something... Would be really nice to get this fixed soon.

@elorzafe
Copy link
Contributor

subscriptions = PubSub.subscribe(‘topic1’, ‘topic2’).subscribe({
     next: data => setMessage(JSON.stringify(data, null, 2)),
     error: error => setMessage(JSON.stringify(error, null, 2)),
     close: () => setMessage('Done'),
   })

@mevert topic2 on that case is providerOptions not a second topic. The first parameter of subscribe is a string or string[] it should be like this.

subscriptions = PubSub.subscribe([‘topic1’, ‘topic2’]).subscribe({
      next: data => setMessage(JSON.stringify(data, null, 2)),
      error: error => setMessage(JSON.stringify(error, null, 2)),
      close: () => setMessage('Done'),
    })

@elorzafe
Copy link
Contributor

@kirkryan why do you need the state if the observable is closing the subscription and sending the error? I think is cleaner to handle reconnection logic than having a process that is checking state. Another option could be sending events on Hub that you can handle the resubcription logic.

How did you plan to check the state of the client?

@mevert
Copy link

mevert commented Sep 21, 2019

subscriptions = PubSub.subscribe(‘topic1’, ‘topic2’).subscribe({
     next: data => setMessage(JSON.stringify(data, null, 2)),
     error: error => setMessage(JSON.stringify(error, null, 2)),
     close: () => setMessage('Done'),
   })

@mevert topic2 on that case is providerOptions not a second topic. The first parameter of subscribe is a string or string[] it should be like this.

subscriptions = PubSub.subscribe([‘topic1’, ‘topic2’]).subscribe({
      next: data => setMessage(JSON.stringify(data, null, 2)),
      error: error => setMessage(JSON.stringify(error, null, 2)),
      close: () => setMessage('Done'),
    })

Sorry, I had typo when writing it here. However, were are using string[] in our real case. Any idea that did your previous changes to PubSub affect to this subscription problem since I don't have the same problem with "@aws-amplify/pubsub": "1.1.0" ?

@elorzafe
Copy link
Contributor

@mevert I will look into this

@stale
Copy link

stale bot commented Oct 23, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@nayan27
Copy link

nayan27 commented Oct 25, 2019

Hi,

Is there any progress on this ? I am having a similar issue:

1 - My applicationA subscribe to a few topics
2- My applicationA opens my other applicationB
3- My applicationB does not use Amplify and only perform specific tasks.
4- After about 1-2 minutes (but could be more), applicationB reopens back applicationA
5- Upon foreground, applicationA's subscriptions call their error function with error: "Disconnected, error code 8"

react-native: 0.57.8
aws-amplify: ^1.2.2

How can i handle this ? is there a way to reconnect automatically ?

Thank you

@chrisbonifacio chrisbonifacio removed the to-be-reproduced Used in order for Amplify to reproduce said issue label May 11, 2021
@enriqueavg
Copy link

Hi all,

This is my version: @aws-amplify/pubsub 3.2.27

I see that current version is 3.3.1, but I'm not sure if this version fix the reconnect issue.

Thanks.

@stale
Copy link

stale bot commented Jun 26, 2021

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@hankconn
Copy link

hankconn commented Jun 26, 2021

simpler... this seems to work

// HACK... stupid amazon
(<any>PubSub)._pluggables[0] = new AWSIoTProvider({
  aws_pubsub_region: 'YOUR REGION',
  aws_pubsub_endpoint: 'YOUR ENDPOINT',
});

"aws-amplify": "^4.1.2",

@houmark
Copy link

houmark commented Jun 28, 2021

Still an issue...

@FilipeAleixo
Copy link

Any news on this?

2 similar comments
@enriqueavg
Copy link

Any news on this?

@dylan-chung
Copy link

Any news on this?

@tigerjiang
Copy link

stail an issue

@pieterbergmans
Copy link

I lose connection after just a couple minutes, very unreliable. My version:

"aws-amplify": "^3.4.3"

Desperate for a fix. Please help.

@watanabeshuji
Copy link

Please help me, too.

@talaikis
Copy link

talaikis commented Dec 14, 2021

Latest version - "frequent" (after few idle hours) disconnects when connection is left for longer time.

ConsoleLogger.js:139 [WARN] 31:47.568 MqttOverWSProvider - 6ac43b3e-84a1-486f-b0b3-d818983d6ca5 {
  "errorCode": 8,
  "errorMessage": "AMQJS0008I Socket closed.",
  "uri": "wss://***"
}
(anonymous) @ ConsoleLogger.js:139
(anonymous) @ ConsoleLogger.js:197
(anonymous) @ MqttOverWSProvider.js:184
(anonymous) @ MqttOverWSProvider.js:225
(anonymous) @ paho-mqtt.js:1600
(anonymous) @ paho-mqtt.js:1460
(anonymous) @ paho-mqtt.js:181

>>> {provider: t, error: "Disconnected, error code: 8"}

@pardeshishubham
Copy link

pardeshishubham commented Jan 17, 2022

+1

{"error": "Disconnected, error code: 7", "provider": {"_clientIdObservers": Map {"28d36dc9-f486-474d-a4b6-53998a03e6f5" => [Set]}, "_clientsQueue": {"promises": [Map]}, "_config": {"Auth": [Object], "aws_pubsub_endpoint": "****************************", "aws_pubsub_region": "ap-south-1", "clientId": ""}, "_topicObservers": Map {"***********#" => [Set]}}}

@craigp1231
Copy link

+1 This is still a problem 3 years after the initial issue was raised! Please Fix!

@sammartinez sammartinez assigned stocaaro and unassigned iartemiev Jan 24, 2022
@pardeshishubham
Copy link

pardeshishubham commented Jan 31, 2022

What i did to solve this issue in react-native is, I used Appstate to determine if app is in background. If it's in background remove the pluggable and once became active, add plugable and subscribe back.

import {AppState} from 'react-native';
useEffect
 useEffect(() => {
    AppState.addEventListener("change", _handleAppStateChange);

    return () => {
       AppState.removeEventListener("change", _handleAppStateChange);
    };
}, []);

const _handleAppStateChange = () => {
    console.log("AppState is Change. =>" , AppState.currentState);
    if (AppState.currentState === 'background' || AppState.currentState === 'inactive ') {
      Amplify.PubSub.removePluggable('AWSIoTProvider');
      console.log("AppState is Background.");
    }
    if (AppState.currentState === 'active') {
      Amplify.addPluggable(
        new AWSIoTProvider({
          aws_pubsub_region: 'yourregion',
          aws_pubsub_endpoint:
            'yourpubsubendpointlink',
        }),
      );
      Amplify.PubSub.subscribe(['yourtopicname']
        ,
      ).subscribe({
        next: data => {
          if (data.value) {
            console.log('data', JSON.stringify(data.value));
          }
        },
        error: e => {
          if (e.error === 'Disconnected, error code: 7') {
            console.log('Error => ', e);
         }
        },
        close: () => console.log('Done'),
      });
      console.log("AppState is Active.");
    }
  }

@Shirsendu-Sarkar
Copy link

What i did to solve this issue in react-native is, I used Appstate to determine if app is in background. If it's in background remove the pluggable and once became active, add plugable and subscribe back.

` import {AppState} from 'react-native'; useEffect useEffect(() => { AppState.addEventListener("change", _handleAppStateChange);

return () => {
   AppState.removeEventListener("change", _handleAppStateChange);
};

}, []);

const _handleAppStateChange = () => { console.log("AppState is Change. =>" , AppState.currentState); if (AppState.currentState === 'background' || AppState.currentState === 'inactive ') { Amplify.PubSub.removePluggable('AWSIoTProvider'); console.log("AppState is Background."); } if (AppState.currentState === 'active') { Amplify.addPluggable( new AWSIoTProvider({ aws_pubsub_region: 'yourregion', aws_pubsub_endpoint: 'yourpubsubendpointlink', }), ); Amplify.PubSub.subscribe(['yourtopicname'] , ).subscribe({ next: data => { if (data.value) { console.log('data', JSON.stringify(data.value)); } }, error: e => { if (e.error === 'Disconnected, error code: 7') { console.log('Error => ', e); } }, close: () => console.log('Done'), }); console.log("AppState is Active."); } } `

its working

@leofolive
Copy link

Amazing how this problem has existed for years and still no solution.

@abdallahshaban557
Copy link
Contributor

Hi @LFMAKER - we are getting close to shipping this feature. We will update this GH issue when it is ready!

@samputer
Copy link

samputer commented Sep 2, 2022

Any update on this issue please?

@chrisbonifacio
Copy link
Member

chrisbonifacio commented Sep 2, 2022

Any update on this issue please?

Please follow this PR for updates on the implementation of reconnect. We'll comment here when merged and released.

@stocaaro
Copy link
Member

stocaaro commented Oct 4, 2022

Reconnection is now staged on the next tag in preparation for release in aws-amplify v5. To test against this update install the next tag version of the aws-amplify packages your project is using. eg yarn add aws-amplify@next.

With this change any disrupted connection will attempt to reconnect when possible. Reconnection can be expected to trigger 5 seconds after the resources to reconnect are available. If the network is disrupted in a way that can't be detected, reconnection will be attempted every minute until the connection is recovered.

Note that missed messages will not backfill on recovery. If you need to trigger behavior to catch up missed messaged on recovery, this should be possible to implement using the connection state Hub messages released last month.

@stocaaro
Copy link
Member

Good news. Automated Reconnection is now available on the latest aws-amplify release! Review the updated subscription docs and consider any application behavior you may want to add to best meet your users needs when subscriptions reconnect.

Please review our breaking change guidance before upgrading your application.

To upgrade Amplify to version 5, run the following in your project folder:

yarn add aws-amplify@latest

Check package.json to see if your project uses other @aws-amplify/* packages directly and upgrade them to latest as well.

With this behavior released, I am closing this issue as resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
investigating This issue is being investigated PubSub Related to PubSub category
Projects
None yet
Development

No branches or pull requests