Use async listener notification to avoid excessive thread stack usage with async operations - Fixes
@@ -4392,20 +4392,36 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V
if (fut != null && !fut.isDone()) {
IgniteInternalFuture<T> f = new GridEmbeddedFuture(fut,
- new IgniteOutClosure<IgniteInternalFuture>() {
- @Override public IgniteInternalFuture<T> apply() {
+ (IgniteOutClosure<IgniteInternalFuture>)() -> {
+ GridFutureAdapter resFut = new GridFutureAdapter();
+
+ ctx.kernalContext().closure().runLocalSafe(() -> {
+ IgniteInternalFuture fut0;
+
if (ctx.kernalContext().isStopping())
- return new GridFinishedFuture<>(
+ fut0 = new GridFinishedFuture<>(
new IgniteCheckedException("Operation has been cancelled (node is stopping)."));
-
+ else {
try {
- return op.op(tx0, opCtx).chain(clo);
+ fut0 = op.op(tx0, opCtx).chain(clo);
}
finally {
// It is necessary to clear tx context in this thread as well.
ctx.shared().txContextReset();
}
}
+
+ fut0.listen((IgniteInClosure<IgniteInternalFuture>)fut01 -> {
+ try {
+ resFut.onDone(fut01.get());
+ }
+ catch (Throwable ex) {
+ resFut.onDone(ex);
+ }
+ });
+ }, true);
+
+ return resFut;
});
saveFuture(holder, f, retry);
