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

task api

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