konsultaner / connectanum-dart

This is a WAMP client (Web Application Messaging Protocol) implementation for the dart language and flutter projects.
MIT License
22 stars 14 forks source link

Support for dynamic reconnectTime in method `connect` #18

Closed jiajun-ifanr closed 3 years ago

jiajun-ifanr commented 3 years ago

Would it be good to support dynamic reconnectTime when calling the connect function?

For instance there is a scenario that one needs to retry 10 times when the network is suddenly disconnected.

The initial reconnectTime is set to 1 second. However in each retry this reconnectTime is increased by 1s.

For example, it will only take 1 second in the first retry. In the next retry it will take 2s. In the nth retry, it will take nth seconds.

And if possible, this reconnectTime is better to be set by users who pass a function to dynamically calculate it.

Currently from what I read, the reconnectTime can be set once only. Is there a way to do this?

konsultaner commented 3 years ago

I'll think about it. Seems like a good idea.

konsultaner commented 3 years ago

@jiajun-ifanr I'm on it! Havn't had time to work on this yet. I hope you can wait a little longer

jiajun-ifanr commented 3 years ago

@jiajun-ifanr I'm on it! Havn't had time to work on this yet. I hope you can wait a little longer

No problem! Thank you!

konsultaner commented 3 years ago

@jiajun-ifanr could you try this:

https://github.com/konsultaner/connectanum-dart/blob/c21eb2a9cf68d1540d7acd33cb46ecf3da165d81/example/main.dart#L22

jiajun-ifanr commented 3 years ago

@konsultaner I tried with the above example, but it seems like it will reconnect only when a session is being initialized. Also when a function is passed to _client.onNextTryToReconnect.listen, and while it is reconnecting, the function doesn't execute.

I want retries are made when a connection is ongoing and very suddenly the network is disconnected due to some network issues (e.g. connection lost / network change).

Is there any way to detect if the connection is lost and then retry connection?

konsultaner commented 3 years ago

What transport do you use? Actually it should also work on connection loss.

https://github.com/konsultaner/connectanum-dart/blob/a1de7e3562514f67ebe47a899fffb9ab5b104efb/lib/src/client.dart#L88

konsultaner commented 3 years ago

No, you're right.. it does not push the event...

konsultaner commented 3 years ago

I added a quick fix. but I need to write some tests on it... Should work if you use the latest master

jiajun-ifanr commented 3 years ago

Looks like it works. Thanks again!

jiajun-ifanr commented 3 years ago

Hi @konsultaner , I find that after the client is reconnected, it doesn't seem to auto resubscribe to what it has already subscribed to. That's to say, it doesn't listen to data changes again.

Please take a glance at the below code as an example. It has a class called Wamp and it is first instantiated and connected to our server on page load. There's a Subscribe button and when you click on it, it will subscribe to a topic.

Here's a scenario where the network is suddenly disconnected (for e.g. 40 seconds). Then the network is back online, and the client begins to retry. Once it is successfully reconnected, it is supposed to listen data changes again. But it isn't.

Also when I click the Subscribe button again, a Bad state: No element exception is thrown. Any chance to get it worked?


import 'package:flutter/material.dart';
import 'package:connectanum/connectanum.dart';
import 'package:connectanum/json.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: Home(),
    );
  }
}

class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  Wamp wamp = new Wamp();

  @override
  void initState() {
    super.initState();
    wamp.connect();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Test App'),
      ),
      body: Center(
          child: RaisedButton(
        onPressed: () {
          wamp.subscribe();
        },
        child: Text('Subscribe'),
      )),
    );
  }
}

class Wamp {
  Client client;
  Session session;

  void connect() async {
    String url =
        'wss://a4d2d62965ddb57fa4d6.ws.myminapp.com/ws/hydrogen/?x-hydrogen-client-id=a4d2d62965ddb57fa4d6&x-hydrogen-env-id=f1eeb28c9552d4c83df1&authorization=Hydrogen-r1%204prp5lsv9ox8n8r4y6ux6hwuguf9r8fg';

    client = Client(
      realm: 'com.ifanrcloud',
      transport: WebSocketTransport(
        url,
        new Serializer(),
        WebSocketSerialization.SERIALIZATION_JSON,
      ),
    );

    try {
      session = await client
          .connect(
            options: ClientConnectOptions(
              reconnectCount: 10,
              reconnectTime: Duration(
                milliseconds: 200,
              ),
            ),
          )
          .first;

      client.onNextTryToReconnect.listen((passedOptions) {
        print('retrying...');
        passedOptions.reconnectTime = Duration(
          milliseconds: passedOptions.reconnectTime.inMilliseconds + 500,
        );
      });
    } on Abort catch (abort) {
      print(abort.message.message);
    }
  }

  void subscribe() async {
    String topic = 'com.ifanrcloud.schema_event.danmu_jiajun.on_create';

    var options = new SubscribeOptions();
    options.addCustomValue("where", (serializerType) => "{}");

    Subscribed subscription = await session.subscribe(topic, options: options);
    print('subscribed successfully...');

    // listen to data change
    // supposed to listen to changes again on reconnection. But it isn't.
    subscription.eventStream.listen(
      (event) {
        print(event.argumentsKeywords.toString());
      },
    );
  }
}

I have tested my JS application counterpart and it works. So it might not be a backend related issue. Is there a workaround for this?

konsultaner commented 3 years ago

Hi @konsultaner , I find that after the client is reconnected, it doesn't seem to auto resubscribe to what it has already subscribed to. That's to say, it doesn't listen to data changes again.

@jiajun-ifanr Yes this is totally expected behaviour. This feature is not implemented yet. You may open a new Issue for this feature if you want it. As soon as I get the time, I will implement it. There will be an additional subscribePermanently as soon as it is implemented. The same issue exists with registrations. They don't stay alive. For now, you may collect your subscriptions and resubscribe them manually in the reconnect event.