1/**
2 * Register effects that should have one active owner in an Effect cluster.
3 *
4 * `Singleton.make` wraps `Sharding.registerSingleton` in a `Layer`. When the
5 * local runner owns the shard for the singleton's name and shard group,
6 * sharding starts the effect; when ownership moves or the layer scope closes,
7 * the running fiber is interrupted and the registration is removed.
8 *
9 * @stability unstable
10 * @since 4.0.0
11 */
12import * as Effect from "../Effect.ts"
13import * as Layer from "../Layer.ts"
14import type { Scope } from "../Scope.ts"
15import { Sharding } from "./Sharding.ts"
16
17/**
18 * Creates a layer that registers a singleton effect with `Sharding` under the
19 * specified name and optional shard group.
20 *
21 * **When to use**
22 *
23 * Use to register a cluster-wide background effect as a `Layer`, so the effect
24 * is started only by the runner that currently owns the singleton's shard.
25 *
26 * **Details**
27 *
28 * The returned layer requires `Sharding` and the services needed by `run`,
29 * except for `Scope`. The registration is scoped to the layer; closing the
30 * layer removes the singleton registration and stops the singleton fiber if it
31 * is running.
32 *
33 * **Gotchas**
34 *
35 * - Registering the same singleton name in the same shard group more than once
36 * dies during registration.
37 * - A `run` effect that completes normally is kept alive until the registration
38 * scope closes or shard ownership moves.
39 * - Failures from `run` are converted to defects, so handle expected failures
40 * inside `run` when the singleton should keep running.
41 *
42 * @see {@link Sharding} for the lower-level service that registers singletons and manages shard ownership
43 *
44 * @stability unstable
45 * @category constructors
46 * @since 4.0.0
47 */
48export const make = <E, R>(
49 name: string,
50 run: Effect.Effect<void, E, R>,
51 options?: {
52 readonly shardGroup?: string | undefined
53 }
54): Layer.Layer<never, never, Sharding | Exclude<R, Scope>> =>
55 Layer.effectDiscard(Effect.gen(function*() {
56 const sharding = yield* Sharding
57 yield* sharding.registerSingleton(name, run, options)
58 }))