From 82ff548fbab86295f1a65010e463189b12f03f75 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Thu, 20 Jul 2023 14:36:49 -0700 Subject: [PATCH] Add spawnedOrFailed --- CHANGELOG.md | 3 +++ src/Node/ChildProcess/Aff.purs | 41 ++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 src/Node/ChildProcess/Aff.purs diff --git a/CHANGELOG.md b/CHANGELOG.md index 4637f2a..5711154 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -61,6 +61,9 @@ New features: - spawnFile - Added unsafe, uncurried API of all ChildProcess-creating functions (#46 by @JordanMartinez) - Added safe variant of `spawnSync`/`spawnSync'` (#46 by @JordanMartinez) +- Added `Aff`-based `waitSpawned` to safely get `Pid` (#47 by @JordanMartinez) + + Blocks until child process either successfully spawns or fails to spawn. Bugfixes: diff --git a/src/Node/ChildProcess/Aff.purs b/src/Node/ChildProcess/Aff.purs new file mode 100644 index 0000000..8eac411 --- /dev/null +++ b/src/Node/ChildProcess/Aff.purs @@ -0,0 +1,41 @@ +module Node.ChildProcess.Aff where + +import Prelude + +import Control.Parallel (parOneOf) +import Data.Either (Either(..)) +import Data.Maybe (fromJust) +import Data.Posix (Pid) +import Effect.Aff (Aff, effectCanceler, makeAff) +import Effect.Ref as Ref +import Node.ChildProcess (ChildProcess, pid) +import Node.ChildProcess as CP +import Node.Errors.SystemError (SystemError) +import Node.EventEmitter (once) +import Partial.Unsafe (unsafePartial) + +-- | Blocks until either a `spawn` or `error` event is fired. +-- | If a `spawn` event fired, child process was successfully started +-- | and the `pid` of the process can be obtained. +-- | If an `error` event fires, child process was not started successfully. +waitSpawned :: ChildProcess -> Aff (Either SystemError Pid) +waitSpawned cp = parOneOf [ pidOnSpawn, errored ] + where + pidOnSpawn = makeAff \done -> do + ref <- Ref.new mempty + removeListener <- cp # once CP.spawnH do + join $ Ref.read ref + pid' <- pid cp + done $ Right $ Right $ unsafePartial $ fromJust pid' + Ref.write removeListener ref + pure $ effectCanceler do + removeListener + + errored = makeAff \done -> do + ref <- Ref.new mempty + removeListener <- cp # once CP.errorH \sysErr -> do + join $ Ref.read ref + done $ Right $ Left sysErr + Ref.write removeListener ref + pure $ effectCanceler do + removeListener