I'm developping a cache wrapper for my service API.Following the idea of Singleton, I used SharedData.LocalLock to prevent repeated cache reload. Finally the code came out as a bunch of nested callbacks as below:
--------------------------------------------------------------------------------
// The cache wrapper
public Future<List<Client>> getClients() {
Promise<List<Client>> promise = Promise.promise();
cacheManager.getClients().onComplete(ar1 -> {
if (ar1.failed()) {
sharedData.getLocalLock(LOCK_NAME).onFailure(e -> {
promise.fail(e);
}).onSuccess(lock -> { // make sure the lock is propertly released!!!!!
cacheManager.getClients().onComplete(ar2 -> {
if (ar2.failed()) {
clientService.getClients().onComplete(ar3 -> {
if (ar3.failed()) {
promise.fail(ar3.cause());
lock.release();
} else {
cacheManager.updateClients(ar3.result()).onComplete(ar4 -> {
promise.complete(ar3.result());
lock.release();
});
}
});
} else {
promise.complete(ar2.result());
lock.release();
}
});
});
} else {
promise.complete(ar1.result());
}
});
return promise.future();
}
--------------------------------------------------------------------------------
I'm quite worried about the async lock used in the example above. If some APIs failed expectedly, it may result in a dead lock, right? the lock example from vertx doc was quite simple, I haven't found any guide on exception handling yet. is there any advice?
BTW, all my async APIs were implemented like below. Since not all exceptions get captured, the promise may remain uncompleted for ever. I think it's a big portential risk. what can I do? I hate to put try-catch everywhere.
---------------------------------------------------------------------------------
Future<T> myAsyncAPI() {
Promise<T> promise = Promise.promise();
// here's the code to perform async tasks and finally completes the promise.
// but what if exceptions occurs? Divide-By-Zero-Exception, Null-Pointer-Exception..
return promise.future();
}
---------------------------------------------------------------------------------