import * as T from "../_internal/task"; import { pipe } from "../../../Function"; import { sequential } from "../../ExecutionStrategy"; import type { Exit } from "../../Exit"; import * as Ex from "../../Exit"; import { Managed } from "../model"; import type { ReleaseMap } from "../ReleaseMap"; import { add, makeReleaseMap } from "../ReleaseMap"; import { releaseAll } from "./releaseAll"; /** * Ensures that a cleanup function runs when this ZManaged is finalized, before * the existing finalizers. */ export const onExitFirst = (cleanup: (exit: Exit) => T.Task) => ( self: Managed ) => onExitFirst_(self, cleanup); /** * Ensures that a cleanup function runs when this ZManaged is finalized, before * the existing finalizers. */ export const onExitFirst_ = ( self: Managed, cleanup: (exit: Exit) => T.Task ) => new Managed( T.uninterruptibleMask(({ restore }) => pipe( T.do, T.bindS("tp", () => T.ask()), T.letS("r", (s) => s.tp[0]), T.letS("outerReleaseMap", (s) => s.tp[1]), T.bindS("innerReleaseMap", () => makeReleaseMap), T.bindS("exitEA", (s) => restore(T.giveAll_(T.result(T.map_(self.task, ([_, a]) => a)), [s.r, s.innerReleaseMap])) ), T.bindS("releaseMapEntry", (s) => add((e) => T.flatten( T.mapBoth_( T.result(T.giveAll_(cleanup(s.exitEA), s.r)), T.result(releaseAll(e, sequential())(s.innerReleaseMap)), (l, r) => T.done(Ex.apSecond_(l, r)) ) ) )(s.outerReleaseMap) ), T.bindS("a", (s) => T.done(s.exitEA)), T.map((s) => [s.releaseMapEntry, s.a]) ) ) );