include Tenacious_intf.S
val init : concurrency:int ‑> unit
To be called to set the amount of concurrency allowed before any call to exec
.
module Heart : Heart_intf.S
include Core.Monad.S
include Base__.Monad_intf.S_without_syntax with type a t := a t
include Base__.Monad_intf.Infix with type a t := a t
module Monad_infix : Base__.Monad_intf.Infix with type a t := a t
val exec : 'a t ‑> name:Core.String.t Core.Lazy.t ‑> ('a * Heart.t) Async.Deferred.t
note that exec
adds a new root in the observable tenacious graph,
even if you call it from a function given to embed
or lift
.
val embed : (cancel:Heart.t ‑> ('a * Heart.t) option Async.Deferred.t) ‑> 'a t
val memoize : name:Core.String.t Core.Lazy.t ‑> 'a t ‑> 'a t
val bracket : 'a t ‑> running:(int ‑> unit) ‑> finished:('a ‑> unit) ‑> cancelled:(unit ‑> unit) ‑> 'a t
This is most useful in combination with memoize:
memoize (bracket ~running ~finished ~cancelled x)
.
Without memoize
, you can get multiple concurrent running..canceled
and
running..finished
blocks even when your tenacious doesn't breaks its heart.
val lift : (unit ‑> ('a * Heart.t) Async.Deferred.t) ‑> 'a t
lift
is specialization/simplification of embed
cutoff is dangerous:
it will delay heart breakage for the time it takes to re-compute the value so
evaluating a memoize (cutoff x)
might give you stale values even when memoize x
wouldn't.
We have had a solution in the form of val protecting_cutoffs : 'a t -> 'a t
that would only return a value after waiting for all cutoffs to finish.
We removed the function right after f322aafe57c1
because it was unused
and was preventing an optimization for Heart.or_broken
.
race
non-deterministically chooses the first computation to succeed,
cancels the other.
Note that as it's non-deterministic it should be used with care. Ideally the final result should not depend on which result gets produced first.
module Result : sig ... end
non-deterministically choose the faster one to fail.
if neither fails, returns both.
The race
caveats apply.
A mutable variable whose state can be watched as a Tenacious computation.
'a Var.t
is conceptually a 'a Ref.t
with
Var.{create,get,set,replace}
corresponding to
Ref.{create,(!),(:=),replace}
.
The important difference is the watch
function, that lets you construct tenacious
computations that depend on the value of the variable.
module For_tests : Tenacious_intf.For_tests with type a t := a t