Skip to content
Snippets Groups Projects
Commit 50ee781d authored by David Sehnal's avatar David Sehnal
Browse files

task api

parent 0442d953
Branches
Tags
No related merge requests found
......@@ -12,6 +12,10 @@ async function test() {
console.log(r);
}
function delay(ms: number) {
return new Promise(r => setTimeout(r, ms));
}
function messageTree(root: Progress.Node, prefix = ''): string {
if (!root.children.length) return `${prefix}${root.progress.message}`;
......@@ -20,25 +24,30 @@ function messageTree(root: Progress.Node, prefix = ''): string {
return `${prefix}${root.progress.message}\n${subTree.join('\n')}`;
}
function createTask<T>(delay: number, r: T): Task<T> {
function createTask<T>(delayMs: number, r: T): Task<T> {
return Task.create('delayed', async ctx => {
await new Promise(r => setTimeout(r, delay));
if (ctx.requiresUpdate) await ctx.update({ message: 'hello from delayed...' });
ctx.updateProgress('Processing delayed... ' + r);
await delay(delayMs);
if (ctx.needsYield) await ctx.yield({ message: 'hello from delayed... ' + r });
return r;
});
}
async function testObs() {
const t = Task.create('test o', async ctx => {
await new Promise(r => setTimeout(r, 250));
if (ctx.requiresUpdate) await ctx.update({ message: 'hi! 1' });
await new Promise(r => setTimeout(r, 125));
if (ctx.requiresUpdate) await ctx.update({ message: 'hi! 2' });
await new Promise(r => setTimeout(r, 250));
if (ctx.requiresUpdate) await ctx.update({ message: 'hi! 3' });
const r = await ctx.runChild({ message: 'Running child!' }, createTask(250, 100));
if (ctx.requiresUpdate) await ctx.update({ message: 'Almost done...' });
await delay(250);
if (ctx.needsYield) await ctx.yield({ message: 'hi! 1' });
await delay(125);
if (ctx.needsYield) await ctx.yield({ message: 'hi! 2' });
await delay(250);
if (ctx.needsYield) await ctx.yield('hi! 3');
ctx.updateProgress('Running children...');
const c1 = ctx.runChild(createTask(250, 1));
const c2 = ctx.runChild(createTask(500, 2));
const c3 = ctx.runChild(createTask(750, 3));
const r = await c1 + await c2 + await c3;
if (ctx.needsYield) await ctx.yield({ message: 'Almost done...' });
return r + 1;
});
const r = await Run(t, p => console.log(messageTree(p.root)), 250);
......
......@@ -116,28 +116,38 @@ class ObservableRuntimeContext implements RuntimeContext {
}
}
get requiresUpdate(): boolean {
get needsYield(): boolean {
this.checkAborted();
return now() - this.info.lastUpdated > this.info.updateRateMs;
}
private setProgress(update: Partial<RuntimeContext.ProgressUpdate>) {
private setProgress(update?: string | Partial<RuntimeContext.ProgressUpdate>) {
this.checkAborted();
if (!update) return;
const progress = this.node.progress;
if (typeof update === 'string') {
progress.message = update;
} else {
if (typeof update.canAbort !== 'undefined') progress.canAbort = update.canAbort;
if (typeof update.current !== 'undefined') progress.current = update.current;
if (typeof update.isIndeterminate !== 'undefined') progress.isIndeterminate = update.isIndeterminate;
if (typeof update.max !== 'undefined') progress.max = update.max;
if (typeof update.message !== 'undefined') progress.message = update.message;
}
}
private resume = () => {
this.isExecuting = true;
this.lastScheduledTime = now();
}
update(progress: Partial<RuntimeContext.ProgressUpdate>): Promise<void> {
updateProgress(progress?: string | Partial<RuntimeContext.ProgressUpdate>) {
this.setProgress(progress);
}
yield(progress?: string | Partial<RuntimeContext.ProgressUpdate>): Promise<void> {
this.isExecuting = false;
this.setProgress(progress);
this.info.lastUpdated = now();
......@@ -146,7 +156,7 @@ class ObservableRuntimeContext implements RuntimeContext {
return ImmediateScheduler.last(this.resume);
}
async runChild<T>(progress: Partial<RuntimeContext.ProgressUpdate>, task: Task<T>): Promise<T> {
async runChild<T>(task: Task<T>, progress?: string | Partial<RuntimeContext.ProgressUpdate>): Promise<T> {
this.setProgress(progress);
const node: Progress.Node = { progress: defaultProgress(this.info.taskId, task), children: [] };
const children = this.node.children as Progress.Node[];
......
......@@ -7,12 +7,13 @@
import Task from '../task'
interface RuntimeContext {
readonly requiresUpdate: boolean,
readonly needsYield: boolean,
updateProgress(progress: string | Partial<RuntimeContext.ProgressUpdate>): void,
// Idiomatic usage:
// if (ctx.requiresUpdate) await ctx.update({ ... });
update(progress: Partial<RuntimeContext.ProgressUpdate>): Promise<void>,
// if (ctx.needsYield) await ctx.yield({ ... });
yield(progress?: string | Partial<RuntimeContext.ProgressUpdate>): Promise<void>,
// Force the user to pass the progress so that the progress tree can be kept in a "good state".
runChild<T>(progress: Partial<RuntimeContext.ProgressUpdate>, task: Task<T>): Promise<T>
runChild<T>(task: Task<T>, progress?: string | Partial<RuntimeContext.ProgressUpdate>): Promise<T>
}
namespace RuntimeContext {
......
......@@ -10,9 +10,10 @@ import RuntimeContext from './runtime-context'
const voidPromise = Promise.resolve(void 0);
class SynchronousRuntimeContext implements RuntimeContext {
requiresUpdate: boolean = false;
update(progress: Partial<RuntimeContext.ProgressUpdate>): Promise<void> { return voidPromise; }
runChild<T>(progress: Partial<RuntimeContext.ProgressUpdate>, task: Task<T>): Promise<T> { return ExecuteSynchronous(task); }
needsYield: boolean = false;
updateProgress(progress: string | Partial<RuntimeContext.ProgressUpdate>): void { }
yield(progress?: string | Partial<RuntimeContext.ProgressUpdate>): Promise<void> { return voidPromise; }
runChild<T>(task: Task<T>, progress?: string | Partial<RuntimeContext.ProgressUpdate>): Promise<T> { return ExecuteSynchronous(task); }
}
const SyncRuntimeInstance = new SynchronousRuntimeContext();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment