util.ts 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. type ExecutionContext = {
  2. run<T>(c: Computation<T>, params?: { updateRateMs: number }): Promise<T>,
  3. subscribe(o: (p: string, compId: number) => void): void
  4. }
  5. namespace ExecutionContext {
  6. // export interface Synchronous extends ExecutionContext {
  7. // run<T>(c: Computation<T>, params?: { updateRateMs: number }): Promise<T>,
  8. // }
  9. // export interface Observable extends ExecutionContext {
  10. // run<T>(c: Computation<T>, params?: { updateRateMs: number }): Promise<T>,
  11. // }
  12. export const Sync: ExecutionContext = 0 as any;
  13. }
  14. interface RuntimeContext extends ExecutionContext {
  15. yield(name: string): Promise<void> | void
  16. }
  17. // if no context is specified, use the synchronous one.
  18. type Computation<T> = { (ctx?: RuntimeContext): Promise<T>, _id: number }
  19. function create<T>(c: (ctx: RuntimeContext) => Promise<T>): Computation<T> { return 0 as any; }
  20. function constant<T>(c: T) { return create(async ctx => c); }
  21. type MultistepFn<P, T> = (params: P, step: (s: number) => Promise<void> | void, ctx: RuntimeContext) => Promise<T>
  22. type ComputationProvider<P, T> = (params: P) => Computation<T>
  23. function MultistepComputation<P, T>(name: string, steps: string[], f: MultistepFn<P, T>): ComputationProvider<P, T> {
  24. return params => create(async ctx => f(params, n => ctx.yield(steps[n]), ctx));
  25. }
  26. // if total count is specified, could automatically provide percentage
  27. type UniformlyChunkedFn<S> = (chunkSize: number, state: S, totalCount?: number) => number
  28. type UniformlyChunkedProvider<S> = (ctx: RuntimeContext, state: S) => Promise<S>
  29. function UniformlyChunked<S>(label: string, initialChunk: number, f: UniformlyChunkedFn<S>): UniformlyChunkedProvider<S> {
  30. // TODO: track average time required for single element and then determine chunk size based on that.
  31. return 0 as any;
  32. }
  33. type LineReaderState = { str: string, position: number, lines: string[] }
  34. const uniformPart = UniformlyChunked('Reading lines', 1000000, (size, state: LineReaderState) => {
  35. state.position += size;
  36. state.lines.push('');
  37. return 0 /* number of lines read */;
  38. });
  39. function readLines(str: string): Computation<string[]> {
  40. return create(async ctx => {
  41. const state = (await uniformPart(ctx, { str, position: 0, lines: [] }));
  42. return state.lines;
  43. });
  44. }
  45. const prependHiToLines = MultistepComputation('Hi prepend', ['Parse input', 'Prepend Hi'], async (p: string, step, ctx) => {
  46. await step(0);
  47. const lines = await ctx.run(readLines(p));
  48. await step(1);
  49. const ret = lines.map(l => 'Hi ' + l);
  50. return ret;
  51. });
  52. (async function() {
  53. const r = await ExecutionContext.Sync.run(prependHiToLines('1\n2'), { updateRateMs: 150 });
  54. console.log(r)
  55. }())