/** * Ported from https://github.com/zio/zio/blob/master/core/shared/src/main/scala/zio/Supervisor.scala * * Copyright 2020 Michael Arnaldi and the Matechs Garage Contributors. */ import { pipe } from "../../Function"; import type * as O from "../../Option"; import type { Exit } from "../Exit/model"; import type { RuntimeFiber } from "../Fiber"; import * as T from "../Task/_core"; import type { Atomic } from "../XRef"; import * as R from "../XRef/atomic"; /** * A hint indicating whether or not to propagate supervision events across * supervisor hierarchies. */ export type Propagation = Stop | Continue; /** * A hint indicating supervision events no longer require propagation. */ export class Stop { readonly _tag = "Stop"; } /** * A hint indicating supervision events require further propagation. */ export class Continue { readonly _tag = "Continue"; } export const _stop = new Stop(); export const _continue = new Continue(); export const propagationAnd = (self: Propagation, that: Propagation) => self._tag === "Continue" && that._tag === "Continue" ? _continue : _stop; export const propagationOr = (self: Propagation, that: Propagation) => self._tag === "Continue" || that._tag === "Continue" ? _continue : _stop; /** * A `Supervisor` is allowed to supervise the launching and termination of * fibers, producing some visible value of type `A` from the supervision. */ export class Supervisor { constructor( readonly value: T.IO, readonly unsafeOnStart: ( environment: R, effect: T.Task, parent: O.Option>, fiber: RuntimeFiber ) => Propagation, readonly unsafeOnEnd: (value: Exit, fiber: RuntimeFiber) => Propagation ) {} /** * Returns a new supervisor that performs the function of this supervisor, * and the function of the specified supervisor, producing a tuple of the * outputs produced by both supervisors. * * The composite supervisor indicates that it has fully handled the * supervision event if only both component supervisors indicate they have * handled the supervision event. */ and(that: Supervisor): Supervisor { return new Supervisor( T.both_(this.value, that.value), (environment, effect, parent, fiber) => propagationAnd( this.unsafeOnStart(environment, effect, parent, fiber), that.unsafeOnStart(environment, effect, parent, fiber) ), (value, fiber) => propagationAnd(this.unsafeOnEnd(value, fiber), that.unsafeOnEnd(value, fiber)) ); } /** * Returns a new supervisor that performs the function of this supervisor, * and the function of the specified supervisor, producing a tuple of the * outputs produced by both supervisors. * * The composite supervisor indicates that it has fully handled the * supervision event if either component supervisors indicate they have * handled the supervision event. */ or(that: Supervisor): Supervisor { return new Supervisor( T.both_(this.value, that.value), (environment, effect, parent, fiber) => propagationOr( this.unsafeOnStart(environment, effect, parent, fiber), that.unsafeOnStart(environment, effect, parent, fiber) ), (value, fiber) => propagationOr(this.unsafeOnEnd(value, fiber), that.unsafeOnEnd(value, fiber)) ); } }