Accessing doc id from exception 'handler' with 2.0 SDK


#1

I’m trying to get a better understanding of how to use the new Observable features in the 2.0 Java SDK.

From the documentation…

The following example will only go to the replica if a TimeoutException happened (if not the error is passed down):

bucket
.get("id")
.timeout(500, TimeUnit.MILLISECONDS)
.onErrorResumeNext(new Func1<Throwable, Observable<? extends JsonDocument>>() {
    @Override
    public Observable<? extends JsonDocument> call(Throwable throwable) {
        if (throwable instanceof TimeoutException) {
            return bucket.getFromReplica("id", ReplicaMode.ALL);
        }
        return Observable.error(throwable);
    }
});

In the call(Throwable throwable) function, i’d like to be able to access the id of the JsonDocument for which this TimeoutException was thrown – so that a getFromReplica can be issued.

My difficulty is that as I’m new to this style of programming, I can’t quite see how to access the JsonDocument at this point, or how it could be passed down so that it was accessible from the call(Throwable throwable) function.

Cheers,
Tom


#2

Hi,

there are a few ways, but let me point out two of them:

The first one is simpler - but not so “pure”, because you are leaking state. Let’s say you have a method wrapped for a transparent get functionality, you already have the ID in scope and can just reuse it, basically like:

public static Observable<JsonDocument> getWithFallback(final String id) {
    return Observable
        .just(id)
        .flatMap(new Func1<String, Observable<JsonDocument>>() {
            @Override
            public Observable<JsonDocument> call(String id) {
                return bucket.async().get(id);
            }
        })
        .onErrorResumeNext(bucket.async().getFromReplica(id, ReplicaMode.ALL))
        .first()
        .timeout(500, TimeUnit.MILLISECONDS);
}

If you want to be more pure and not share the ID, or maybe sometimes you just don’t have access to it from the outside, you can just ned inside a flatmap:

public static Observable<JsonDocument> getWithFallback(final String id) {
    return Observable
        .just(id)
        .flatMap(new Func1<String, Observable<JsonDocument>>() {
            @Override
            public Observable<JsonDocument> call(String innerId) {
                return bucket
                    .async().get(innerId)
                    .onErrorResumeNext(bucket.async().getFromReplica(innerId, ReplicaMode.ALL))
                    .first();
            }
        })
        .timeout(500, TimeUnit.MILLISECONDS);
}