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

Race Condition with Multiple Stream Methods #3

Closed
paulquinn opened this issue Feb 4, 2020 · 1 comment · Fixed by #4
Closed

Race Condition with Multiple Stream Methods #3

paulquinn opened this issue Feb 4, 2020 · 1 comment · Fixed by #4

Comments

@paulquinn
Copy link
Contributor

I can successfully connect to my server hubs with streaming methods using C# and Typescript clients. However, using this package I get an exception.

Setup

I have two subsequent streaming methods declared:

var messageStream1 = this.connection.stream("serverStreamingMethod1", args: []);
var messageStream2 = this.connection.stream("serverStreamingMethod2", args: []);
  • Logging is also turned on in HttpConnectionOptions.
  • The Flutter device is Web and Android.

Outcome

  • the first call succeeds, messageStream1 is a stream
  • the second call fails, messageStream2 is null
  • the error message "Bad state: Future already completed" is written to the output stream
  • on the server, both the invocations were successfully completed (verified through logging)
  • the signalr client is receiving the messages from both methods (verified though multiple
    "(WebSockets transport) sending data. String data of length 'XXX'." messages with the correct lengths), though the messages aren't being passed to the second stream (as it's null).
  • it makes no difference which order the calls are in

Diagnosis

I've dug/stepped through the code and the error seems to be in http_connection.dart. The Future the error message (Bad state: Future already completed) is complaining about is the _sendBufferedData one returned at the end of the void _bufferData(dynamic data) method (this can be verified by adding a print(_sendBufferedData.isCompleted) statement when using multiple streaming methods. I'm not sure why this is the case (comparing to the TS client code) - but it looks like the buffer is being sent (and that operation not being completed) while other data is being added to the buffer.

Fix

The fix is easy... adding a guard around the _sendBufferedData.complete(); call in the _bufferData method fixes the issue, ie:

if(!_sendBufferedData.isCompleted) {
      _sendBufferedData.complete();
}

...this makes general sense as it means that the _buffer actually buffers data until the last buffered contents have been send successfully in the send loop. I'm not sure why that guard isn't in the TS client, though it seems to work without it...

I've tested this via Flutter Web and Android and it seems to work.

If you're open to a pull request, I can do that.

@jamiewest
Copy link
Owner

Thank you for your detailed issue, a PR would be greatly appreciated!

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

Successfully merging a pull request may close this issue.

2 participants