concurrent.js 1.1 KB

123456789101112131415161718192021222324252627282930313233
  1. import {createDeferred} from '../utils/deferred.js';
  2. // When using multiple `.readable()`/`.writable()`/`.duplex()`, `final` and `destroy` should wait for other streams
  3. export const initializeConcurrentStreams = () => ({
  4. readableDestroy: new WeakMap(),
  5. writableFinal: new WeakMap(),
  6. writableDestroy: new WeakMap(),
  7. });
  8. // Each file descriptor + `waitName` has its own array of promises.
  9. // Each promise is a single `.readable()`/`.writable()`/`.duplex()` call.
  10. export const addConcurrentStream = (concurrentStreams, stream, waitName) => {
  11. const weakMap = concurrentStreams[waitName];
  12. if (!weakMap.has(stream)) {
  13. weakMap.set(stream, []);
  14. }
  15. const promises = weakMap.get(stream);
  16. const promise = createDeferred();
  17. promises.push(promise);
  18. const resolve = promise.resolve.bind(promise);
  19. return {resolve, promises};
  20. };
  21. // Wait for other streams, but stop waiting when subprocess ends
  22. export const waitForConcurrentStreams = async ({resolve, promises}, subprocess) => {
  23. resolve();
  24. const [isSubprocessExit] = await Promise.race([
  25. Promise.allSettled([true, subprocess]),
  26. Promise.all([false, ...promises]),
  27. ]);
  28. return !isSubprocessExit;
  29. };