2
 Observable
        .from(couchbaseDocuments)
        .subscribeOn(Schedulers.io())
        .flatMap(docToInsert->asyncBucket.insert(docToInsert))
        .retryWhen(RetryBuilder.anyOf(TemporaryFailureException.class).delay(Delay.exponential(TimeUnit.MILLISECONDS, 5)).max(3).build())
        .map(doc->convertToJava(JsonObject.fromJson(doc.content()),CouchbaseEntity.class).getId())
        .toBlocking()
        .forEach(id->insertedIds.add(id));

Req :

  1. Bulk insert documents in couchbase of a certain type.
  2. Create another document which will have just the ids of the docs we inserted in the first step
  3. If first steps fails at some id we stop inserting, the 2nd doc then should have only those ids which were inserted till the exception occured
  4. The call is synchronous

I am new to RxJava. I wrote the above react code however it seems that I have not clearly understood some concepts. My idea was that the forEach at the end will always get the emitted item and if an exception occurs I will catch it and then later use the insertedIds list to create the 2nd documents. However the list always has all the ids which doesnt fulfill my reqs.

Can anyone please explain whats wrong with the code and how I could achieve the above reqs?

humbleCoder
  • 667
  • 14
  • 27

1 Answers1

2

the retry methods will resubscribe to the upstream Observable.

In your case that means subscribing to couchbaseDocuments and potentially attempting to re-insert docs that have already successfully been inserted.

Instead of retrying the entire stream again, you might prefer to just retry the insert that failed:

 Observable
        .from(couchbaseDocuments)
        .subscribeOn(Schedulers.io())
        .flatMap(docToInsert->asyncBucket.insert(docToInsert).retryWhen(...))
        .map(doc->convertToJava(JsonObject.fromJson(doc.content()),CouchbaseEntity.class).getId())
        .toBlocking()
        .forEach(id->insertedIds.add(id));

Essentially: you had to move a single parenthesis.

Andrew G
  • 2,596
  • 2
  • 19
  • 26
  • Thanks I think it works. One more question instead of forEach if I use subscribe will it have the same effect?. With subscribe I also get the onError method where can handle the exceptions. – humbleCoder Jul 24 '18 at 05:23
  • 1
    yes. It's more idiomatic to use subscribe. If you look at the source, forEach calls subscribe. Your retryWhen will swallow any error it doesn't rethrow. Yes, you can handle uncaught exceptions in onError, however you will not see any that are handled in retryWhen, only unhandled exceptions, e.g. from your retry code itself rethrowing, convertToJava or other exceptions. – Andrew G Jul 24 '18 at 12:21
  • Ok I just checked the subscribe for BlockingObservable is marked as @Beta. Whats the reason for it? – humbleCoder Jul 25 '18 at 05:18
  • 1
    Update to the latest version of RxJava 1, or preferably 2. – Andrew G Jul 25 '18 at 12:47