vanadium-archive/java

Cancelling a Watch causes RuntimeException

Closed this issue · 3 comments

We're now using Watch in a bunch of places, but trying to cancel the Watch results in a RuntimeException (not very friendly). @sjamesr @spetrovic77

10-15 20:45:02.867 20580-20925/io.v.android.apps.syncslides E/AndroidRuntime﹕ FATAL EXCEPTION: Thread-1282
Process: io.v.android.apps.syncslides, PID: 20580
java.lang.RuntimeException: Error retrieving next stream element.
at io.v.v23.syncbase.nosql.DatabaseImpl$WatchChangeStreamImpl$1.computeNext(DatabaseImpl.java:286)
at io.v.v23.syncbase.nosql.DatabaseImpl$WatchChangeStreamImpl$1.computeNext(DatabaseImpl.java:271)
at com.google.common.collect.AbstractIterator.tryToComputeNext(AbstractIterator.java:143)
at com.google.common.collect.AbstractIterator.hasNext(AbstractIterator.java:138)
at io.v.android.apps.syncslides.db.CurrentSlideWatcher.watchCurrentSlide(CurrentSlideWatcher.java:112)
at io.v.android.apps.syncslides.db.CurrentSlideWatcher.access$000(CurrentSlideWatcher.java:27)
at io.v.android.apps.syncslides.db.CurrentSlideWatcher$1.run(CurrentSlideWatcher.java:51)
at java.lang.Thread.run(Thread.java:818)
Caused by: io.v.v23.verror.VException: gojni:<rpc.Client>"/@6@wsh@127.0.0.1:52895@@505fcf7050bf9010a02f4f0f60bf4fcf@s@dev.v.io/u/ken.vanadium@gmail.com/android/io.v.android.apps.syncslides@@/syncslides/syncslides".WatchGlob: Canceled: [remote=@6@wsh@127.0.0.1:52895@@505fcf7050bf9010a02f4f0f60bf4fcf@s@dev.v.io/u/ken.vanadium@gmail.com/android/io.v.android.apps.syncslides@@: gojni:<rpc.Client>"/@6@wsh@127.0.0.1:52895@@505fcf7050bf9010a02f4f0f60bf4fcf@s@dev.v.io/u/ken.vanadium@gmail.com/android/io.v.android.apps.syncslides@@/syncslides/syncslides".WatchGlob: Bad protocol or type: failed to decode response: EOF]
at io.v.v23.verror.VExceptionVdlConverter.nativeFromVdlValue(VExceptionVdlConverter.java:70)
at io.v.v23.verror.VExceptionVdlConverter.nativeFromVdlValue(VExceptionVdlConverter.java:22)
at io.v.v23.vom.BinaryDecoder.readValue(BinaryDecoder.java:190)
at io.v.v23.vom.BinaryDecoder.readValueMessage(BinaryDecoder.java:118)
at io.v.v23.vom.BinaryDecoder.decodeValue(BinaryDecoder.java:85)
at io.v.v23.vom.VomUtil.decode(VomUtil.java:110)
at io.v.impl.google.rpc.StreamImpl.nativeRecv(Native Method)
at io.v.impl.google.rpc.StreamImpl.recv(StreamImpl.java:32)
at io.v.impl.google.rpc.ClientCallImpl.recv(ClientCallImpl.java:89)
at io.v.v23.services.watch.GlobWatcherClientImpl$2.recv(GlobWatcherClientImpl.java:67)
at io.v.v23.services.watch.GlobWatcherClientImpl$2.recv(GlobWatcherClientImpl.java:58)
at io.v.v23.syncbase.nosql.DatabaseImpl$WatchChangeStreamImpl$1.computeNext(DatabaseImpl.java:279)
            at io.v.v23.syncbase.nosql.DatabaseImpl$WatchChangeStreamImpl$1.computeNext(DatabaseImpl.java:271)
            at com.google.common.collect.AbstractIterator.tryToComputeNext(AbstractIterator.java:143)
            at com.google.common.collect.AbstractIterator.hasNext(AbstractIterator.java:138)
            at io.v.android.apps.syncslides.db.CurrentSlideWatcher.watchCurrentSlide(CurrentSlideWatcher.java:112)
            at io.v.android.apps.syncslides.db.CurrentSlideWatcher.access$000(CurrentSlideWatcher.java:27)
            at io.v.android.apps.syncslides.db.CurrentSlideWatcher$1.run(CurrentSlideWatcher.java:51)
            at java.lang.Thread.run(Thread.java:818)

Can you link to the code that cancels the watch?

https://vanadium-review.googlesource.com/#/c/16684/2/projects/syncslides/app/src/main/java/io/v/android/apps/syncslides/db/CurrentSlideWatcher.java

public void removeListener(DB.CurrentSlideListener listener) {
mListeners.remove(listener);
if (!hasListeners()) {
mVContext.cancel();
mThread.interrupt();
mThread = null;
mHandler.removeCallbacksAndMessages(null);
}
}

I think a workaround for now would be to call cancel on the stream that you get at line 110 rather than on the VContext. Refactoring the code to do this without races might be a bit tricky.

It's weird to have two ways to cancel the stream. We should make both work or remove one. If we wanted to leave the API as is, we need to change StreamImpl to recognize a VException representing a context cancel as endOfData() and not rethrow.