From d3eb920fe401fa61ff71c626943fc8d0b4ee7ad5 Mon Sep 17 00:00:00 2001 From: Sandychuang8 Date: Tue, 5 Jun 2018 21:32:06 -0700 Subject: [PATCH] Register for cancellation callback to detect timeout on replicator connect (#1020) (PR #1033) Inability to connect is not reported by TcpClient. There needs to be logic to handle the case where the other side does not respond. --- .../Sync/WebSocketWrapper.cs | 40 ++++++++++++++----- .../ReplicationTest.cs | 4 +- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/src/Couchbase.Lite.Shared/Sync/WebSocketWrapper.cs b/src/Couchbase.Lite.Shared/Sync/WebSocketWrapper.cs index 3877ef640..fdd2bdc44 100644 --- a/src/Couchbase.Lite.Shared/Sync/WebSocketWrapper.cs +++ b/src/Couchbase.Lite.Shared/Sync/WebSocketWrapper.cs @@ -197,21 +197,39 @@ public void Start() } // STEP 2: Open the socket connection to the remote host - var cts = new CancellationTokenSource(); - cts.CancelAfter(ConnectTimeout); - try { - _client.ConnectAsync(_logic.UrlRequest.Host, _logic.UrlRequest.Port).ContinueWith(t => - { - if (!NetworkTaskSuccessful(t)) { - return; - } + var cts = new CancellationTokenSource(ConnectTimeout); + var tok = cts.Token; + + try + { + _client.ConnectAsync(_logic.UrlRequest.Host, _logic.UrlRequest.Port) + .ContinueWith(t => + { + if (!NetworkTaskSuccessful(t)) { + return; + } + _queue.DispatchAsync(StartInternal); - _queue.DispatchAsync(StartInternal); - }, cts.Token); - } catch (Exception e) { + }, tok); + } + catch (Exception e) + { // Yes, unfortunately exceptions can either be thrown here or in the task... DidClose(e); } + + var cancelCallback = default(CancellationTokenRegistration); + cancelCallback = tok.Register(() => + { + if (!_client.Connected) { + // TODO: Should this be transient? + DidClose(new OperationCanceledException()); + _client.Dispose(); + } + + cancelCallback.Dispose(); + cts.Dispose(); + }); }); } diff --git a/src/Couchbase.Lite.Tests.Shared/ReplicationTest.cs b/src/Couchbase.Lite.Tests.Shared/ReplicationTest.cs index 4765bb337..1749cd040 100644 --- a/src/Couchbase.Lite.Tests.Shared/ReplicationTest.cs +++ b/src/Couchbase.Lite.Tests.Shared/ReplicationTest.cs @@ -83,13 +83,13 @@ public async Task TestReplicatorStopsWhenEndpointInvalid() { repl.Start(); var count = 0; - while (count++ <= 20 && repl.Status.Activity != ReplicatorActivityLevel.Stopped) + while (count++ <= 35 && repl.Status.Activity != ReplicatorActivityLevel.Stopped) { WriteLine($"Replication status still {repl.Status.Activity}, waiting for stopped..."); await Task.Delay(500); } - count.Should().BeLessThan(20, "because otherwise the replicator never stopped"); + count.Should().BeLessThan(35, "because otherwise the replicator never stopped"); } }