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

Reconnect logic #691

Open
haf opened this issue Feb 29, 2024 · 7 comments
Open

Reconnect logic #691

haf opened this issue Feb 29, 2024 · 7 comments

Comments

@haf
Copy link

haf commented Feb 29, 2024

There have already been some questions about how to reconnect. My use-case is bi-directional streaming with gRPC; with a connection that is alive for as long as the app is alive (but like we know the OS might/will close connections after a while). I want to make sure the gRPC client reconnects and retries to send unsent messages.

These issues mentioned reconnection behaviour:

I'd like to get an explainer on how exactly to write "some code".

For background, I keep track of the state like this:

      final sendStream = StreamController<AnalyseRequest>(
        onListen: () {
          loggy.debug('LISTEN ON request stream for listing$listingId');
        },
        onCancel: () {
          loggy.debug('CANCEL request stream for listing$listingId');
        },
        onPause: () {
          loggy.debug('PAUSE request stream for listing$listingId');
        },
        onResume: () {
          loggy.debug('RESUME request stream for listing$listingId');
        },
      );

      // kick-start the bi-directional streaming
      final responses = client.analyse(
        sendStream.stream,
        options: CallOptions(compression: const GzipCodec()),
      );

      // listen to the response stream / messages
      // ignore: cancel_subscriptions
      final subscription = responses.listen(
        _onAnalyseResponse(listingId),
        // ignore: avoid_types_on_closure_parameters
        onError: (Object error, StackTrace stackTrace) {
          loggy.error('request stream for listing$listingId error: $error', error, stackTrace);
          _events.sink.addError(error, stackTrace);
        },
      );

      _streams[listingId] = (responses, subscription, sendStream);

Then at some point, due to networks being networks; this gets logged:

flutter: 🐛 16:58:25.540942 DEBUG PROVIDER: StreamingAPIPredictor - CANCEL request stream for listingd55a919c-0e8b-419a-a1e0-a208e97a93b2
flutter: ‼️ 16:58:25.541688 ERROR PROVIDER: StreamingAPIPredictor - request stream for listingd55a919c-0e8b-419a-a1e0-a208e97a93b2 error: gRPC Error (code: 14, codeName: UNAVAILABLE, message: Missing trailers, details: null, rawResponse: null, trailers: {})

version: 3.2.4

The ultimate API for me would be that I can rely on the client to keep this stream open; how exactly this would work, I'm not sure, so I'm asking you.

Repro steps

  1. set up a bidirectional stream
  2. sleep the app
  3. switch back to the app

OR

  1. same
  2. switch networks
  3. try to send a request

Expected result: either that we can resume the connection (incl its state server-side with its python gRPC impl); or that there's some guidance on how to build resilient gRPC clients and hooks for me to hook into to resume.

Actual result: the app hangs, because the socket is dead and I don't see how to reconnect it

@vhunkalo
Copy link

@haf did you resolve this issue somehow?
have similar problem with bi-directional gRPC stream

@haf
Copy link
Author

haf commented Apr 30, 2024

No, no solution, still need one.

@vhunkalo
Copy link

as I correctly understand, you also need to know status of this stream to make either reconnect or close, yes? @haf

@vhunkalo
Copy link

it is inside http2 library, but it's hidden
https://github.com/dart-lang/http2/blob/master/lib/src/streams/stream_handler.dart

@haf
Copy link
Author

haf commented Apr 30, 2024

No I don't believe in statuses; if I try to send and get timeouts or ECONNRST or similar back, then I want to try to reconnect.

@vhunkalo
Copy link

how you handle this issue right now?
with connectivity checker and forcefully close connection when change?

@haf
Copy link
Author

haf commented Apr 30, 2024

I moved away from streaming for this reason; I don't have a solution yet. But if I really need one I'm going to dig into this library and maybe I'd wrap the channel or make it a factory method instead of an instance (if it needs to be recreated)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants