Skip to content

Instantly share code, notes, and snippets.

@brantburnett
Last active January 12, 2021 23:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brantburnett/7a562876b1d53015310ce38b69da18d7 to your computer and use it in GitHub Desktop.
Save brantburnett/7a562876b1d53015310ce38b69da18d7 to your computer and use it in GitHub Desktop.
Couchbase SDK 3.x CancellationToken Handling

Proposed Approach

This proposal is to clarify how we handle various cancellation scenarios which may cancel an in-flight operation.

Idempotent Operations (i.e. GET, LookupIn, etc)

Note: Should also include operations related to bootstrap like hello, auth, select bucket, etc.

Phase External Cancellation Timeout Cancellation
Before Sent OperationCanceledException UnambiguousTimeoutException
Waiting For Response OperationCanceledException UnambiguousTimeoutException
Retry Wait OperationCanceledException UnambiguousTimeoutException

Non-Idempotent Operations (i.e. Set, Replace, Touch, etc)

Phase External Cancellation Timeout Cancellation
Before Sent OperationCanceledException UnambiguousTimeoutException
Waiting For Response Wait for success/failure AmbiguousTimeoutException
Retry Wait OperationCanceledException UnambiguousTimeoutException

Of particular note is the handling of external cancellation that occurs while waiting for a response from the server. In this scenario, we don't want to throw an OperationCancelledException immediately because it would be ambiguous whether or not the operation may have been completed. Instead, once the operation is sent to the server, we always wait for a response back from the server (up to the timeout). The success/failure will be returned immediately without further retry attempts.

This is in keeping with the idea of a key/value operation being an atomic operation. However, there may be corner cases where the consumer doesn't want this behavior. In this case, they could use other patterns to enforce instant cancellation.

// Example consumer code that will instantly cancel if that edge case is required

var result = collection.UpsertAsync(key, doc, new UpsertOptions().CancellationToken(cancellationToken));
var tcs = new TaskCompletionSource<bool>();
cancellationToken.Register(() => tcs.SetCancelled(cancellationToken));
await Task.WhenAny(result, tcs.Task);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment