import * as Effect from "./Effect.ts"; import type { Inspectable } from "./Inspectable.ts"; import type { Pipeable } from "./Pipeable.ts"; import type * as Scope from "./Scope.ts"; import * as TxQueue from "./TxQueue.ts"; declare const TypeId = "~effect/TxPubSub"; /** * A TxPubSub represents a transactional publish/subscribe hub that broadcasts messages * to all current subscribers using Software Transactional Memory (STM) semantics. * * **Example** (Subscribing to a transactional pub/sub) * * ```ts import.meta.vitest * import { Effect, TxPubSub, TxQueue } from "effect" * * const program = Effect.gen(function*() { * const hub = yield* TxPubSub.unbounded() * * return yield* Effect.scoped( * Effect.gen(function*() { * const sub = yield* TxPubSub.subscribe(hub) * yield* TxPubSub.publish(hub, "hello") * return yield* TxQueue.take(sub) * }) * ) * }) * * await Effect.runPromise(program) // => "hello" * ``` * * @stability stable * @category models * @since 4.0.0 */ export interface TxPubSub extends Inspectable, Pipeable { readonly [TypeId]: typeof TypeId; readonly strategy: "bounded" | "unbounded" | "dropping" | "sliding"; readonly capacity: number; } /** * Creates a bounded TxPubSub with the specified capacity. When a subscriber's * queue is full, the publisher will retry the transaction until space is available. * * **Example** (Creating a bounded pub/sub) * * ```ts import.meta.vitest * import { Effect, TxPubSub, TxQueue } from "effect" * * const program = Effect.gen(function*() { * const hub = yield* TxPubSub.bounded(16) * * return yield* Effect.scoped( * Effect.gen(function*() { * const sub = yield* TxPubSub.subscribe(hub) * yield* TxPubSub.publish(hub, 42) * return yield* TxQueue.take(sub) * }) * ) * }) * * await Effect.runPromise(program) // => 42 * ``` * * @stability stable * @category constructors * @since 2.0.0 */ export declare const bounded: (capacity: number) => Effect.Effect>; /** * Creates a dropping TxPubSub with the specified capacity. When a subscriber's * queue is full, the message is dropped for that subscriber. * * **Example** (Creating a dropping pub/sub) * * ```ts import.meta.vitest * import { Effect, TxPubSub, TxQueue } from "effect" * * const program = Effect.gen(function*() { * const hub = yield* TxPubSub.dropping(2) * * return yield* Effect.scoped( * Effect.gen(function*() { * const sub = yield* TxPubSub.subscribe(hub) * yield* TxPubSub.publish(hub, 1) * yield* TxPubSub.publish(hub, 2) * yield* TxPubSub.publish(hub, 3) // dropped * const v1 = yield* TxQueue.take(sub) * const v2 = yield* TxQueue.take(sub) * return [v1, v2] * }) * ) * }) * * await Effect.runPromise(program) // => [1, 2] * ``` * * @stability stable * @category constructors * @since 2.0.0 */ export declare const dropping: (capacity: number) => Effect.Effect>; /** * Creates a sliding TxPubSub with the specified capacity. When a subscriber's * queue is full, the oldest message in that subscriber's queue is dropped. * * **Example** (Creating a sliding pub/sub) * * ```ts import.meta.vitest * import { Effect, TxPubSub, TxQueue } from "effect" * * const program = Effect.gen(function*() { * const hub = yield* TxPubSub.sliding(2) * * return yield* Effect.scoped( * Effect.gen(function*() { * const sub = yield* TxPubSub.subscribe(hub) * yield* TxPubSub.publish(hub, 1) * yield* TxPubSub.publish(hub, 2) * yield* TxPubSub.publish(hub, 3) // evicts 1 * return yield* TxQueue.take(sub) * }) * ) * }) * * await Effect.runPromise(program) // => 2 * ``` * * @stability stable * @category constructors * @since 2.0.0 */ export declare const sliding: (capacity: number) => Effect.Effect>; /** * Creates an unbounded TxPubSub with unlimited capacity. Messages are always accepted. * * **Example** (Creating an unbounded pub/sub) * * ```ts import.meta.vitest * import { Effect, TxPubSub, TxQueue } from "effect" * * const program = Effect.gen(function*() { * const hub = yield* TxPubSub.unbounded() * * return yield* Effect.scoped( * Effect.gen(function*() { * const sub = yield* TxPubSub.subscribe(hub) * yield* TxPubSub.publish(hub, "msg") * return yield* TxQueue.take(sub) * }) * ) * }) * * await Effect.runPromise(program) // => "msg" * ``` * * @stability stable * @category constructors * @since 2.0.0 */ export declare const unbounded: () => Effect.Effect>; /** * Returns the capacity of the TxPubSub. * * **Example** (Reading pub/sub capacity) * * ```ts import.meta.vitest * import { Effect, TxPubSub } from "effect" * * const program = Effect.gen(function*() { * const hub = yield* TxPubSub.bounded(16) * return TxPubSub.capacity(hub) * }) * * await Effect.runPromise(program) // => 16 * ``` * * @stability stable * @category getters * @since 2.0.0 */ export declare const capacity: (self: TxPubSub) => number; /** * Returns the current number of messages across all subscriber queues (the max). * * **Example** (Reading subscriber queue size) * * ```ts import.meta.vitest * import { Effect, TxPubSub, TxQueue } from "effect" * * const program = Effect.gen(function*() { * const hub = yield* TxPubSub.unbounded() * * return yield* Effect.scoped( * Effect.gen(function*() { * const sub = yield* TxPubSub.subscribe(hub) * yield* TxPubSub.publish(hub, 1) * yield* TxPubSub.publish(hub, 2) * return yield* TxPubSub.size(hub) * }) * ) * }) * * await Effect.runPromise(program) // => 2 * ``` * * @stability stable * @category getters * @since 2.0.0 */ export declare const size: (self: TxPubSub) => Effect.Effect; /** * Checks whether the TxPubSub has no pending messages (all subscriber queues are empty). * * **Example** (Checking whether a pub/sub is empty) * * ```ts import.meta.vitest * import { Effect, TxPubSub } from "effect" * * const program = Effect.gen(function*() { * const hub = yield* TxPubSub.unbounded() * return yield* TxPubSub.isEmpty(hub) * }) * * await Effect.runPromise(program) // => true * ``` * * @stability stable * @category predicates * @since 2.0.0 */ export declare const isEmpty: (self: TxPubSub) => Effect.Effect; /** * Checks whether any subscriber queue has pending messages. * A pub/sub with no subscribers is empty, even if values have been published. * * **Example** (Checking whether a pub/sub is non-empty) * * ```ts import.meta.vitest * import { Effect, TxPubSub } from "effect" * * const program = Effect.gen(function*() { * const hub = yield* TxPubSub.unbounded() * const empty = yield* TxPubSub.isNonEmpty(hub) * * const nonEmpty = yield* Effect.scoped(Effect.gen(function*() { * yield* TxPubSub.subscribe(hub) * yield* TxPubSub.publish(hub, 1) * return yield* TxPubSub.isNonEmpty(hub) * })) * return [empty, nonEmpty] as const * }) * * await Effect.runPromise(program) // => [false, true] * ``` * * @stability stable * @category predicates * @since 4.0.0 */ export declare const isNonEmpty: (self: TxPubSub) => Effect.Effect; /** * Checks whether any subscriber queue is at capacity. * * **Example** (Checking whether a pub/sub is full) * * ```ts import.meta.vitest * import { Effect, TxPubSub } from "effect" * * const program = Effect.gen(function*() { * const hub = yield* TxPubSub.bounded(2) * return yield* TxPubSub.isFull(hub) * }) * * await Effect.runPromise(program) // => false * ``` * * @stability stable * @category predicates * @since 2.0.0 */ export declare const isFull: (self: TxPubSub) => Effect.Effect; /** * Checks whether the TxPubSub has been shut down. * * **Example** (Checking whether a pub/sub is shut down) * * ```ts import.meta.vitest * import { Effect, TxPubSub } from "effect" * * const program = Effect.gen(function*() { * const hub = yield* TxPubSub.unbounded() * const before = yield* TxPubSub.isShutdown(hub) * yield* TxPubSub.shutdown(hub) * return [before, yield* TxPubSub.isShutdown(hub)] * }) * * await Effect.runPromise(program) // => [false, true] * ``` * * @stability stable * @category predicates * @since 2.0.0 */ export declare const isShutdown: (self: TxPubSub) => Effect.Effect; /** * Publishes a message to all current subscribers. * * **Details** * * Returns `true` if the message was delivered to all subscribers, or `false` if the hub is shut down or the message was dropped for any subscriber. For the bounded strategy, the transaction retries if any subscriber queue is full. For the sliding strategy, full subscriber queues drop their oldest messages. For the dropping strategy, full subscriber queues drop the new message and the operation returns `false`. * * **Example** (Publishing a message to subscribers) * * ```ts import.meta.vitest * import { Effect, TxPubSub, TxQueue } from "effect" * * const program = Effect.gen(function*() { * const hub = yield* TxPubSub.unbounded() * * // No subscribers - publish is a no-op * const r1 = yield* TxPubSub.publish(hub, "no one listening") * * const msg = yield* Effect.scoped( * Effect.gen(function*() { * const sub = yield* TxPubSub.subscribe(hub) * yield* TxPubSub.publish(hub, "hello") * return yield* TxQueue.take(sub) * }) * ) * return [r1, msg] * }) * * await Effect.runPromise(program) // => [true, "hello"] * ``` * * @stability stable * @category mutations * @since 2.0.0 */ export declare const publish: { /** * Publishes a message to all current subscribers. * * **Details** * * Returns `true` if the message was delivered to all subscribers, or `false` if the hub is shut down or the message was dropped for any subscriber. For the bounded strategy, the transaction retries if any subscriber queue is full. For the sliding strategy, full subscriber queues drop their oldest messages. For the dropping strategy, full subscriber queues drop the new message and the operation returns `false`. * * **Example** (Publishing a message to subscribers) * * ```ts import.meta.vitest * import { Effect, TxPubSub, TxQueue } from "effect" * * const program = Effect.gen(function*() { * const hub = yield* TxPubSub.unbounded() * * // No subscribers - publish is a no-op * const r1 = yield* TxPubSub.publish(hub, "no one listening") * * const msg = yield* Effect.scoped( * Effect.gen(function*() { * const sub = yield* TxPubSub.subscribe(hub) * yield* TxPubSub.publish(hub, "hello") * return yield* TxQueue.take(sub) * }) * ) * return [r1, msg] * }) * * await Effect.runPromise(program) // => [true, "hello"] * ``` * * @stability stable * @category mutations * @since 2.0.0 */ (value: A): (self: TxPubSub) => Effect.Effect; /** * Publishes a message to all current subscribers. * * **Details** * * Returns `true` if the message was delivered to all subscribers, or `false` if the hub is shut down or the message was dropped for any subscriber. For the bounded strategy, the transaction retries if any subscriber queue is full. For the sliding strategy, full subscriber queues drop their oldest messages. For the dropping strategy, full subscriber queues drop the new message and the operation returns `false`. * * **Example** (Publishing a message to subscribers) * * ```ts import.meta.vitest * import { Effect, TxPubSub, TxQueue } from "effect" * * const program = Effect.gen(function*() { * const hub = yield* TxPubSub.unbounded() * * // No subscribers - publish is a no-op * const r1 = yield* TxPubSub.publish(hub, "no one listening") * * const msg = yield* Effect.scoped( * Effect.gen(function*() { * const sub = yield* TxPubSub.subscribe(hub) * yield* TxPubSub.publish(hub, "hello") * return yield* TxQueue.take(sub) * }) * ) * return [r1, msg] * }) * * await Effect.runPromise(program) // => [true, "hello"] * ``` * * @stability stable * @category mutations * @since 2.0.0 */ (self: TxPubSub, value: A): Effect.Effect; }; /** * Publishes all messages from an iterable to all current subscribers. * * **Details** * * Returns `true` if all messages were delivered to all subscribers. * * **Example** (Publishing multiple messages to subscribers) * * ```ts import.meta.vitest * import { Effect, TxPubSub, TxQueue } from "effect" * * const program = Effect.gen(function*() { * const hub = yield* TxPubSub.unbounded() * * return yield* Effect.scoped( * Effect.gen(function*() { * const sub = yield* TxPubSub.subscribe(hub) * yield* TxPubSub.publishAll(hub, [1, 2, 3]) * const v1 = yield* TxQueue.take(sub) * const v2 = yield* TxQueue.take(sub) * const v3 = yield* TxQueue.take(sub) * return [v1, v2, v3] * }) * ) * }) * * await Effect.runPromise(program) // => [1, 2, 3] * ``` * * @stability stable * @category mutations * @since 2.0.0 */ export declare const publishAll: { /** * Publishes all messages from an iterable to all current subscribers. * * **Details** * * Returns `true` if all messages were delivered to all subscribers. * * **Example** (Publishing multiple messages to subscribers) * * ```ts import.meta.vitest * import { Effect, TxPubSub, TxQueue } from "effect" * * const program = Effect.gen(function*() { * const hub = yield* TxPubSub.unbounded() * * return yield* Effect.scoped( * Effect.gen(function*() { * const sub = yield* TxPubSub.subscribe(hub) * yield* TxPubSub.publishAll(hub, [1, 2, 3]) * const v1 = yield* TxQueue.take(sub) * const v2 = yield* TxQueue.take(sub) * const v3 = yield* TxQueue.take(sub) * return [v1, v2, v3] * }) * ) * }) * * await Effect.runPromise(program) // => [1, 2, 3] * ``` * * @stability stable * @category mutations * @since 2.0.0 */ (values: Iterable): (self: TxPubSub) => Effect.Effect; /** * Publishes all messages from an iterable to all current subscribers. * * **Details** * * Returns `true` if all messages were delivered to all subscribers. * * **Example** (Publishing multiple messages to subscribers) * * ```ts import.meta.vitest * import { Effect, TxPubSub, TxQueue } from "effect" * * const program = Effect.gen(function*() { * const hub = yield* TxPubSub.unbounded() * * return yield* Effect.scoped( * Effect.gen(function*() { * const sub = yield* TxPubSub.subscribe(hub) * yield* TxPubSub.publishAll(hub, [1, 2, 3]) * const v1 = yield* TxQueue.take(sub) * const v2 = yield* TxQueue.take(sub) * const v3 = yield* TxQueue.take(sub) * return [v1, v2, v3] * }) * ) * }) * * await Effect.runPromise(program) // => [1, 2, 3] * ``` * * @stability stable * @category mutations * @since 2.0.0 */ (self: TxPubSub, values: Iterable): Effect.Effect; }; /** * Subscribes to the TxPubSub, returning a scoped `TxQueue` for messages published after subscription. * * **Details** * * The returned queue uses the hub's capacity strategy: bounded subscriptions backpressure publishers when full, dropping subscriptions may miss new messages when full, and sliding subscriptions may evict older queued messages. The subscription is automatically removed when the scope is closed. * * **Example** (Subscribing multiple queues) * * ```ts import.meta.vitest * import { Effect, TxPubSub, TxQueue } from "effect" * * const program = Effect.gen(function*() { * const hub = yield* TxPubSub.unbounded() * * return yield* Effect.scoped( * Effect.gen(function*() { * const sub1 = yield* TxPubSub.subscribe(hub) * const sub2 = yield* TxPubSub.subscribe(hub) * * yield* TxPubSub.publish(hub, "broadcast") * * const msg1 = yield* TxQueue.take(sub1) * const msg2 = yield* TxQueue.take(sub2) * return [msg1, msg2] * }) * ) * }) * * await Effect.runPromise(program) // => ["broadcast", "broadcast"] * ``` * * @stability unstable * @category mutations * @since 2.0.0 */ export declare const subscribe: (self: TxPubSub) => Effect.Effect, never, Scope.Scope>; /** * Creates a subscriber queue and registers it with the pub/sub. * * **When to use** * * Use to create and register a subscriber queue inside a larger transaction * when registration must be atomic with other Tx operations. * * **Details** * * This is the transactional acquire step of `subscribe`, exposed so that callers can compose it with other Tx operations in a single transaction, such as `TxSubscriptionRef.changes`. * * @see {@link subscribe} for the scoped acquire and release wrapper when no custom transaction composition is needed * @see {@link releaseSubscriber} to remove and shut down a queue returned by `acquireSubscriber` * * @stability unstable * @category mutations * @since 4.0.0 */ export declare const acquireSubscriber: (self: TxPubSub) => Effect.Effect, never, Effect.Transaction>; /** * Removes a subscriber queue from the pub/sub and shuts it down. * * **When to use** * * Use to release a manually acquired subscriber queue inside a larger * transaction, removing it from the pub/sub and shutting it down together with * related transactional cleanup. * * **Details** * * This is the transactional release step of `subscribe`, exposed so that callers can compose it with other Tx operations in a single transaction. * * **Gotchas** * * The supplied queue is shut down after being removed, so callers should pass a * queue acquired for this pub/sub. * * @see {@link acquireSubscriber} for the matching transactional acquire step * @see {@link subscribe} for the scoped acquire and release wrapper * * @stability unstable * @category mutations * @since 4.0.0 */ export declare const releaseSubscriber: { /** * Removes a subscriber queue from the pub/sub and shuts it down. * * **When to use** * * Use to release a manually acquired subscriber queue inside a larger * transaction, removing it from the pub/sub and shutting it down together with * related transactional cleanup. * * **Details** * * This is the transactional release step of `subscribe`, exposed so that callers can compose it with other Tx operations in a single transaction. * * **Gotchas** * * The supplied queue is shut down after being removed, so callers should pass a * queue acquired for this pub/sub. * * @see {@link acquireSubscriber} for the matching transactional acquire step * @see {@link subscribe} for the scoped acquire and release wrapper * * @stability unstable * @category mutations * @since 4.0.0 */ (queue: TxQueue.TxQueue): (self: TxPubSub) => Effect.Effect; /** * Removes a subscriber queue from the pub/sub and shuts it down. * * **When to use** * * Use to release a manually acquired subscriber queue inside a larger * transaction, removing it from the pub/sub and shutting it down together with * related transactional cleanup. * * **Details** * * This is the transactional release step of `subscribe`, exposed so that callers can compose it with other Tx operations in a single transaction. * * **Gotchas** * * The supplied queue is shut down after being removed, so callers should pass a * queue acquired for this pub/sub. * * @see {@link acquireSubscriber} for the matching transactional acquire step * @see {@link subscribe} for the scoped acquire and release wrapper * * @stability unstable * @category mutations * @since 4.0.0 */ (self: TxPubSub, queue: TxQueue.TxQueue): Effect.Effect; }; /** * Shuts down the TxPubSub and all subscriber queues registered at the time of shutdown. * * **Details** * * After shutdown, `publish` and `publishAll` return `false`, and `awaitShutdown` completes. The operation is idempotent. * * **Gotchas** * * Subscribers acquired after shutdown are not automatically shut down by this call. * * **Example** (Shutting down a pub/sub) * * ```ts import.meta.vitest * import { Effect, TxPubSub } from "effect" * * const program = Effect.gen(function*() { * const hub = yield* TxPubSub.unbounded() * yield* TxPubSub.shutdown(hub) * * const shut = yield* TxPubSub.isShutdown(hub) * const accepted = yield* TxPubSub.publish(hub, 1) * return [shut, accepted] * }) * * await Effect.runPromise(program) // => [true, false] * ``` * * @stability stable * @category mutations * @since 2.0.0 */ export declare const shutdown: (self: TxPubSub) => Effect.Effect; /** * Waits for the TxPubSub to be shut down. * * **Example** (Waiting for shutdown) * * ```ts import.meta.vitest * import { Effect, Fiber, TxPubSub } from "effect" * * const program = Effect.gen(function*() { * const hub = yield* TxPubSub.unbounded() * * const fiber = yield* Effect.forkChild(TxPubSub.awaitShutdown(hub)) * yield* TxPubSub.shutdown(hub) * yield* Fiber.await(fiber) * return yield* TxPubSub.isShutdown(hub) * }) * * await Effect.runPromise(program) // => true * ``` * * @stability stable * @category mutations * @since 2.0.0 */ export declare const awaitShutdown: (self: TxPubSub) => Effect.Effect; /** * Checks whether the given value is a TxPubSub. * * **Example** (Checking for a TxPubSub) * * ```ts import.meta.vitest * import { TxPubSub } from "effect" * * const someValue: unknown = {} * TxPubSub.isTxPubSub(someValue) // => false * ``` * * @stability stable * @category guards * @since 4.0.0 */ export declare const isTxPubSub: (u: unknown) => u is TxPubSub; export {}; //# sourceMappingURL=TxPubSub.d.ts.map