Skip to content

Commit d66ec37

Browse files
Add spawnedOrFailed (#47)
1 parent 6a4f27c commit d66ec37

File tree

2 files changed

+44
-0
lines changed

2 files changed

+44
-0
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ New features:
6161
- spawnFile
6262
- Added unsafe, uncurried API of all ChildProcess-creating functions (#46 by @JordanMartinez)
6363
- Added safe variant of `spawnSync`/`spawnSync'` (#46 by @JordanMartinez)
64+
- Added `Aff`-based `waitSpawned` to safely get `Pid` (#47 by @JordanMartinez)
65+
66+
Blocks until child process either successfully spawns or fails to spawn.
6467

6568
Bugfixes:
6669

src/Node/ChildProcess/Aff.purs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
module Node.ChildProcess.Aff where
2+
3+
import Prelude
4+
5+
import Control.Parallel (parOneOf)
6+
import Data.Either (Either(..))
7+
import Data.Maybe (fromJust)
8+
import Data.Posix (Pid)
9+
import Effect.Aff (Aff, effectCanceler, makeAff)
10+
import Effect.Ref as Ref
11+
import Node.ChildProcess (ChildProcess, pid)
12+
import Node.ChildProcess as CP
13+
import Node.Errors.SystemError (SystemError)
14+
import Node.EventEmitter (once)
15+
import Partial.Unsafe (unsafePartial)
16+
17+
-- | Blocks until either a `spawn` or `error` event is fired.
18+
-- | If a `spawn` event fired, child process was successfully started
19+
-- | and the `pid` of the process can be obtained.
20+
-- | If an `error` event fires, child process was not started successfully.
21+
waitSpawned :: ChildProcess -> Aff (Either SystemError Pid)
22+
waitSpawned cp = parOneOf [ pidOnSpawn, errored ]
23+
where
24+
pidOnSpawn = makeAff \done -> do
25+
ref <- Ref.new mempty
26+
removeListener <- cp # once CP.spawnH do
27+
join $ Ref.read ref
28+
pid' <- pid cp
29+
done $ Right $ Right $ unsafePartial $ fromJust pid'
30+
Ref.write removeListener ref
31+
pure $ effectCanceler do
32+
removeListener
33+
34+
errored = makeAff \done -> do
35+
ref <- Ref.new mempty
36+
removeListener <- cp # once CP.errorH \sysErr -> do
37+
join $ Ref.read ref
38+
done $ Right $ Left sysErr
39+
Ref.write removeListener ref
40+
pure $ effectCanceler do
41+
removeListener

0 commit comments

Comments
 (0)