chunked.ts 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
  1. /**
  2. * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author David Sehnal <david.sehnal@gmail.com>
  5. */
  6. import { now } from './now'
  7. import { RuntimeContext } from '../execution/runtime-context'
  8. type UniformlyChunkedFn<S> = (chunkSize: number, state: S) => number
  9. type ChunkedSubtaskProvider<S> = (ctx: RuntimeContext, state: S) => Promise<S>
  10. function ChunkedSubtask<S>(initialChunk: number, f: UniformlyChunkedFn<S>,
  11. update: (ctx: RuntimeContext, state: S, processed: number) => Promise<void> | void): ChunkedSubtaskProvider<S> {
  12. return async (ctx: RuntimeContext, state: S) => {
  13. let chunkSize = Math.max(initialChunk, 0);
  14. let globalProcessed = 0, globalTime = 0;
  15. if (ctx.isSynchronous) {
  16. f(Number.MAX_SAFE_INTEGER, state);
  17. return state;
  18. }
  19. let start = now();
  20. let lastSize = 0, currentTime = 0;
  21. while ((lastSize = f(chunkSize, state)) > 0) {
  22. globalProcessed += lastSize;
  23. const delta = now() - start;
  24. currentTime += delta;
  25. globalTime += delta;
  26. if (ctx.shouldUpdate) {
  27. await update(ctx, state, globalProcessed);
  28. chunkSize = Math.round(currentTime * globalProcessed / globalTime) + 1;
  29. start = now();
  30. currentTime = 0;
  31. }
  32. }
  33. if (ctx.shouldUpdate) {
  34. await update(ctx, state, globalProcessed);
  35. }
  36. return state;
  37. }
  38. }
  39. export { ChunkedSubtask }