Uploaded image for project: 'Couchbase .NET client library'
  1. Couchbase .NET client library
  2. NCBC-900

Switching from asynchronous to synchronous context causes some bucket methods to hang

    XMLWordPrintable

Details

    • Bug
    • Status: Resolved
    • Critical
    • Resolution: Fixed
    • 2.1.0
    • 2.2.2
    • library
    • Server 3.0.3 on Windows 2012

    Description

      The following asynchronous methods never complete when called from a synchronous context:
      IBucket.ExistsAsync()
      IBucket.QueryAsync() with a query containing StartKey and EndKey

      Example:
      bool Exists(string id)

      { return bucket.ExistsAsync(id).ConfigureAwait(false).GetAwaiter().GetResult(); }

      The symptom does not occur when run from unit tests, but happens with 100% regularity inside an ASP.NET WebApi service. No exceptions are thrown, the task just never returns.

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          Scotch Scotch added a comment -

          I created a simple ASP.NET test application to demonstrate the problem behavior. Edit the Repository/CouchbaseRepository.cs file and set a valid bucket and server name at the top. Then toggle whether line 89 or 90 is commented out (one uses Exists and the other ExistsAsync). The async one never returns.

          To exercise it, use curl or postman to make the following WebApi request:

          POST /documents HTTP/1.1
          Host: localhost:46062
          Accept: text/plain
          Content-Type: text/plain
          Cache-Control: no-cache

          This is my text.

          Scotch Scotch added a comment - I created a simple ASP.NET test application to demonstrate the problem behavior. Edit the Repository/CouchbaseRepository.cs file and set a valid bucket and server name at the top. Then toggle whether line 89 or 90 is commented out (one uses Exists and the other ExistsAsync). The async one never returns. To exercise it, use curl or postman to make the following WebApi request: POST /documents HTTP/1.1 Host: localhost:46062 Accept: text/plain Content-Type: text/plain Cache-Control: no-cache This is my text.
          Scotch Scotch added a comment -

          QueryAsync<>() exhibits the same behavior as ExistAsync(). GetAsync<>(), UpsertAsync(), and RemoveAsync() work fine.

          Scotch Scotch added a comment - QueryAsync<>() exhibits the same behavior as ExistAsync(). GetAsync<>(), UpsertAsync(), and RemoveAsync() work fine.
          jmorris Jeff Morris added a comment - - edited

          I am going to flag this as "won't fix" for a couple of reasons:

          However, it's possible that in a future release the internal implementation of ExistsAsync may change which has a side effect the issue resolving itself.

          jmorris Jeff Morris added a comment - - edited I am going to flag this as "won't fix" for a couple of reasons: The method calls that cause the behavior according the documentation are intended to be used by the compiler only: https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.taskawaiter.aspx The work around is to use the synchronous equivalent method (Exists vs. ExistsAsync) if synchronous behavior is wanted. The Exists methods wrap observe, so another work around it to call observe and check if the keys exists. However, it's possible that in a future release the internal implementation of ExistsAsync may change which has a side effect the issue resolving itself.
          Scotch Scotch added a comment -

          Please consider re-opening this bug report.

          >>The method calls that cause the behavior according the documentation are intended to be used by the compiler only
          GetAwaiter().AwaitResult() is a slightly more permissive version of .Result(), which is fully supported for end user consumption by the .NET Framework. If you wish, use that instead of my AwaitResult() extension as the outcome is identical.

          >>The work around is to use the synchronous equivalent method (Exists vs. ExistsAsync) if synchronous behavior is wanted.
          Asynchronous behavior is desired here, but that doesn't mean every method will be async. There are no ToStringAsync() methods, for example. By not addressing this you are saying that if any part of the call stack is synchronous then the call to Couchbase MUST be synchronous as well. That's a pretty major limitation that doesn't exist with any other TAP-capable library (HttpClient, ADO, Oracle, NEST).

          >>The Exists methods wrap observe, so another work around it to call observe and check if the keys exists.
          If the only method I can safely call is synchronous Exists(), then there isn't much point in observing as I already have the result.

          Scotch Scotch added a comment - Please consider re-opening this bug report. >>The method calls that cause the behavior according the documentation are intended to be used by the compiler only GetAwaiter().AwaitResult() is a slightly more permissive version of .Result(), which is fully supported for end user consumption by the .NET Framework. If you wish, use that instead of my AwaitResult() extension as the outcome is identical. >>The work around is to use the synchronous equivalent method (Exists vs. ExistsAsync) if synchronous behavior is wanted. Asynchronous behavior is desired here, but that doesn't mean every method will be async. There are no ToStringAsync() methods, for example. By not addressing this you are saying that if any part of the call stack is synchronous then the call to Couchbase MUST be synchronous as well. That's a pretty major limitation that doesn't exist with any other TAP-capable library (HttpClient, ADO, Oracle, NEST). >>The Exists methods wrap observe, so another work around it to call observe and check if the keys exists. If the only method I can safely call is synchronous Exists(), then there isn't much point in observing as I already have the result.
          jmorris Jeff Morris added a comment -

          Will revisit after 2.2.0.

          jmorris Jeff Morris added a comment - Will revisit after 2.2.0.
          Scotch Scotch added a comment -

          Thanks Jeff, please let me know if there's anything I can do to help.

          Scotch Scotch added a comment - Thanks Jeff, please let me know if there's anything I can do to help.

          People

            jmorris Jeff Morris
            Scotch Scotch
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes

                PagerDuty