Skip to content

Commit

Permalink
Add spawnedOrFailed (#47)
Browse files Browse the repository at this point in the history
  • Loading branch information
JordanMartinez authored Jul 20, 2023
1 parent 6a4f27c commit d66ec37
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 0 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down
41 changes: 41 additions & 0 deletions src/Node/ChildProcess/Aff.purs
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit d66ec37

Please sign in to comment.