Skip to content
This repository has been archived by the owner on Jan 1, 2024. It is now read-only.

Cannot access process.exitCode and process.stdout, process.stderr sequentially #150

Closed
nandin-borjigin opened this issue Sep 14, 2023 · 2 comments · Fixed by #151
Closed

Comments

@nandin-borjigin
Copy link

nandin-borjigin commented Sep 14, 2023

import { Effect, Stream, pipe, Equal } from "effect";
import * as Command from "@effect/platform/Command";
import { layer as NodeCommandExecutor } from "@effect/platform-node/CommandExecutor";
import { layer as NodeFs } from "@effect/platform-node/FileSystem";

pipe(
  Command.make("ls", "none-existing"),
  Command.start,
  Effect.tap((process) =>
    pipe(
      process.exitCode,
      Effect.filterOrFail(
        Equal.equals(0), 
        () => "Exit code not 0"
      ),
      Effect.tapError(() => // We'd like to print the stderr channel in case of non-zero exit code.
        pipe(
          process.stderr,
          Stream.merge(process.stdout),
          Stream.runCollect,
          Effect.tap(Effect.log)
        )
      )
    )
  ),
  Effect.provideSomeLayer(NodeCommandExecutor),
  Effect.provideSomeLayer(NodeFs),
  Effect.runPromise
);
  • The stderr and stdout streams are empty if we evaluate exitCode before running them.
  • If we do not evaluate exitCode and directly run the stream, it is not empty.
timestamp=2023-09-14T15:12:52.429Z level=INFO fiber=#0 message="{\"_id\":\"Chunk\",\"values\":[]}"
[Error: Exit code not 0
undefined] {
  toJSON: [Function (anonymous)],
  toString: [Function (anonymous)],
  [Symbol(@effect/io/Runtime/FiberFailure)]: Symbol(@effect/io/Runtime/FiberFailure),
  [Symbol(@effect/io/Runtime/FiberFailure/Cause)]: { _tag: 'Fail', error: 'Exit code not 0' },
  [Symbol(nodejs.util.inspect.custom)]: [Function (anonymous)]
}
@nandin-borjigin
Copy link
Author

It seems like it relates to concurrency.

If I evaluate the exitCode and run the stderr stream concurrently, it gives the correct result.

pipe(
  Command.make("ls", "none-existing"),
  Command.start,
  Effect.map((process) => [
    pipe(
      process.stderr,
      Stream.runFold(new Uint8Array(), concatU8Array),
      Effect.map((u8) => new TextDecoder().decode(u8))
    ),
    pipe(process.exitCode),
  ]),
  Effect.flatMap(Effect.allWith({ concurrency: "unbounded" })),
  Effect.tap(Effect.log),
  Effect.provideSomeLayer(NodeCommandExecutor),
  Effect.provideSomeLayer(NodeFs),
  Effect.runPromise
);

export function concatU8Array(acc: Uint8Array, chunk: Uint8Array): Uint8Array {
  const buffer = new Uint8Array(acc.length + chunk.length);
  buffer.set(acc);
  buffer.set(chunk, acc.length);
  return buffer;
}

But if I replace concurrency: "unbounded" with concurrency: undefined, the program doesn't output anything, which is quite surprising.

@nandin-borjigin nandin-borjigin changed the title Cannot access process.exitCode and process.stdout, process.stderr at the same time. Cannot access process.exitCode and process.stdout, process.stderr sequentially Sep 14, 2023
@tim-smart
Copy link
Member

tim-smart commented Sep 14, 2023

It looks like exitCode assumes a running process, rather than a process that has already exited.

Will look at a patch soon :)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants