1. Clone repo & submodules:
❍ git clone https://github.com/gskapka/func-log.git
2. Switch into directory:
❍ cd func-log
3. Install dependencies:
❍ npm install
4. Run tests:
❍ node why-log-twice
❍ Expected output:
`Proc 1 log # 1`
`Proc 1 log # 2`
`Proc 1 log # 3`
`Proc 1 log # 4`
`Proc 2 log # 1`
`Proc 2 log # 2`
`Proc 2 log # 3`
`Proc 2 log # 4`
`Proc 1 log # 9`
`Proc 1 log # 10`
`Proc 1 log # 11`
`Proc 1 log # 12`
`Proc 1 log # 13`
`Proc 1 log # 14`
`Proc 1 log # 15`
`All procs have finished!`
❍ Actual output:
`Proc 1 log # 1`
`Proc 1 log # 2`
`Proc 1 log # 3`
`Proc 1 log # 4`
`Proc 2 log # 1`
`Proc 1 log # 6` // <-- These should not be logged
`Proc 2 log # 2`
`Proc 1 log # 7`
`Proc 2 log # 3`
`Proc 1 log # 8`
`Proc 2 log # 4`
`Proc 1 log # 9`
`Proc 1 log # 10` // <-- now it's logging twice! :confounded:
`Proc 1 log # 10`
`Proc 2 log # 6`
`Proc 1 log # 11`
`Proc 1 log # 11`
`Proc 2 log # 7`
`Proc 1 log # 12`
`Proc 1 log # 12`
`Proc 2 log # 8`
`Proc 1 log # 13`
`Proc 1 log # 13`
`Proc 2 log # 9`
`Proc 1 log # 14`
`Proc 1 log # 14`
`Proc 2 log # 10`
`All procs have finished!`
Obviously to have javascript fire up two child processes and then follow their stdout
's for a time, logging as they streams, switching between them at will is super easy to do. Imperatively. It's also really ugly, & stateful and just urgh. So I'm trying to do it purely, and have built up the computation using the Task
monad from folktale (the old one, that is), threading through a stateful object by hand like a chump:
// main _ :: Task error {childProcs}
const main = startProc1({})
.chain(logUntilProc1IsReady)
.chain(startProc2)
.chain(logUntilProc2IsReady)
.chain(logUntilProc1IsFinished)
Much prettier. It would be much better too, if it worked - help! 😵
Here is the logging function:
// logStreamUntil :: int -> (a -> bool) -> proc -> string -> Task error State () {childProcs}
const logStreamUntil = curry((predFunc, procName, procObj) =>
new Task ((_, res) => {
const proc = procObj[procName]
const logUntilPred = data =>
predFunc(data)
? (rmAllListeners(proc), res(procObj))
: console.log(data)
proc.stdout.on('data', logUntilPred)
}))
And here is the rmAllListeners
function:
// rmAllListeners :: childProc -> childProc
const rmAllListeners = proc => (proc.removeAllListeners(), proc.stdout.unref())
Which latter is clearly the issue. Listeners, despite being namespaced and supposedly obliterated by the above, are not being. Why?
🔲 Make it.
🔲 Make it work.
✅ Fail at figuring out why it doesn't work.
🔲 Ask other people to make it work.