Mixing sync and async giving problems

#1

I’m trying to mix using an async bucket and sync bucket together.
I’m using the java sdk 2.1.4

When I try to get the results synchronously (in the middle of the async call), the sync calls occasionally gives me a timeout.
I did sniff the wire and the result did come back, it’s just the client did not process it.
I can make it work by not reusing the cluster object (I create 2 clusters each with the same hosts, then have 1 cluster one the sync bucket and the other cluster open the async bucket).

I realize mixing the sync and async is pretty weird, and we will probably refactor it at some point, but for now we would like to get this working.

Thanks for the help
-Kevin

Here is the junit test. This test assumes you have 2 buckets (bucket1 and bucket2). Bucket1 has a single doc (with a key of key1). Bucket2 can be empty.

    import org.junit.Before;
    import org.junit.Test;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import com.couchbase.client.java.AsyncBucket;
    import com.couchbase.client.java.Bucket;
    import com.couchbase.client.java.Cluster;
    import com.couchbase.client.java.CouchbaseCluster;
    import com.couchbase.client.java.document.JsonDocument;
    
    import rx.Observable;
    
public class CouchSyncTest {

  private static final Logger LOGGER = LoggerFactory.getLogger(CouchSyncTest.class);

Cluster cluster;
AsyncBucket aBucket;
Bucket bucket;
@Before
public void setup() {
  String[] nodes = {
        ....
  };
  cluster = CouchbaseCluster.create(nodes);
  aBucket =  cluster.openBucket("bucket1").async();
  bucket =  cluster.openBucket("bucket2");

}


private Object adjustDoc(JsonDocument parentDoc) {
  // These keys actually come from parentDoc.
  String[] ids = {
      "key1",
      "key2",
      "key3",
      "key4",
      "key5",
      "key6",
      "key7",
      "key8",
      "key9",
      "key10",
      "key11",
      "key12",
      "key13",
      "key14",
      "key15",
      "key16",
      "key17",
      "key18",
      "key19",        
      "key20"
  };
  for (String i: ids) {
    try {
      JsonDocument jd = bucket.get(i);
      // Adjust parent doc with results from this doc
      LOGGER.info("got something");
    } catch (Exception e) {
      LOGGER.info("got the exception",e);
    }
  }

  return parentDoc;
}


@Test
public void doesntWork() {
  String key="key1";
  Observable<Object> ob = Observable.just(key).flatMap(aBucket::get).map(o -> adjustDoc(o));
  ob.subscribe();
  try {
    Thread.sleep(10000);
  } catch (Exception e) {}
}
}
#2

You are doing blocking calls inside a non-blocking async stream, in a map function. That’s a bad idea©

You can use sync bucket in parallel to an async bucket, separately, but mixing the two together isn’t possible and will lead to blocking and timeouts, as you saw.

What I mean by separately is more along the lines of:

//this is OK
JsonObject updatedContent = JsonObject.emtpy(); //or something more relevant
JsonDocument docUpdated = JsonDocument.create("key1", updatedContent);
aBucket.upsert(docUpdated).subscribe(); //we just update in a fire and forget fashion

JsonDocument otherDoc = bucket.get("key2"); //do something with the other doc

As a side note, on your test you could have directly used get without Observable.just (for a single key):

Observable<Object> ob = aBucket.get(key)
   //still a bad idea
   .map(o -> adjustDoc(o));
#3

Simon,
Thanks for the info. I was hoping we could get away without too much refactoring of the code, but I guess we will have to do it.

Thanks again for the help
-Kevin