EdgeAIG's picture
download
raw
20.8 kB
import { dual, identity } from "./Function.js";
import * as core from "./internal/core.js";
import * as internalEffect from "./internal/effect.js";
import * as Option from "./Option.js";
import { pipeArguments } from "./Pipeable.js";
import { hasProperty } from "./Predicate.js";
const TypeId = "~effect/Deferred";
/**
* Checks whether a value is a `Deferred`.
*
* **When to use**
*
* Use to validate unknown values at runtime boundaries before treating them as
* `Deferred` values.
*
* @category guards
* @since 4.0.0
*/
export const isDeferred = u => hasProperty(u, TypeId);
const DeferredProto = {
[TypeId]: {
_A: identity,
_E: identity
},
pipe() {
return pipeArguments(this, arguments);
}
};
/**
* Creates an empty `Deferred` synchronously outside the `Effect` runtime.
*
* **When to use**
*
* Use to allocate a `Deferred` synchronously when direct allocation outside
* `Effect` is required.
*
* **Example** (Creating a Deferred unsafely)
*
* ```ts
* import { Deferred } from "effect"
*
* const deferred = Deferred.makeUnsafe<number>()
* console.log(deferred)
* ```
*
* @category unsafe
* @since 4.0.0
*/
export const makeUnsafe = () => {
const self = Object.create(DeferredProto);
self.resumes = undefined;
self.effect = undefined;
return self;
};
/**
* Creates a new `Deferred`.
*
* **When to use**
*
* Use to allocate an empty `Deferred` inside an `Effect` workflow.
*
* **Example** (Creating a Deferred)
*
* ```ts
* import { Deferred, Effect } from "effect"
*
* const program = Effect.gen(function*() {
* const deferred = yield* Deferred.make<number>()
* yield* Deferred.succeed(deferred, 42)
* const value = yield* Deferred.await(deferred)
* console.log(value) // 42
* })
* ```
*
* @category constructors
* @since 2.0.0
*/
export const make = () => internalEffect.sync(() => makeUnsafe());
const _await = self => internalEffect.callback(resume => {
if (self.effect) return resume(self.effect);
self.resumes ??= [];
self.resumes.push(resume);
return internalEffect.sync(() => {
const index = self.resumes.indexOf(resume);
self.resumes.splice(index, 1);
});
});
export {
/**
* Retrieves the value of the `Deferred`, suspending the fiber running the
* workflow until the result is available.
*
* **When to use**
*
* Use to wait for a `Deferred` to be completed and resume with its success,
* failure, defect, or interruption.
*
* **Details**
*
* Awaiters observe the completion effect stored in the `Deferred`.
*
* **Example** (Awaiting a Deferred value)
*
* ```ts
* import { Deferred, Effect } from "effect"
*
* const program = Effect.gen(function*() {
* const deferred = yield* Deferred.make<number>()
* yield* Deferred.succeed(deferred, 42)
*
* const value = yield* Deferred.await(deferred)
* console.log(value) // 42
* })
* ```
*
* @see {@link complete} for completing from an effect and memoizing its result
* @see {@link completeWith} for completing with an effect directly
*
* @category getters
* @since 2.0.0
*/
_await as await };
/**
* Runs the supplied `Effect` and attempts to complete the `Deferred` with its
* memoized result.
*
* **When to use**
*
* Use when completing a `Deferred` should run an effect once and share its
* result with all awaiters.
*
* **Details**
*
* The returned effect succeeds with `true` when this call completed the
* `Deferred`, or `false` if it was already completed.
*
* **Example** (Completing a Deferred from an effect)
*
* ```ts
* import { Deferred, Effect } from "effect"
*
* const program = Effect.gen(function*() {
* const deferred = yield* Deferred.make<number>()
* const completed = yield* Deferred.complete(deferred, Effect.succeed(42))
* console.log(completed) // true
*
* const value = yield* Deferred.await(deferred)
* console.log(value) // 42
* })
* ```
*
* @see {@link completeWith} for storing an effect directly without memoizing its result
*
* @category completion
* @since 2.0.0
*/
export const complete = /*#__PURE__*/dual(2, (self, effect) => internalEffect.suspend(() => self.effect ? internalEffect.succeed(false) : into(effect, self)));
/**
* Attempts to complete the `Deferred` with the specified effect directly.
*
* **When to use**
*
* Use to store an already environment-free effect as the completion without
* running it during completion.
*
* **Details**
*
* The returned effect succeeds with `true` when this call completed the
* `Deferred`, or `false` if it was already completed.
*
* **Gotchas**
*
* The supplied effect is not memoized by `completeWith`; each awaiter may run
* the stored effect independently.
*
* **Example** (Completing a Deferred with an effect)
*
* ```ts
* import { Deferred, Effect } from "effect"
*
* const program = Effect.gen(function*() {
* const deferred = yield* Deferred.make<number>()
* const completed = yield* Deferred.completeWith(deferred, Effect.succeed(42))
* console.log(completed) // true
*
* const value = yield* Deferred.await(deferred)
* console.log(value) // 42
* })
* ```
*
* @see {@link complete} for running an effect once and sharing its result
* @see {@link done} for completing from an already computed `Exit`
*
* @category completion
* @since 2.0.0
*/
export const completeWith = /*#__PURE__*/dual(2, (self, effect) => internalEffect.sync(() => doneUnsafe(self, effect)));
/**
* Completes the `Deferred` with the specified `Exit` value, which will be
* propagated to all fibers waiting on the value of the `Deferred`.
*
* **When to use**
*
* Use to complete a `Deferred` from an already computed `Exit`.
*
* **Details**
*
* The returned effect succeeds with `true` when this call completed the
* `Deferred`, or `false` if it was already completed.
*
* **Example** (Completing a Deferred with an Exit)
*
* ```ts
* import { Deferred, Effect, Exit } from "effect"
*
* const program = Effect.gen(function*() {
* const deferred = yield* Deferred.make<number>()
* yield* Deferred.done(deferred, Exit.succeed(42))
*
* const value = yield* Deferred.await(deferred)
* console.log(value) // 42
* })
* ```
*
* @see {@link complete} for completing from an effect and memoizing its result
* @see {@link completeWith} for storing an effect directly
* @see {@link succeed} for completing with a success value
* @see {@link failCause} for completing with a failure cause
*
* @category completion
* @since 2.0.0
*/
export const done = completeWith;
/**
* Attempts to complete the `Deferred` with the specified error.
*
* **When to use**
*
* Use to complete a `Deferred` with a typed failure value.
*
* **Details**
*
* Fibers waiting on the `Deferred` fail with that error only if this call
* completes it. The returned effect succeeds with `true` when this call
* completed the `Deferred`, or `false` if it was already completed.
*
* **Example** (Failing a Deferred with an error)
*
* ```ts
* import { Deferred, Effect } from "effect"
*
* const program = Effect.gen(function*() {
* const deferred = yield* Deferred.make<number, string>()
* const success = yield* Deferred.fail(deferred, "Operation failed")
* console.log(success) // true
* })
* ```
*
* @category completion
* @since 2.0.0
*/
export const fail = /*#__PURE__*/dual(2, (self, error) => done(self, core.exitFail(error)));
/**
* Computes an error when the returned effect is run, then attempts to complete
* the `Deferred` with that error.
*
* **When to use**
*
* Use to lazily compute a typed failure value when the `Deferred` completion
* effect runs.
*
* **Details**
*
* Fibers waiting on the `Deferred` fail with the computed error only if this
* call completes it. The returned effect succeeds with `true` when this call
* completed the `Deferred`, or `false` if it was already completed.
*
* **Example** (Failing a Deferred with a lazy error)
*
* ```ts
* import { Deferred, Effect } from "effect"
*
* const program = Effect.gen(function*() {
* const deferred = yield* Deferred.make<number, string>()
* const success = yield* Deferred.failSync(deferred, () => "Lazy error")
* console.log(success) // true
* })
* ```
*
* @category completion
* @since 2.0.0
*/
export const failSync = /*#__PURE__*/dual(2, (self, evaluate) => internalEffect.suspend(() => fail(self, evaluate())));
/**
* Attempts to complete the `Deferred` with the specified `Cause`.
*
* **When to use**
*
* Use to complete a `Deferred` with a full failure cause.
*
* **Details**
*
* Fibers waiting on the `Deferred` observe that cause only if this call
* completes it. The returned effect succeeds with `true` when this call
* completed the `Deferred`, or `false` if it was already completed.
*
* **Example** (Failing a Deferred with a Cause)
*
* ```ts
* import { Cause, Deferred, Effect } from "effect"
*
* const program = Effect.gen(function*() {
* const deferred = yield* Deferred.make<number, string>()
* const success = yield* Deferred.failCause(
* deferred,
* Cause.fail("Operation failed")
* )
* console.log(success) // true
* })
* ```
*
* @category completion
* @since 2.0.0
*/
export const failCause = /*#__PURE__*/dual(2, (self, cause) => done(self, core.exitFailCause(cause)));
/**
* Computes a `Cause` when the returned effect is run, then attempts to
* complete the `Deferred` with that cause.
*
* **When to use**
*
* Use to lazily compute a full failure cause when the `Deferred` completion
* effect runs.
*
* **Details**
*
* Fibers waiting on the `Deferred` observe the computed cause only if this
* call completes it. The returned effect succeeds with `true` when this call
* completed the `Deferred`, or `false` if it was already completed.
*
* **Example** (Failing a Deferred with a lazy Cause)
*
* ```ts
* import { Cause, Deferred, Effect } from "effect"
*
* const program = Effect.gen(function*() {
* const deferred = yield* Deferred.make<number, string>()
* const success = yield* Deferred.failCauseSync(
* deferred,
* () => Cause.fail("Lazy error")
* )
* console.log(success) // true
* })
* ```
*
* @category completion
* @since 2.0.0
*/
export const failCauseSync = /*#__PURE__*/dual(2, (self, evaluate) => internalEffect.suspend(() => failCause(self, evaluate())));
/**
* Attempts to complete the `Deferred` with a defect.
*
* **When to use**
*
* Use to complete a `Deferred` with an unexpected defect.
*
* **Details**
*
* Fibers waiting on the `Deferred` die with that defect only if this call
* completes it. The returned effect succeeds with `true` when this call
* completed the `Deferred`, or `false` if it was already completed.
*
* **Example** (Killing a Deferred with a defect)
*
* ```ts
* import { Deferred, Effect } from "effect"
*
* const program = Effect.gen(function*() {
* const deferred = yield* Deferred.make<number>()
* const success = yield* Deferred.die(
* deferred,
* new Error("Something went wrong")
* )
* console.log(success) // true
* })
* ```
*
* @category completion
* @since 2.0.0
*/
export const die = /*#__PURE__*/dual(2, (self, defect) => done(self, core.exitDie(defect)));
/**
* Computes a defect when the returned effect is run, then attempts to complete
* the `Deferred` with that defect.
*
* **When to use**
*
* Use to lazily compute an unexpected defect when the completion effect runs.
*
* **Details**
*
* Fibers waiting on the `Deferred` die with the computed defect only if this
* call completes it. The returned effect succeeds with `true` when this call
* completed the `Deferred`, or `false` if it was already completed.
*
* **Example** (Killing a Deferred with a lazy defect)
*
* ```ts
* import { Deferred, Effect } from "effect"
*
* const program = Effect.gen(function*() {
* const deferred = yield* Deferred.make<number>()
* const success = yield* Deferred.dieSync(
* deferred,
* () => new Error("Lazy error")
* )
* console.log(success) // true
* })
* ```
*
* @category completion
* @since 2.0.0
*/
export const dieSync = /*#__PURE__*/dual(2, (self, evaluate) => internalEffect.suspend(() => die(self, evaluate())));
/**
* Attempts to complete the `Deferred` with interruption by the current fiber.
*
* **When to use**
*
* Use to complete a `Deferred` as interrupted by the current fiber.
*
* **Details**
*
* Fibers waiting on the `Deferred` are interrupted with the current fiber id
* only if this call completes it. The returned effect succeeds with `true`
* when this call completed the `Deferred`, or `false` if it was already
* completed.
*
* **Example** (Interrupting a Deferred)
*
* ```ts
* import { Deferred, Effect } from "effect"
*
* const program = Effect.gen(function*() {
* const deferred = yield* Deferred.make<number>()
* const success = yield* Deferred.interrupt(deferred)
* console.log(success) // true
* })
* ```
*
* @category completion
* @since 2.0.0
*/
export const interrupt = self => core.withFiber(fiber => interruptWith(self, fiber.id));
/**
* Attempts to complete the `Deferred` with interruption by the specified
* `FiberId`.
*
* **When to use**
*
* Use to complete a `Deferred` as interrupted by a specific fiber id.
*
* **Details**
*
* Fibers waiting on the `Deferred` are interrupted with that fiber id only if
* this call completes it. The returned effect succeeds with `true` when this
* call completed the `Deferred`, or `false` if it was already completed.
*
* **Example** (Interrupting a Deferred with a fiber id)
*
* ```ts
* import { Deferred, Effect } from "effect"
*
* const program = Effect.gen(function*() {
* const deferred = yield* Deferred.make<number>()
* const success = yield* Deferred.interruptWith(deferred, 42)
* console.log(success) // true
* })
* ```
*
* @category completion
* @since 2.0.0
*/
export const interruptWith = /*#__PURE__*/dual(2, (self, fiberId) => failCause(self, internalEffect.causeInterrupt(fiberId)));
/**
* Returns `true` if this `Deferred` has already been completed with a value or
* an error, `false` otherwise.
*
* **When to use**
*
* Use to check completion status inside an `Effect` workflow.
*
* **Example** (Checking Deferred completion)
*
* ```ts
* import { Deferred, Effect } from "effect"
*
* const program = Effect.gen(function*() {
* const deferred = yield* Deferred.make<number>()
* const beforeCompletion = yield* Deferred.isDone(deferred)
* console.log(beforeCompletion) // false
*
* yield* Deferred.succeed(deferred, 42)
* const afterCompletion = yield* Deferred.isDone(deferred)
* console.log(afterCompletion) // true
* })
* ```
*
* @category getters
* @since 2.0.0
*/
export const isDone = self => internalEffect.sync(() => isDoneUnsafe(self));
/**
* Returns whether this `Deferred` has already been completed synchronously.
*
* **When to use**
*
* Use to check `Deferred` completion synchronously in code that cannot return
* an `Effect`, such as low-level integration code.
*
* @see {@link isDone} for checking completion inside `Effect`
* @see {@link poll} for reading the completed effect when available
*
* @category getters
* @since 4.0.0
*/
export const isDoneUnsafe = self => self.effect !== undefined;
/**
* Returns the current completion effect as an `Option`. This returns
* `Option.some(effect)` when the `Deferred` is completed, `Option.none()`
* otherwise.
*
* **When to use**
*
* Use to inspect whether a `Deferred` is already completed and retrieve its
* stored completion effect when available.
*
* **Example** (Polling Deferred completion)
*
* ```ts
* import { Deferred, Effect } from "effect"
*
* const program = Effect.gen(function*() {
* const deferred = yield* Deferred.make<number>()
* const beforeCompletion = yield* Deferred.poll(deferred)
* console.log(beforeCompletion._tag === "None") // true
*
* yield* Deferred.succeed(deferred, 42)
* const afterCompletion = yield* Deferred.poll(deferred)
* console.log(afterCompletion._tag === "Some") // true
* })
* ```
*
* @category getters
* @since 2.0.0
*/
export function poll(self) {
return internalEffect.sync(() => Option.fromUndefinedOr(self.effect));
}
/**
* Attempts to complete the `Deferred` with the specified value.
*
* **When to use**
*
* Use to complete a `Deferred` with a successful value.
*
* **Details**
*
* Fibers waiting on the `Deferred` receive the value only if this call
* completes it. The returned effect succeeds with `true` when this call
* completed the `Deferred`, or `false` if it was already completed.
*
* **Example** (Completing a Deferred with a value)
*
* ```ts
* import { Deferred, Effect } from "effect"
*
* const program = Effect.gen(function*() {
* const deferred = yield* Deferred.make<number>()
* yield* Deferred.succeed(deferred, 42)
*
* const value = yield* Deferred.await(deferred)
* console.log(value) // 42
* })
* ```
*
* @category completion
* @since 2.0.0
*/
export const succeed = /*#__PURE__*/dual(2, (self, value) => done(self, core.exitSucceed(value)));
/**
* Computes a value when the returned effect is run, then attempts to complete
* the `Deferred` with that value.
*
* **When to use**
*
* Use to lazily compute a successful value when the `Deferred` completion
* effect runs.
*
* **Details**
*
* Fibers waiting on the `Deferred` receive the computed value only if this call
* completes it. The returned effect succeeds with `true` when this call
* completed the `Deferred`, or `false` if it was already completed.
*
* **Example** (Completing a Deferred with a lazy value)
*
* ```ts
* import { Deferred, Effect } from "effect"
*
* const program = Effect.gen(function*() {
* const deferred = yield* Deferred.make<number>()
* yield* Deferred.sync(deferred, () => 42)
*
* const value = yield* Deferred.await(deferred)
* console.log(value) // 42
* })
* ```
*
* @category completion
* @since 2.0.0
*/
export const sync = /*#__PURE__*/dual(2, (self, evaluate) => internalEffect.suspend(() => succeed(self, evaluate())));
/**
* Attempts to complete the `Deferred` synchronously with the specified
* completion effect.
*
* **When to use**
*
* Use to complete a `Deferred` synchronously in low-level code that already has
* the completion effect.
*
* **Details**
*
* This mutates the `Deferred` directly and should be reserved for low-level
* code; prefer the effectful completion APIs when possible. Returns `true` if
* this call completed the `Deferred`, or `false` if it was already completed.
*
* **Example** (Completing a Deferred unsafely)
*
* ```ts
* import { Deferred, Effect } from "effect"
*
* const deferred = Deferred.makeUnsafe<number>()
* const success = Deferred.doneUnsafe(deferred, Effect.succeed(42))
* console.log(success) // true
* ```
*
* @category unsafe
* @since 4.0.0
*/
export const doneUnsafe = (self, effect) => {
if (self.effect) return false;
self.effect = effect;
if (self.resumes) {
for (let i = 0; i < self.resumes.length; i++) {
self.resumes[i](effect);
}
self.resumes = undefined;
}
return true;
};
/**
* Runs an `Effect` and attempts to complete a `Deferred` with the effect's
* result.
*
* **When to use**
*
* Use to pipe an effect result into a `Deferred` while preserving success,
* failure, defects, and interruption.
*
* **Details**
*
* If the effect succeeds, fails, dies, or is interrupted, that result is used
* as the attempted completion. The returned effect cannot fail; it succeeds
* with `true` if it completed the `Deferred`, or `false` if the `Deferred` was
* already completed.
*
* **Example** (Completing a Deferred from an effect result)
*
* ```ts
* import { Deferred, Effect } from "effect"
*
* // Define an effect that succeeds
* const successEffect = Effect.succeed(42)
*
* const program = Effect.gen(function*() {
* // Create a deferred
* const deferred = yield* Deferred.make<number, string>()
*
* // Complete the deferred using the successEffect
* const isCompleted = yield* Deferred.into(successEffect, deferred)
*
* // Access the value of the deferred
* const value = yield* Deferred.await(deferred)
* console.log(value)
*
* return isCompleted
* })
*
* Effect.runPromise(program).then(console.log)
* // Output:
* // 42
* // true
* ```
*
* @category Synchronization Utilities
* @since 4.0.0
*/
export const into = /*#__PURE__*/dual(2, (self, deferred) => internalEffect.uninterruptibleMask(restore => internalEffect.flatMap(internalEffect.exit(restore(self)), exit => done(deferred, exit))));
//# sourceMappingURL=Deferred.js.map

Xet Storage Details

Size:
20.8 kB
·
Xet hash:
833abf41dc1ce5af4bd3f49b15b6e88994405838b45cf5ee3be43214681de399

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.