Module B0_zero.Op

Build operations.

This module provides a type for specifying operations and their result. Operation execution and caching are respectively handled by the Exec and Reviver modules.

Operation status

type failure =
  1. | Exec of string option

    Execution failure with a potential error msg.

  2. | Missing_writes of B0_std.Fpath.t list

    Write specification failure.

  3. | Missing_reads of B0_std.Fpath.t list

    Read synchronisation failure.


The type for operation failures.

type status =
  1. | Aborted

    Aborted due to prerequisite failure.

  2. | Success

    Executed successfully.

  3. | Failed of failure

    Executed unsuccessfully.

  4. | Waiting

    Waiting for execution.


The type for operation statuses.


type id = int

The type for build operation identifiers.

type mark = string

The type for build operation marks. Marks have no special semantics they are just used to label operations for UI purposes.

type t

The type for build operations.

type op = t


module Copy : sig ... end

File copy.

module Delete : sig ... end

Path deletion.

module Mkdir : sig ... end

Directory creation.

module Notify : sig ... end

End-user notifications.

module Read : sig ... end

File reads.

module Spawn : sig ... end

Tool spawns.

module Wait_files : sig ... end

Waiting on files.

module Write : sig ... end

File writes.

type kind =
  1. | Copy of Copy.t
  2. | Delete of Delete.t
  3. | Mkdir of Mkdir.t
  4. | Notify of Notify.t
  5. | Read of Read.t
  6. | Spawn of Spawn.t
  7. | Wait_files of Wait_files.t
  8. | Write of Write.t

The type for operation kinds.

val kind_name : kind -> string

kind_name k is an end user name for kind k.

val make : id -> mark:mark -> time_created:B0_std.Mtime.Span.t -> time_started:B0_std.Mtime.Span.t -> duration:B0_std.Mtime.Span.t -> revived:bool -> status:status -> reads:B0_std.Fpath.t list -> writes:B0_std.Fpath.t list -> writes_manifest_root:B0_std.Fpath.t option -> hash:B0_std.Hash.t -> ?post_exec:(op -> unit) -> ?k:(op -> unit) -> kind -> t

make constructs an operation. See the corresponding accessors for the semantics of various arguments.

val kind : t -> kind

kind o is o's kind.

val equal : t -> t -> bool

equal o0 o1 is id o0 = id o1.

val compare : t -> t -> int

compare o0 o1 is compare (id o0) (id o1).

val id : t -> id

id o is the identifier of operation o.

val mark : t -> string

mark o is the mark of o.

val time_created : t -> B0_std.Mtime.Span.t

time_created o is o's creation time.

val time_started : t -> B0_std.Mtime.Span.t

time_started o is o's execution start time. This is different from B0_std.Mtime.Span.max_span once the operation has been submitted for execution.

val time_ended : t -> B0_std.Mtime.Span.t

time_ended o is o's execution end time. This is different from B0_std.Mtime.Span.max_span once the operation has been completed and collected.

val waited : t -> B0_std.Mtime.Span.t

waited is o's waiting time between creation and execution.

val duration : t -> B0_std.Mtime.Span.t

duration is o's execution duration time.

val revived : t -> bool

revived o is true iff o was revived from a cache. Only relevant if hash is not B0_std.Hash.nil.

val status : t -> status

status o is o execution status.

val reads : t -> B0_std.Fpath.t list

reads o are the file paths read by the operation.

val writes : t -> B0_std.Fpath.t list

writes o are the file paths written by o.

val writes_manifest_root : t -> B0_std.Fpath.t option

writes_manifest_root o if Some root, the operation is cached using a manifest key. This means the writes made relative to root are stored along-side the cache key.

val hash : t -> B0_std.Hash.t

hash o is the operation's hash. This is B0_std.Hash.nil before the operation hash has been effectively computed and set via set_hash. This remains B0_std.Hash.nil for operations that are not revivable.

val supports_reviving : t -> bool

supports_reviving o is true if operation o can be revived. This is only valid after the hash of o been effectively computed and set via set_hash.

val disable_reviving : t -> unit

disable_reviving o disables the ability to revive operation o. This only works after the hash been effectively computed and set via set_hash, for example in post execution call backs.

Updating the build operation

val invoke_k : t -> unit

exec_k o () invokes and discards o's continuation. Note that this does not protect against the continuation raising.

val discard_k : t -> unit

discard o discards o's continuation.

val invoke_post_exec : t -> unit

exec_post_exec o invokes and discards o's post execution hook. This hook called is right after the operation execution and, if applicable, before reviver recording. It is always called even if the operation fails or is revived (use status and revived to check these conditions). Note that if the hook unexpectedly raises this turns o in to a failure.

val discard_post_exec : t -> unit

discard_post_exec o discards o's post execution hook.

val abort : t -> unit

abort o sets the status of o to Op.status.Aborted and discards the operation closures (including kind specific ones).

val set_time_started : t -> B0_std.Mtime.Span.t -> unit

set_time_started o t sets o's execution start time to t.

val set_time_ended : t -> B0_std.Mtime.Span.t -> unit

set_time_ended o t sets o's execution end time to s.

val set_revived : t -> bool -> unit

set_revived o b sets o's cache revival status to b.

val set_status : t -> status -> unit

set_status o s sets the execution status to s.

val set_status_from_result : t -> ('a, string) Stdlib.result -> unit

set_status_from_result o r sets status of operation o to Executed if r is Ok _ and Failed (Exec e) if r is Error e.

val set_reads : t -> B0_std.Fpath.t list -> unit

set_reads t fs sets the file paths read by o to fs. Note that this resets the hash.

val set_writes : t -> B0_std.Fpath.t list -> unit

set_writes t fs sets the file paths written by o to fs.

val set_writes_manifest_root : t -> B0_std.Fpath.t option -> unit

set_writes_manifest_root t r sets the writes manifest root to r.

val set_hash : t -> B0_std.Hash.t -> unit

set_hash o h sets the operation hash to h.

Operation sets and map

module Set : Stdlib.Set.S with type elt = t

Operation sets

module Map : Stdlib.Map.S with type key = t

Operation maps

Analyzing operations

val did_not_write : t -> B0_std.Fpath.t list

did_not_write o compares writes with the current state of the file system and reports those files that do not exist.

val cannot_read : t -> B0_std.Fpath.t list

cannot_read o compares reads with the current state of the file system and reports those files that cannot be read.

val unready_reads : ready_roots:B0_std.Fpath.Set.t -> t list -> B0_std.Fpath.Set.t

unready_reads os are the file read by os that are not written by those and not in ready_roots.

val read_write_maps : t list -> Set.t B0_std.Fpath.Map.t * Set.t B0_std.Fpath.Map.t

read_write_maps ops is reads, writes with reads mapping file paths to operations that reads them and writes mapping file paths to operations that write them.

val write_map : t list -> Set.t B0_std.Fpath.Map.t

write_map os is snd (read_write_maps os). If one of the operation sets in the map is not a singleton the operations should likely not be run toghether.

val find_read_write_cycle : t list -> t list option

find_read_write_cycle os is Some cs if there exists a read/write cycle among the operations os. This means each each element of cs writes a file read by its successor in the list with the successor of the last element being the first.

type aggregate_error =
  1. | Failures

    Some operations failed.

  2. | Cycle of t list

    Dependency cycle.

  3. | Never_became_ready of B0_std.Fpath.Set.t

    Some files never became ready.


The type for errors related to a list of operations. This is:

  • Failures, if there is one or more operations in the list that Failed.
  • Cycle ops, if there is a set of Waiting operations in the list whose individual reads and writes leads to a dependency cycle. See also find_read_write_cycle.
  • Never_became_ready fs, with fs files that are in the reads of Waiting operations but are written by no operation from the list and were not made ready.

Note that formally more than one of these conditions can be true at the same time. But Never_became_ready is only reported once the first two kind of errors have been ruled out. The reason is that those files that never became ready may be created by continuations of the failed or cyclic operations and reporting them would not lead the user to focus on the right cause.

val find_aggregate_error : ready_roots:B0_std.Fpath.Set.t -> t list -> (unit, aggregate_error) Stdlib.result

find_aggregate_error ~ready_roots os finds an aggregate error among the list of operation os, assuming files ready_roots were made ready. This is Ok () if all operations os are Success.