feather icon indicating copy to clipboard operation
feather copied to clipboard

Commands become a DAG: split and join

Open charlesetc opened this issue 3 years ago • 2 comments

Right now, our commands construct a linear chain of pipes. It would be nice if we could do arbitrary DAGs, something along the lines of:

val split : cmd -> cmd * cmd
(** [split] a command into two identical commands that have the same output *)

val as_fifo : cmd -> string
(** take a command and turn it into a named pipe. Similar to <( ... ) in bash. *)

This could be used like so:

let log1, log2 = process "tail" [ "-f" ; "log" ] |> split in 
process "cat" [as_fifo (log1 |. shuf); as_fifo (log2 |. sort)] |> run

The named pipes would have to be cleaned up when the Feather.run exits and Stdlib.at_exit.

I looked into this a bit and the most annoying part is that neither Base nor Stdlib implement a way to get the name of a tempfile without actually creating the tempfile. (We want to mkfifo ourselves.) So we'll have to implement our own random tempfile function.

charlesetc avatar Aug 18 '21 05:08 charlesetc

Nice idea !

The situation is like this in Base and Stdlib because apparently the implementation tests if a file already exists with a given name by directly creating it.

It shouldn't be too hard to tweak the original implementation (below) to do what we want.

let temp_file_name temp_dir prefix suffix =
  let rnd = (Random.State.bits (Lazy.force prng)) land 0xFFFFFF in
  concat temp_dir (Printf.sprintf "%s%06x%s" prefix rnd suffix)


let current_temp_dir_name = ref temp_dir_name

let set_temp_dir_name s = current_temp_dir_name := s
let get_temp_dir_name () = !current_temp_dir_name

let temp_file ?(temp_dir = !current_temp_dir_name) prefix suffix =
  let rec try_name counter =
    let name = temp_file_name temp_dir prefix suffix in
    try
      close_desc(open_desc name [Open_wronly; Open_creat; Open_excl] 0o600);
      name
    with Sys_error _ as e ->
      if counter >= 1000 then raise e else try_name (counter + 1)
  in try_name 0

(also apparently the bos library contains what we want but that would be another dependency)

Firobe avatar Aug 18 '21 15:08 Firobe

Good point — I'd be happy with just having our own utility function for that.

charlesetc avatar Jan 20 '22 19:01 charlesetc