Processes
Effection 3.0 does not ship with a process library out of the box, but what it does do is make writing resources so easy, that you can do it yourself.
Operating system processes are a perfect candidate for modeling as a resource because they match the resource criteria which are:
- They are long running
- We want to be able to interact with them while they are running.
This section provides a sketch of how you might create a "command" resource for both Deno and Node that will run an operating system command, and then make sure that no matter what happens, that command is shut down properly.
// use-command
import { action, resource, spawn, suspend, createSignal } from "effection";
import { spawn as spawnChild} from "node:child_process";
export function useCommand(...args) {
return resource(function*(provide) {
// spawn the OS process
let proc = spawnChild(...args);
let stdout = createSignal();
let stderr = createSignal();
// create a task that finishes the process finishes
let exit = yield* spawn(function*() {
// get the exit code
let code = yield* action(function*(resolve) {
proc.on("exit", resolve);
try {
yield* suspend();
} finally {
proc.off("exit", resolve);
}
});
// close stdin, stdout
stdout.close();
stderr.close();
// return the exitcode
return code;
})
// connect stdin, stdout to signals
proc.stdout.on("data", stdout.send);
proc.stderr.on("data", stderr.send);
try {
// provide the resource handle
yield* provide({ exit, stdout, stderr });
} finally {
proc.stdout.off("data", stdout.send);
proc.stderr.off("data", stderr.send);
proc.kill("SIGINT");
// wait until the process is fully exited
yield* exit;
}
});
}
using a command
We can now use this command resource to create a process and stream its stdout to the console:
import { main, each } from "effection";
import { useCommand } from "./use-command.mjs";
await main(function*() {
let ls = yield* useCommand("ls", ["-lh"]);
for (let data of yield* each(ls.stdout)) {
console.log(`stdout: ${data}`);
yield* each.next();
}
console.log(`exit: ${yield* ls.exit}`)
});