Browse Source

mol-task: fixed subtask cancellation

David Sehnal 5 years ago
parent
commit
3a6013145e
2 changed files with 12 additions and 7 deletions
  1. 4 4
      src/examples/task.ts
  2. 8 3
      src/mol-task/execution/observable.ts

+ 4 - 4
src/examples/task.ts

@@ -28,9 +28,9 @@ function messageTree(root: Progress.Node, prefix = ''): string {
 
 function createTask<T>(delayMs: number, r: T): Task<T> {
     return Task.create('delayed value ' + r, async ctx => {
-        ctx.update('Processing delayed... ' + r, true);
+        ctx.update(`Processing delayed ${r} after ${delayMs}ms`, true);
         await Scheduler.delay(delayMs);
-        if (ctx.shouldUpdate) await ctx.update({ message: 'hello from delayed... ' });
+        if (ctx.shouldUpdate) await ctx.update({ message: `hello from delayed ${r} ${delayMs}` });
         return r;
     }, () => console.log('On abort called ' + r));
 }
@@ -63,7 +63,7 @@ export function testTree() {
         const r = await c1 + await c2 + await c3;
         if (ctx.shouldUpdate) await ctx.update({ message: 'Almost done...' });
         return r + 1;
-    });
+    }, () => console.log('On abort O'));
 }
 
 export type ChunkedState = { i: number, current: number, total: number }
@@ -115,7 +115,7 @@ async function test() {
         // const r = await Run(testTree(), abortingObserver, 250);
         // console.log(r);
 
-        const m = await ms({ i: 10 }).run(logP);
+        const m = await testTree().run(abortingObserver, 50);
         console.log(m);
     } catch (e) {
         console.error(e);

+ 8 - 3
src/mol-task/execution/observable.ts

@@ -10,7 +10,7 @@ import { Progress } from './progress'
 import { now } from '../../mol-util/now';
 import { Scheduler } from '../util/scheduler'
 import { UserTiming } from '../util/user-timing'
-import { isProductionMode } from '../../mol-util/debug'
+import { isDebugMode } from '../../mol-util/debug'
 
 interface ExposedTask<T> extends Task<T> {
     f: (ctx: RuntimeContext) => Promise<T>,
@@ -101,6 +101,8 @@ async function execute<T>(task: ExposedTask<T>, ctx: ObservableRuntimeContext) {
         return ret;
     } catch (e) {
         if (Task.isAbort(e)) {
+            ctx.isAborted = true;
+
             // wait for all child computations to go thru the abort phase.
             if (ctx.node.children.length > 0) {
                 await new Promise(res => { ctx.onChildrenFinished = res; });
@@ -109,7 +111,7 @@ async function execute<T>(task: ExposedTask<T>, ctx: ObservableRuntimeContext) {
                 task.onAbort();
             }
         }
-        if (!isProductionMode) console.error(e);
+        if (isDebugMode) console.error(e);
         throw e;
     }
 }
@@ -147,6 +149,8 @@ class ObservableRuntimeContext implements RuntimeContext {
     isExecuting = true;
     lastUpdatedTime = 0;
 
+    isAborted?: boolean;
+
     node: Progress.Node;
     info: ProgressInfo;
 
@@ -155,6 +159,7 @@ class ObservableRuntimeContext implements RuntimeContext {
 
     private checkAborted() {
         if (this.info.abortToken.abortRequested) {
+            this.isAborted = true;
             abort(this.info);
         }
     }
@@ -220,7 +225,7 @@ class ObservableRuntimeContext implements RuntimeContext {
                 // need to catch the error here because otherwise
                 // promises for running child tasks in a tree-like computation
                 // will get orphaned and cause "uncaught error in Promise".
-                return void 0 as any;
+                if (this.isAborted) return void 0 as any;
             }
             throw e;
         } finally {