veffect
Version:
powerful TypeScript validation library built on the robust foundation of Effect combining exceptional type safety, high performance, and developer experience. Taking inspiration from Effect's functional principles, VEffect delivers a balanced approach tha
1,244 lines (1,243 loc) • 88.3 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.zipWithOptions = exports.zipRightOptions = exports.zipOptions = exports.zipLeftOptions = exports.withTracerScoped = exports.withSpanScoped = exports.withRuntimeFlagsScoped = exports.withRandomScoped = exports.withEarlyRelease = exports.withConfigProviderScoped = exports.withClockScoped = exports.validateWith = exports.validateFirst = exports.validateAllParDiscard = exports.validateAllPar = exports.validateAll = exports.validate = exports.using = exports.unsafeMakeChildFiber = exports.unsafeForkUnstarted = exports.unsafeFork = exports.tracerLogger = exports.tagMetricsScoped = exports.structuredLogger = exports.sequentialFinalizers = exports.scopedEffect = exports.scopeWith = exports.scopeUse = exports.scopeTag = exports.scopeMake = exports.scopeExtend = exports.scope = exports.replicateEffect = exports.replicate = exports.reduceEffect = exports.raceWith = exports.raceFibersWith = exports.raceAll = exports.race = exports.partition = exports.parallelNFinalizers = exports.parallelFinalizers = exports.mergeAll = exports.makeSpanScoped = exports.loggerWithSpanAnnotations = exports.loggerWithConsoleLog = exports.loggerWithConsoleError = exports.logFmtLogger = exports.labelMetricsScoped = exports.jsonLogger = exports.invokeWithInterrupt = exports.interruptWhenPossible = exports.forkWithErrorHandler = exports.forkDaemon = exports.fork = exports.forEachParUnbounded = exports.forEachParN = exports.forEachConcurrentDiscard = exports.forEach = exports.finalizersMask = exports.filter = exports.fiberSuccesses = exports.fiberStarted = exports.fiberScoped = exports.fiberRefUnsafeMakeSupervisor = exports.fiberRefMakeWith = exports.fiberRefMakeRuntimeFlags = exports.fiberRefMakeContext = exports.fiberRefMake = exports.fiberRefLocallyScopedWith = exports.fiberRefLocallyScoped = exports.fiberLifetimes = exports.fiberJoinAll = exports.fiberInterruptFork = exports.fiberFailures = exports.fiberAwaitAll = exports.fiberAll = exports.fiberActive = exports.exists = exports.ensuring = exports.disconnect = exports.defaultLogger = exports.daemonChildren = exports.currentSupervisor = exports.currentRuntimeFlags = exports.currentMinimumLogLevel = exports.currentLoggers = exports.batchedLogger = exports.allWith = exports.allSuccesses = exports.all = exports.addFinalizer = exports.acquireReleaseInterruptible = exports.acquireRelease = exports.FiberRuntime = void 0;
var Boolean = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../Boolean.js"));
var Chunk = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../Chunk.js"));
var Context = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../Context.js"));
var Deferred = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../Deferred.js"));
var _Effectable = /*#__PURE__*/require("../Effectable.js");
var ExecutionStrategy = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../ExecutionStrategy.js"));
var FiberId = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../FiberId.js"));
var FiberRefs = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../FiberRefs.js"));
var FiberRefsPatch = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../FiberRefsPatch.js"));
var FiberStatus = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../FiberStatus.js"));
var _Function = /*#__PURE__*/require("../Function.js");
var _GlobalValue = /*#__PURE__*/require("../GlobalValue.js");
var HashMap = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../HashMap.js"));
var HashSet = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../HashSet.js"));
var Inspectable = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../Inspectable.js"));
var LogLevel = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../LogLevel.js"));
var MRef = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../MutableRef.js"));
var Option = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../Option.js"));
var _Pipeable = /*#__PURE__*/require("../Pipeable.js");
var Predicate = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../Predicate.js"));
var RA = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../ReadonlyArray.js"));
var Ref = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../Ref.js"));
var RuntimeFlagsPatch = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("../RuntimeFlagsPatch.js"));
var _Scheduler = /*#__PURE__*/require("../Scheduler.js");
var _RequestBlock = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("./blockedRequests.js"));
var internalCause = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("./cause.js"));
var clock = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("./clock.js"));
var _completedRequestMap = /*#__PURE__*/require("./completedRequestMap.js");
var concurrency = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("./concurrency.js"));
var _configProvider = /*#__PURE__*/require("./configProvider.js");
var internalEffect = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("./core-effect.js"));
var core = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("./core.js"));
var defaultServices = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("./defaultServices.js"));
var _console = /*#__PURE__*/require("./defaultServices/console.js");
var executionStrategy = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("./executionStrategy.js"));
var internalFiber = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("./fiber.js"));
var FiberMessage = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("./fiberMessage.js"));
var fiberRefs = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("./fiberRefs.js"));
var fiberScope = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("./fiberScope.js"));
var internalLogger = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("./logger.js"));
var metric = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("./metric.js"));
var metricBoundaries = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("./metric/boundaries.js"));
var metricLabel = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("./metric/label.js"));
var OpCodes = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("./opCodes/effect.js"));
var _random = /*#__PURE__*/require("./random.js");
var _request = /*#__PURE__*/require("./request.js");
var _runtimeFlags2 = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("./runtimeFlags.js"));
var _runtimeFlags = _runtimeFlags2;
var supervisor = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("./supervisor.js"));
var SupervisorPatch = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("./supervisor/patch.js"));
var tracer = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("./tracer.js"));
var version = /*#__PURE__*/_interopRequireWildcard( /*#__PURE__*/require("./version.js"));
function _getRequireWildcardCache(e) {
if ("function" != typeof WeakMap) return null;
var r = new WeakMap(),
t = new WeakMap();
return (_getRequireWildcardCache = function (e) {
return e ? t : r;
})(e);
}
function _interopRequireWildcard(e, r) {
if (!r && e && e.__esModule) return e;
if (null === e || "object" != typeof e && "function" != typeof e) return {
default: e
};
var t = _getRequireWildcardCache(r);
if (t && t.has(e)) return t.get(e);
var n = {
__proto__: null
},
a = Object.defineProperty && Object.getOwnPropertyDescriptor;
for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) {
var i = a ? Object.getOwnPropertyDescriptor(e, u) : null;
i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u];
}
return n.default = e, t && t.set(e, n), n;
}
/** @internal */
const fiberStarted = exports.fiberStarted = /*#__PURE__*/metric.counter("effect_fiber_started", {
incremental: true
});
/** @internal */
const fiberActive = exports.fiberActive = /*#__PURE__*/metric.counter("effect_fiber_active");
/** @internal */
const fiberSuccesses = exports.fiberSuccesses = /*#__PURE__*/metric.counter("effect_fiber_successes", {
incremental: true
});
/** @internal */
const fiberFailures = exports.fiberFailures = /*#__PURE__*/metric.counter("effect_fiber_failures", {
incremental: true
});
/** @internal */
const fiberLifetimes = exports.fiberLifetimes = /*#__PURE__*/metric.tagged( /*#__PURE__*/metric.histogram("effect_fiber_lifetimes", /*#__PURE__*/metricBoundaries.exponential({
start: 0.5,
factor: 2,
count: 35
})), "time_unit", "milliseconds");
/** @internal */
const EvaluationSignalContinue = "Continue";
/** @internal */
const EvaluationSignalDone = "Done";
/** @internal */
const EvaluationSignalYieldNow = "Yield";
const runtimeFiberVariance = {
/* c8 ignore next */
_E: _ => _,
/* c8 ignore next */
_A: _ => _
};
const absurd = _ => {
throw new Error(`BUG: FiberRuntime - ${Inspectable.toStringUnknown(_)} - please report an issue at https://github.com/Effect-TS/effect/issues`);
};
const YieldedOp = /*#__PURE__*/Symbol.for("effect/internal/fiberRuntime/YieldedOp");
const yieldedOpChannel = /*#__PURE__*/(0, _GlobalValue.globalValue)("effect/internal/fiberRuntime/yieldedOpChannel", () => ({
currentOp: null
}));
const contOpSuccess = {
[OpCodes.OP_ON_SUCCESS]: (_, cont, value) => {
return cont.effect_instruction_i1(value);
},
["OnStep"]: (_, _cont, value) => {
return core.exitSucceed(core.exitSucceed(value));
},
[OpCodes.OP_ON_SUCCESS_AND_FAILURE]: (_, cont, value) => {
return cont.effect_instruction_i2(value);
},
[OpCodes.OP_REVERT_FLAGS]: (self, cont, value) => {
self.patchRuntimeFlags(self._runtimeFlags, cont.patch);
if (_runtimeFlags.interruptible(self._runtimeFlags) && self.isInterrupted()) {
return core.exitFailCause(self.getInterruptedCause());
} else {
return core.exitSucceed(value);
}
},
[OpCodes.OP_WHILE]: (self, cont, value) => {
cont.effect_instruction_i2(value);
if (cont.effect_instruction_i0()) {
self.pushStack(cont);
return cont.effect_instruction_i1();
} else {
return core.unit;
}
}
};
const drainQueueWhileRunningTable = {
[FiberMessage.OP_INTERRUPT_SIGNAL]: (self, runtimeFlags, cur, message) => {
self.processNewInterruptSignal(message.cause);
return _runtimeFlags.interruptible(runtimeFlags) ? core.exitFailCause(message.cause) : cur;
},
[FiberMessage.OP_RESUME]: (_self, _runtimeFlags, _cur, _message) => {
throw new Error("It is illegal to have multiple concurrent run loops in a single fiber");
},
[FiberMessage.OP_STATEFUL]: (self, runtimeFlags, cur, message) => {
message.onFiber(self, FiberStatus.running(runtimeFlags));
return cur;
},
[FiberMessage.OP_YIELD_NOW]: (_self, _runtimeFlags, cur, _message) => {
return core.flatMap(core.yieldNow(), () => cur);
}
};
/**
* Executes all requests, submitting requests to each data source in parallel.
*/
const runBlockedRequests = self => core.forEachSequentialDiscard(_RequestBlock.flatten(self), requestsByRequestResolver => forEachConcurrentDiscard(_RequestBlock.sequentialCollectionToChunk(requestsByRequestResolver), ([dataSource, sequential]) => {
const map = new Map();
const arr = [];
for (const block of sequential) {
arr.push(Chunk.toReadonlyArray(block));
for (const entry of block) {
map.set(entry.request, entry);
}
}
const flat = arr.flat();
return core.fiberRefLocally(invokeWithInterrupt(dataSource.runAll(arr), flat, () => flat.forEach(entry => {
entry.listeners.interrupted = true;
})), _completedRequestMap.currentRequestMap, map);
}, false, false));
/** @internal */
class FiberRuntime {
[internalFiber.FiberTypeId] = internalFiber.fiberVariance;
[internalFiber.RuntimeFiberTypeId] = runtimeFiberVariance;
pipe() {
return (0, _Pipeable.pipeArguments)(this, arguments);
}
_fiberRefs;
_fiberId;
_runtimeFlags;
_queue = new Array();
_children = null;
_observers = new Array();
_running = false;
_stack = [];
_asyncInterruptor = null;
_asyncBlockingOn = null;
_exitValue = null;
_steps = [];
_supervisor;
_scheduler;
_tracer;
currentOpCount = 0;
isYielding = false;
constructor(fiberId, fiberRefs0, runtimeFlags0) {
this._runtimeFlags = runtimeFlags0;
this._fiberId = fiberId;
this._fiberRefs = fiberRefs0;
this._supervisor = this.getFiberRef(currentSupervisor);
this._scheduler = this.getFiberRef(_Scheduler.currentScheduler);
if (_runtimeFlags.runtimeMetrics(runtimeFlags0)) {
const tags = this.getFiberRef(core.currentMetricLabels);
fiberStarted.unsafeUpdate(1, tags);
fiberActive.unsafeUpdate(1, tags);
}
this._tracer = Context.get(this.getFiberRef(defaultServices.currentServices), tracer.tracerTag);
}
/**
* The identity of the fiber.
*/
id() {
return this._fiberId;
}
/**
* Begins execution of the effect associated with this fiber on in the
* background. This can be called to "kick off" execution of a fiber after
* it has been created.
*/
resume(effect) {
this.tell(FiberMessage.resume(effect));
}
/**
* The status of the fiber.
*/
get status() {
return this.ask((_, status) => status);
}
/**
* Gets the fiber runtime flags.
*/
get runtimeFlags() {
return this.ask((state, status) => {
if (FiberStatus.isDone(status)) {
return state._runtimeFlags;
}
return status.runtimeFlags;
});
}
/**
* Returns the current `FiberScope` for the fiber.
*/
scope() {
return fiberScope.unsafeMake(this);
}
/**
* Retrieves the immediate children of the fiber.
*/
get children() {
return this.ask(fiber => Array.from(fiber.getChildren()));
}
/**
* Gets the fiber's set of children.
*/
getChildren() {
if (this._children === null) {
this._children = new Set();
}
return this._children;
}
/**
* Retrieves the interrupted cause of the fiber, which will be `Cause.empty`
* if the fiber has not been interrupted.
*
* **NOTE**: This method is safe to invoke on any fiber, but if not invoked
* on this fiber, then values derived from the fiber's state (including the
* log annotations and log level) may not be up-to-date.
*/
getInterruptedCause() {
return this.getFiberRef(core.currentInterruptedCause);
}
/**
* Retrieves the whole set of fiber refs.
*/
fiberRefs() {
return this.ask(fiber => fiber.getFiberRefs());
}
/**
* Returns an effect that will contain information computed from the fiber
* state and status while running on the fiber.
*
* This allows the outside world to interact safely with mutable fiber state
* without locks or immutable data.
*/
ask(f) {
return core.suspend(() => {
const deferred = core.deferredUnsafeMake(this._fiberId);
this.tell(FiberMessage.stateful((fiber, status) => {
core.deferredUnsafeDone(deferred, core.sync(() => f(fiber, status)));
}));
return core.deferredAwait(deferred);
});
}
/**
* Adds a message to be processed by the fiber on the fiber.
*/
tell(message) {
this._queue.push(message);
if (!this._running) {
this._running = true;
this.drainQueueLaterOnExecutor();
}
}
get await() {
return core.async(resume => {
const cb = exit => resume(core.succeed(exit));
this.tell(FiberMessage.stateful((fiber, _) => {
if (fiber._exitValue !== null) {
cb(this._exitValue);
} else {
fiber.addObserver(cb);
}
}));
return core.sync(() => this.tell(FiberMessage.stateful((fiber, _) => {
fiber.removeObserver(cb);
})));
}, this.id());
}
get inheritAll() {
return core.withFiberRuntime((parentFiber, parentStatus) => {
const parentFiberId = parentFiber.id();
const parentFiberRefs = parentFiber.getFiberRefs();
const parentRuntimeFlags = parentStatus.runtimeFlags;
const childFiberRefs = this.getFiberRefs();
const updatedFiberRefs = fiberRefs.joinAs(parentFiberRefs, parentFiberId, childFiberRefs);
parentFiber.setFiberRefs(updatedFiberRefs);
const updatedRuntimeFlags = parentFiber.getFiberRef(currentRuntimeFlags);
const patch = (0, _Function.pipe)(_runtimeFlags.diff(parentRuntimeFlags, updatedRuntimeFlags),
// Do not inherit WindDown or Interruption!
RuntimeFlagsPatch.exclude(_runtimeFlags.Interruption), RuntimeFlagsPatch.exclude(_runtimeFlags.WindDown));
return core.updateRuntimeFlags(patch);
});
}
/**
* Tentatively observes the fiber, but returns immediately if it is not
* already done.
*/
get poll() {
return core.sync(() => Option.fromNullable(this._exitValue));
}
/**
* Unsafely observes the fiber, but returns immediately if it is not
* already done.
*/
unsafePoll() {
return this._exitValue;
}
/**
* In the background, interrupts the fiber as if interrupted from the specified fiber.
*/
interruptAsFork(fiberId) {
return core.sync(() => this.tell(FiberMessage.interruptSignal(internalCause.interrupt(fiberId))));
}
/**
* In the background, interrupts the fiber as if interrupted from the specified fiber.
*/
unsafeInterruptAsFork(fiberId) {
this.tell(FiberMessage.interruptSignal(internalCause.interrupt(fiberId)));
}
/**
* Adds an observer to the list of observers.
*
* **NOTE**: This method must be invoked by the fiber itself.
*/
addObserver(observer) {
if (this._exitValue !== null) {
observer(this._exitValue);
} else {
this._observers.push(observer);
}
}
/**
* Removes the specified observer from the list of observers that will be
* notified when the fiber exits.
*
* **NOTE**: This method must be invoked by the fiber itself.
*/
removeObserver(observer) {
this._observers = this._observers.filter(o => o !== observer);
}
/**
* Retrieves all fiber refs of the fiber.
*
* **NOTE**: This method is safe to invoke on any fiber, but if not invoked
* on this fiber, then values derived from the fiber's state (including the
* log annotations and log level) may not be up-to-date.
*/
getFiberRefs() {
this.setFiberRef(currentRuntimeFlags, this._runtimeFlags);
return this._fiberRefs;
}
/**
* Deletes the specified fiber ref.
*
* **NOTE**: This method must be invoked by the fiber itself.
*/
unsafeDeleteFiberRef(fiberRef) {
this._fiberRefs = fiberRefs.delete_(this._fiberRefs, fiberRef);
}
/**
* Retrieves the state of the fiber ref, or else its initial value.
*
* **NOTE**: This method is safe to invoke on any fiber, but if not invoked
* on this fiber, then values derived from the fiber's state (including the
* log annotations and log level) may not be up-to-date.
*/
getFiberRef(fiberRef) {
if (this._fiberRefs.locals.has(fiberRef)) {
return this._fiberRefs.locals.get(fiberRef)[0][1];
}
return fiberRef.initial;
}
/**
* Sets the fiber ref to the specified value.
*
* **NOTE**: This method must be invoked by the fiber itself.
*/
setFiberRef(fiberRef, value) {
this._fiberRefs = fiberRefs.updateAs(this._fiberRefs, {
fiberId: this._fiberId,
fiberRef,
value
});
this.refreshRefCache();
}
refreshRefCache() {
this._tracer = Context.get(this.getFiberRef(defaultServices.currentServices), tracer.tracerTag);
this._supervisor = this.getFiberRef(currentSupervisor);
this._scheduler = this.getFiberRef(_Scheduler.currentScheduler);
}
/**
* Wholesale replaces all fiber refs of this fiber.
*
* **NOTE**: This method must be invoked by the fiber itself.
*/
setFiberRefs(fiberRefs) {
this._fiberRefs = fiberRefs;
this.refreshRefCache();
}
/**
* Adds a reference to the specified fiber inside the children set.
*
* **NOTE**: This method must be invoked by the fiber itself.
*/
addChild(child) {
this.getChildren().add(child);
}
/**
* Removes a reference to the specified fiber inside the children set.
*
* **NOTE**: This method must be invoked by the fiber itself.
*/
removeChild(child) {
this.getChildren().delete(child);
}
/**
* On the current thread, executes all messages in the fiber's inbox. This
* method may return before all work is done, in the event the fiber executes
* an asynchronous operation.
*
* **NOTE**: This method must be invoked by the fiber itself.
*/
drainQueueOnCurrentThread() {
let recurse = true;
while (recurse) {
let evaluationSignal = EvaluationSignalContinue;
const prev = globalThis[internalFiber.currentFiberURI];
globalThis[internalFiber.currentFiberURI] = this;
try {
while (evaluationSignal === EvaluationSignalContinue) {
evaluationSignal = this._queue.length === 0 ? EvaluationSignalDone : this.evaluateMessageWhileSuspended(this._queue.splice(0, 1)[0]);
}
} finally {
this._running = false;
globalThis[internalFiber.currentFiberURI] = prev;
}
// Maybe someone added something to the queue between us checking, and us
// giving up the drain. If so, we need to restart the draining, but only
// if we beat everyone else to the restart:
if (this._queue.length > 0 && !this._running) {
this._running = true;
if (evaluationSignal === EvaluationSignalYieldNow) {
this.drainQueueLaterOnExecutor();
recurse = false;
} else {
recurse = true;
}
} else {
recurse = false;
}
}
}
/**
* Schedules the execution of all messages in the fiber's inbox.
*
* This method will return immediately after the scheduling
* operation is completed, but potentially before such messages have been
* executed.
*
* **NOTE**: This method must be invoked by the fiber itself.
*/
drainQueueLaterOnExecutor() {
this._scheduler.scheduleTask(this.run, this.getFiberRef(core.currentSchedulingPriority));
}
/**
* Drains the fiber's message queue while the fiber is actively running,
* returning the next effect to execute, which may be the input effect if no
* additional effect needs to be executed.
*
* **NOTE**: This method must be invoked by the fiber itself.
*/
drainQueueWhileRunning(runtimeFlags, cur0) {
let cur = cur0;
while (this._queue.length > 0) {
const message = this._queue.splice(0, 1)[0];
// @ts-expect-error
cur = drainQueueWhileRunningTable[message._tag](this, runtimeFlags, cur, message);
}
return cur;
}
/**
* Determines if the fiber is interrupted.
*
* **NOTE**: This method is safe to invoke on any fiber, but if not invoked
* on this fiber, then values derived from the fiber's state (including the
* log annotations and log level) may not be up-to-date.
*/
isInterrupted() {
return !internalCause.isEmpty(this.getFiberRef(core.currentInterruptedCause));
}
/**
* Adds an interruptor to the set of interruptors that are interrupting this
* fiber.
*
* **NOTE**: This method must be invoked by the fiber itself.
*/
addInterruptedCause(cause) {
const oldSC = this.getFiberRef(core.currentInterruptedCause);
this.setFiberRef(core.currentInterruptedCause, internalCause.sequential(oldSC, cause));
}
/**
* Processes a new incoming interrupt signal.
*
* **NOTE**: This method must be invoked by the fiber itself.
*/
processNewInterruptSignal(cause) {
this.addInterruptedCause(cause);
this.sendInterruptSignalToAllChildren();
}
/**
* Interrupts all children of the current fiber, returning an effect that will
* await the exit of the children. This method will return null if the fiber
* has no children.
*
* **NOTE**: This method must be invoked by the fiber itself.
*/
sendInterruptSignalToAllChildren() {
if (this._children === null || this._children.size === 0) {
return false;
}
let told = false;
for (const child of this._children) {
child.tell(FiberMessage.interruptSignal(internalCause.interrupt(this.id())));
told = true;
}
return told;
}
/**
* Interrupts all children of the current fiber, returning an effect that will
* await the exit of the children. This method will return null if the fiber
* has no children.
*
* **NOTE**: This method must be invoked by the fiber itself.
*/
interruptAllChildren() {
if (this.sendInterruptSignalToAllChildren()) {
const it = this._children.values();
this._children = null;
let isDone = false;
const body = () => {
const next = it.next();
if (!next.done) {
return core.asUnit(next.value.await);
} else {
return core.sync(() => {
isDone = true;
});
}
};
return core.whileLoop({
while: () => !isDone,
body,
step: () => {
//
}
});
}
return null;
}
reportExitValue(exit) {
if (_runtimeFlags.runtimeMetrics(this._runtimeFlags)) {
const tags = this.getFiberRef(core.currentMetricLabels);
const startTimeMillis = this.id().startTimeMillis;
const endTimeMillis = Date.now();
fiberLifetimes.unsafeUpdate(endTimeMillis - startTimeMillis, tags);
fiberActive.unsafeUpdate(-1, tags);
switch (exit._tag) {
case OpCodes.OP_SUCCESS:
{
fiberSuccesses.unsafeUpdate(1, tags);
break;
}
case OpCodes.OP_FAILURE:
{
fiberFailures.unsafeUpdate(1, tags);
break;
}
}
}
if (exit._tag === "Failure") {
const level = this.getFiberRef(core.currentUnhandledErrorLogLevel);
if (!internalCause.isInterruptedOnly(exit.cause) && level._tag === "Some") {
this.log("Fiber terminated with an unhandled error", exit.cause, level);
}
}
}
setExitValue(exit) {
this._exitValue = exit;
this.reportExitValue(exit);
for (let i = this._observers.length - 1; i >= 0; i--) {
this._observers[i](exit);
}
}
getLoggers() {
return this.getFiberRef(currentLoggers);
}
log(message, cause, overrideLogLevel) {
const logLevel = Option.isSome(overrideLogLevel) ? overrideLogLevel.value : this.getFiberRef(core.currentLogLevel);
const minimumLogLevel = this.getFiberRef(currentMinimumLogLevel);
if (LogLevel.greaterThan(minimumLogLevel, logLevel)) {
return;
}
const spans = this.getFiberRef(core.currentLogSpan);
const annotations = this.getFiberRef(core.currentLogAnnotations);
const loggers = this.getLoggers();
const contextMap = this.getFiberRefs();
if (HashSet.size(loggers) > 0) {
const clockService = Context.get(this.getFiberRef(defaultServices.currentServices), clock.clockTag);
const date = new Date(clockService.unsafeCurrentTimeMillis());
for (const logger of loggers) {
logger.log({
fiberId: this.id(),
logLevel,
message,
cause,
context: contextMap,
spans,
annotations,
date
});
}
}
}
/**
* Evaluates a single message on the current thread, while the fiber is
* suspended. This method should only be called while evaluation of the
* fiber's effect is suspended due to an asynchronous operation.
*
* **NOTE**: This method must be invoked by the fiber itself.
*/
evaluateMessageWhileSuspended(message) {
switch (message._tag) {
case FiberMessage.OP_YIELD_NOW:
{
return EvaluationSignalYieldNow;
}
case FiberMessage.OP_INTERRUPT_SIGNAL:
{
this.processNewInterruptSignal(message.cause);
if (this._asyncInterruptor !== null) {
this._asyncInterruptor(core.exitFailCause(message.cause));
this._asyncInterruptor = null;
}
return EvaluationSignalContinue;
}
case FiberMessage.OP_RESUME:
{
this._asyncInterruptor = null;
this._asyncBlockingOn = null;
this.evaluateEffect(message.effect);
return EvaluationSignalContinue;
}
case FiberMessage.OP_STATEFUL:
{
message.onFiber(this, this._exitValue !== null ? FiberStatus.done : FiberStatus.suspended(this._runtimeFlags, this._asyncBlockingOn));
return EvaluationSignalContinue;
}
default:
{
return absurd(message);
}
}
}
/**
* Evaluates an effect until completion, potentially asynchronously.
*
* **NOTE**: This method must be invoked by the fiber itself.
*/
evaluateEffect(effect0) {
this._supervisor.onResume(this);
try {
let effect = _runtimeFlags.interruptible(this._runtimeFlags) && this.isInterrupted() ? core.exitFailCause(this.getInterruptedCause()) : effect0;
while (effect !== null) {
const eff = effect;
const exit = this.runLoop(eff);
if (exit === YieldedOp) {
const op = yieldedOpChannel.currentOp;
yieldedOpChannel.currentOp = null;
if (op._op === OpCodes.OP_YIELD) {
if (_runtimeFlags.cooperativeYielding(this._runtimeFlags)) {
this.tell(FiberMessage.yieldNow());
this.tell(FiberMessage.resume(core.exitUnit));
effect = null;
} else {
effect = core.exitUnit;
}
} else if (op._op === OpCodes.OP_ASYNC) {
// Terminate this evaluation, async resumption will continue evaluation:
effect = null;
}
} else {
this._runtimeFlags = (0, _Function.pipe)(this._runtimeFlags, _runtimeFlags.enable(_runtimeFlags.WindDown));
const interruption = this.interruptAllChildren();
if (interruption !== null) {
effect = core.flatMap(interruption, () => exit);
} else {
if (this._queue.length === 0) {
// No more messages to process, so we will allow the fiber to end life:
this.setExitValue(exit);
} else {
// There are messages, possibly added by the final op executed by
// the fiber. To be safe, we should execute those now before we
// allow the fiber to end life:
this.tell(FiberMessage.resume(exit));
}
effect = null;
}
}
}
} finally {
this._supervisor.onSuspend(this);
}
}
/**
* Begins execution of the effect associated with this fiber on the current
* thread. This can be called to "kick off" execution of a fiber after it has
* been created, in hopes that the effect can be executed synchronously.
*
* This is not the normal way of starting a fiber, but it is useful when the
* express goal of executing the fiber is to synchronously produce its exit.
*/
start(effect) {
if (!this._running) {
this._running = true;
const prev = globalThis[internalFiber.currentFiberURI];
globalThis[internalFiber.currentFiberURI] = this;
try {
this.evaluateEffect(effect);
} finally {
this._running = false;
globalThis[internalFiber.currentFiberURI] = prev;
// Because we're special casing `start`, we have to be responsible
// for spinning up the fiber if there were new messages added to
// the queue between the completion of the effect and the transition
// to the not running state.
if (this._queue.length > 0) {
this.drainQueueLaterOnExecutor();
}
}
} else {
this.tell(FiberMessage.resume(effect));
}
}
/**
* Begins execution of the effect associated with this fiber on in the
* background, and on the correct thread pool. This can be called to "kick
* off" execution of a fiber after it has been created, in hopes that the
* effect can be executed synchronously.
*/
startFork(effect) {
this.tell(FiberMessage.resume(effect));
}
/**
* Takes the current runtime flags, patches them to return the new runtime
* flags, and then makes any changes necessary to fiber state based on the
* specified patch.
*
* **NOTE**: This method must be invoked by the fiber itself.
*/
patchRuntimeFlags(oldRuntimeFlags, patch) {
const newRuntimeFlags = _runtimeFlags.patch(oldRuntimeFlags, patch);
globalThis[internalFiber.currentFiberURI] = this;
this._runtimeFlags = newRuntimeFlags;
return newRuntimeFlags;
}
/**
* Initiates an asynchronous operation, by building a callback that will
* resume execution, and then feeding that callback to the registration
* function, handling error cases and repeated resumptions appropriately.
*
* **NOTE**: This method must be invoked by the fiber itself.
*/
initiateAsync(runtimeFlags, asyncRegister) {
let alreadyCalled = false;
const callback = effect => {
if (!alreadyCalled) {
alreadyCalled = true;
this.tell(FiberMessage.resume(effect));
}
};
if (_runtimeFlags.interruptible(runtimeFlags)) {
this._asyncInterruptor = callback;
}
try {
asyncRegister(callback);
} catch (e) {
callback(core.failCause(internalCause.die(e)));
}
}
pushStack(cont) {
this._stack.push(cont);
if (cont._op === "OnStep") {
this._steps.push({
refs: this.getFiberRefs(),
flags: this._runtimeFlags
});
}
}
popStack() {
const item = this._stack.pop();
if (item) {
if (item._op === "OnStep") {
this._steps.pop();
}
return item;
}
return;
}
getNextSuccessCont() {
let frame = this.popStack();
while (frame) {
if (frame._op !== OpCodes.OP_ON_FAILURE) {
return frame;
}
frame = this.popStack();
}
}
getNextFailCont() {
let frame = this.popStack();
while (frame) {
if (frame._op !== OpCodes.OP_ON_SUCCESS && frame._op !== OpCodes.OP_WHILE) {
return frame;
}
frame = this.popStack();
}
}
[OpCodes.OP_TAG](op) {
return core.map(core.fiberRefGet(core.currentContext), context => Context.unsafeGet(context, op));
}
["Left"](op) {
return core.fail(op.left);
}
["None"](_) {
return core.fail(new core.NoSuchElementException());
}
["Right"](op) {
return core.exitSucceed(op.right);
}
["Some"](op) {
return core.exitSucceed(op.value);
}
[OpCodes.OP_SYNC](op) {
const value = op.effect_instruction_i0();
const cont = this.getNextSuccessCont();
if (cont !== undefined) {
if (!(cont._op in contOpSuccess)) {
// @ts-expect-error
absurd(cont);
}
// @ts-expect-error
return contOpSuccess[cont._op](this, cont, value);
} else {
yieldedOpChannel.currentOp = core.exitSucceed(value);
return YieldedOp;
}
}
[OpCodes.OP_SUCCESS](op) {
const oldCur = op;
const cont = this.getNextSuccessCont();
if (cont !== undefined) {
if (!(cont._op in contOpSuccess)) {
// @ts-expect-error
absurd(cont);
}
// @ts-expect-error
return contOpSuccess[cont._op](this, cont, oldCur.effect_instruction_i0);
} else {
yieldedOpChannel.currentOp = oldCur;
return YieldedOp;
}
}
[OpCodes.OP_FAILURE](op) {
const cause = op.effect_instruction_i0;
const cont = this.getNextFailCont();
if (cont !== undefined) {
switch (cont._op) {
case OpCodes.OP_ON_FAILURE:
case OpCodes.OP_ON_SUCCESS_AND_FAILURE:
{
if (!(_runtimeFlags.interruptible(this._runtimeFlags) && this.isInterrupted())) {
return cont.effect_instruction_i1(cause);
} else {
return core.exitFailCause(internalCause.stripFailures(cause));
}
}
case "OnStep":
{
if (!(_runtimeFlags.interruptible(this._runtimeFlags) && this.isInterrupted())) {
return core.exitSucceed(core.exitFailCause(cause));
} else {
return core.exitFailCause(internalCause.stripFailures(cause));
}
}
case OpCodes.OP_REVERT_FLAGS:
{
this.patchRuntimeFlags(this._runtimeFlags, cont.patch);
if (_runtimeFlags.interruptible(this._runtimeFlags) && this.isInterrupted()) {
return core.exitFailCause(internalCause.sequential(cause, this.getInterruptedCause()));
} else {
return core.exitFailCause(cause);
}
}
default:
{
absurd(cont);
}
}
} else {
yieldedOpChannel.currentOp = core.exitFailCause(cause);
return YieldedOp;
}
}
[OpCodes.OP_WITH_RUNTIME](op) {
return op.effect_instruction_i0(this, FiberStatus.running(this._runtimeFlags));
}
["Blocked"](op) {
const refs = this.getFiberRefs();
const flags = this._runtimeFlags;
if (this._steps.length > 0) {
const frames = [];
const snap = this._steps[this._steps.length - 1];
let frame = this.popStack();
while (frame && frame._op !== "OnStep") {
frames.push(frame);
frame = this.popStack();
}
this.setFiberRefs(snap.refs);
this._runtimeFlags = snap.flags;
const patchRefs = FiberRefsPatch.diff(snap.refs, refs);
const patchFlags = _runtimeFlags.diff(snap.flags, flags);
return core.exitSucceed(core.blocked(op.effect_instruction_i0, core.withFiberRuntime(newFiber => {
while (frames.length > 0) {
newFiber.pushStack(frames.pop());
}
newFiber.setFiberRefs(FiberRefsPatch.patch(newFiber.id(), newFiber.getFiberRefs())(patchRefs));
newFiber._runtimeFlags = _runtimeFlags.patch(patchFlags)(newFiber._runtimeFlags);
return op.effect_instruction_i1;
})));
}
return core.uninterruptibleMask(restore => core.flatMap(forkDaemon(core.runRequestBlock(op.effect_instruction_i0)), () => restore(op.effect_instruction_i1)));
}
["RunBlocked"](op) {
return runBlockedRequests(op.effect_instruction_i0);
}
[OpCodes.OP_UPDATE_RUNTIME_FLAGS](op) {
const updateFlags = op.effect_instruction_i0;
const oldRuntimeFlags = this._runtimeFlags;
const newRuntimeFlags = _runtimeFlags.patch(oldRuntimeFlags, updateFlags);
// One more chance to short circuit: if we're immediately going
// to interrupt. Interruption will cause immediate reversion of
// the flag, so as long as we "peek ahead", there's no need to
// set them to begin with.
if (_runtimeFlags.interruptible(newRuntimeFlags) && this.isInterrupted()) {
return core.exitFailCause(this.getInterruptedCause());
} else {
// Impossible to short circuit, so record the changes
this.patchRuntimeFlags(this._runtimeFlags, updateFlags);
if (op.effect_instruction_i1) {
// Since we updated the flags, we need to revert them
const revertFlags = _runtimeFlags.diff(newRuntimeFlags, oldRuntimeFlags);
this.pushStack(new core.RevertFlags(revertFlags, op));
return op.effect_instruction_i1(oldRuntimeFlags);
} else {
return core.exitUnit;
}
}
}
[OpCodes.OP_ON_SUCCESS](op) {
this.pushStack(op);
return op.effect_instruction_i0;
}
["OnStep"](op) {
this.pushStack(op);
return op.effect_instruction_i0;
}
[OpCodes.OP_ON_FAILURE](op) {
this.pushStack(op);
return op.effect_instruction_i0;
}
[OpCodes.OP_ON_SUCCESS_AND_FAILURE](op) {
this.pushStack(op);
return op.effect_instruction_i0;
}
[OpCodes.OP_ASYNC](op) {
this._asyncBlockingOn = op.effect_instruction_i1;
this.initiateAsync(this._runtimeFlags, op.effect_instruction_i0);
yieldedOpChannel.currentOp = op;
return YieldedOp;
}
[OpCodes.OP_YIELD](op) {
this.isYielding = false;
yieldedOpChannel.currentOp = op;
return YieldedOp;
}
[OpCodes.OP_WHILE](op) {
const check = op.effect_instruction_i0;
const body = op.effect_instruction_i1;
if (check()) {
this.pushStack(op);
return body();
} else {
return core.exitUnit;
}
}
[OpCodes.OP_COMMIT](op) {
return op.commit();
}
/**
* The main run-loop for evaluating effects.
*
* **NOTE**: This method must be invoked by the fiber itself.
*/
runLoop(effect0) {
let cur = effect0;
this.currentOpCount = 0;
// eslint-disable-next-line no-constant-condition
while (true) {
if ((this._runtimeFlags & _runtimeFlags2.OpSupervision) !== 0) {
this._supervisor.onEffect(this, cur);
}
if (this._queue.length > 0) {
cur = this.drainQueueWhileRunning(this._runtimeFlags, cur);
}
if (!this.isYielding) {
this.currentOpCount += 1;
const shouldYield = this._scheduler.shouldYield(this);
if (shouldYield !== false) {
this.isYielding = true;
this.currentOpCount = 0;
const oldCur = cur;
cur = core.flatMap(core.yieldNow({
priority: shouldYield
}), () => oldCur);
}
}
try {
if (!("_op" in cur) || !(cur._op in this)) {
// @ts-expect-error
absurd(cur);
}
// @ts-expect-error
cur = this._tracer.context(() => {
if (version.getCurrentVersion() !== cur[_Effectable.EffectTypeId]._V) {
return core.dieMessage(`Cannot execute an Effect versioned ${cur[_Effectable.EffectTypeId]._V} with a Runtime of version ${version.getCurrentVersion()}`);
}
// @ts-expect-error
return this[cur._op](cur);
}, this);
if (cur === YieldedOp) {
const op = yieldedOpChannel.currentOp;
if (op._op === OpCodes.OP_YIELD || op._op === OpCodes.OP_ASYNC) {
return YieldedOp;
}
yieldedOpChannel.currentOp = null;
return op._op === OpCodes.OP_SUCCESS || op._op === OpCodes.OP_FAILURE ? op : core.exitFailCause(internalCause.die(op));
}
} catch (e) {
if (core.isEffectError(e)) {
cur = core.exitFailCause(e.cause);
} else if (core.isInterruptedException(e)) {
cur = core.exitFailCause(internalCause.sequential(internalCause.die(e), internalCause.interrupt(FiberId.none)));
} else {
cur = core.exitFailCause(internalCause.die(e));
}
}
}
}
run = () => {
this.drainQueueOnCurrentThread();
};
}
// circular with Logger
/** @internal */
exports.FiberRuntime = FiberRuntime;
const currentMinimumLogLevel = exports.currentMinimumLogLevel = /*#__PURE__*/(0, _GlobalValue.globalValue)("effect/FiberRef/currentMinimumLogLevel", () => core.fiberRefUnsafeMake(LogLevel.fromLiteral("Info")));
/** @internal */
const loggerWithConsoleLog = self => internalLogger.makeLogger(opts => {
const services = FiberRefs.getOrDefault(opts.context, defaultServices.currentServices);
Context.get(services, _console.consoleTag).unsafe.log(self.log(opts));
});
/** @internal */
exports.loggerWithConsoleLog = loggerWithConsoleLog;
const loggerWithConsoleError = self => internalLogger.makeLogger(opts => {
const services = FiberRefs.getOrDefault(opts.context, defaultServices.currentServices);
Context.get(services, _console.consoleTag).unsafe.error(self.log(opts));
});
/** @internal */
exports.loggerWithConsoleError = loggerWithConsoleError;
const defaultLogger = exports.defaultLogger = /*#__PURE__*/(0, _GlobalValue.globalValue)( /*#__PURE__*/Symbol.for("effect/Logger/defaultLogger"), () => loggerWithConsoleLog(internalLogger.stringLogger));
/** @internal */
const jsonLogger = exports.jsonLogger = /*#__PURE__*/(0, _GlobalValue.globalValue)( /*#__PURE__*/Symbol.for("effect/Logger/jsonLogger"), () => loggerWithConsoleLog(internalLogger.jsonLogger));
/** @internal */
const logFmtLogger = exports.logFmtLogger = /*#__PURE__*/(0, _GlobalValue.globalValue)( /*#__PURE__*/Symbol.for("effect/Logger/logFmtLogger"), () => loggerWithConsoleLog(internalLogger.logfmtLogger));
/** @internal */
const structuredLogger = exports.structuredLogger = /*#__PURE__*/(0, _GlobalValue.globalValue)( /*#__PURE__*/Symbol.for("effect/Logger/structuredLogger"), () => loggerWithConsoleLog(internalLogger.structuredLogger));
/** @internal */
const tracerLogger = exports.tracerLogger = /*#__PURE__*/(0, _GlobalValue.globalValue)( /*#__PURE__*/Symbol.for("effect/Logger/tracerLogger"), () => internalLogger.makeLogger(({
annotations,
cause,
context,
fiberId,
logLevel,
message
}) => {
const span = Option.flatMap(fiberRefs.get(context, core.currentContext), Context.getOption(tracer.spanTag));
const clockService = Option.map(fiberRefs.get(context, defaultServices.currentServices), _ => Context.get(_, clock.clockTag));
if (span._tag === "None" || span.value._tag === "ExternalSpan" || clockService._tag === "None") {
return;
}
const attributes = Object.fromEntries(HashMap.map(annotations, Inspectable.toStringUnknown));
attributes["effect.fiberId"] = FiberId.threadName(fiberId);
attributes["effect.logLevel"] = logLevel.label;
if (cause !== null && cause._tag !== "Empty") {
attributes["effect.cause"] = internalCause.pretty(cause);
}
span.value.event(String(message), clockService.value.unsafeCurrentTimeNanos(), attributes);
}));
/** @internal */
const loggerWithSpanAnnotations = self => internalLogger.mapInputOptions(self, options => {
const span = Option.flatMap(fiberRefs.get(options.context, core.currentContext), Context.getOption(tracer.spanTag));
if (span._tag === "None") {
return options;
}
return {
...options,
annotations: (0, _Function.pipe)(options.annotations, HashMap.set("effect.traceId", span.value.traceId), HashMap.set("effect.spanId", span.value.spanId), span.value._tag === "Span" ? HashMap.set("effect.spanName", span.value.name) : _Function.identity)
};
});
/** @internal */
exports.loggerWithSpanAnnotations = loggerWithSpanAnnotations;
const currentLoggers = exports.currentLoggers = /*#__PURE__*/(0, _GlobalValue.globalValue)( /*#__PURE__*/Symbol.for("effect/FiberRef/currentLoggers"), () => core.fiberRefUnsafeMakeHashSet(HashSet.make(defaultLogger, tracerLogger)));
/** @internal */
const batchedLogger = exports.batchedLogger = /*#__PURE__*/(0, _Function.dual)(3, (self, window, f) => core.flatMap(scope, scope => {
let buffer = [];
const flush = core.suspend(() => {
if (buffer.length === 0) {
return core.unit;
}
const arr = buffer;
buffer = [];
return f(arr);
});
return core.uninterruptibleMask(restore => (0, _Function.pipe)(internalEffect.sleep(window), core.zipRight(flush), internalEffect.forever, restore, forkDaemon, core.flatMap(fiber => core.scopeAddFinalizer(scope, core.interruptFiber(fiber))), core.zipRight(addFinalizer(() => flush)), core.as(internalLogger.makeLogger(options => {
buffer.push(self.log(options));
}))));
}));
// circular with Effect
/* @internal */
const acquireRelease = exports.acquireRelease = /*#__PURE__*/(0, _Function.dual)(args => core.isEffect(args[0]), (acquire, release) => core.uninterruptible(core.tap(acquire, a => addFinalizer(exit => release(a, exit)))));
/* @internal */
const acquireReleaseInterruptible = exports.acquireReleaseInterruptible = /*#__PURE__*/(0, _Function.dual)(args => core.isEffect(args[0]), (acquire, release) => ensuring(acquire, addFinalizer(exit => release(exit))));
/* @internal */
const addFinalizer = finalizer => core.withFiberRuntime(runtime => {
const acquireRefs = runtime.getFiberRefs();
const acquireFlags = runtime._runtimeFlags;
return core.flatMap(scope, scope => core.scopeAddFinalizerExit(scope, exit => core.withFiberRuntime(runtimeFinalizer => {
const preRefs = runtimeFinalizer.getFiberRefs();
const preFlags = runtimeFinalizer._runtimeFlags;
const patchRefs = FiberRefsPatch.diff(preRefs, acquireRefs);
const patchFlags = _runtimeFlags.diff(preFlags, acquireFlags);
const inverseRefs = FiberRefsPatch.diff(acquireRefs, preRefs);
runtimeFinalizer.setFiberRefs(FiberRefsPatch.patch(patchRefs, runtimeFinalizer.id(), acquireRefs));
return ensuring(core.withRuntimeFlags(finalizer(exit), patchFlags), core.sync(() => {
runtimeFinalizer.setFiberRefs(FiberRefsPatch.patch(inverseRefs, runtimeFinalizer.id(), runtimeFinalizer.getFiberRefs()));
}));
})));
});
/* @internal */
exports.addFinalizer = addFinalizer;
const daemonChildren = self => {
const forkScope = core.fiberRefLocally(core.currentForkScopeOverride, Option.some(fiberScope.globalScope));
return forkScope(self);
};
/** @internal */
exports.daemonChildren = daemonChildren;
const _existsParFound = /*#__PURE__*/Symbol.for("effect/Effect/existsPar/found");
/* @internal */
const exists = exports.exists = /*#__PURE__*/(0, _Function.dual)(args => Predicate.isIterable(args[0]), (elements, f, options) => concurrency.matchSimple(options?.concurrency, () => core.suspend(() => existsLoop(elements[Symbol.iterator](), 0, f)), () => core.matchEffect(forEach(elements, (a, i) => core.if_(f(a, i), {
onTrue: core.fail(_existsParFound),
onFalse: core.unit
}), options), {
onFailure: e => e === _existsParFound ? core.succeed(true) : core.fail(e),
onSuccess: () => core.succeed(false)
})));
const existsLoop = (iterator, index, f) => {
const next = iterator.next();
if (next.done) {
return core.succeed(false);
}
return (0, _Function.pipe)(core.flatMap(f(next.value, index), b => b ? core.succeed(b) : existsLoop(iterator, index + 1, f)));
};
/* @int