On This Page

Sharding and Supervision

25 symbols from @neontechspace/fluxerly/effect

Variables#

supervisor#

Run bot workers in separate Node processes on this machine

The create method validates the process plan when executed but starts no children. The start method launches those children once and waits for their assignment and configuration acknowledgements, not gateway READY. The waitForReady method waits for a later all-child READY state without starting or stopping the supervisor. The waitForClose method waits until every owned child exits. Cancelling that wait does not stop the children. The status method returns a frozen snapshot of each child's latest reported gateway state for its current process generation. The snapshot is local, not a simultaneous health check across processes

const supervisor: SupervisorTools

Each child module must execute supervisor.child.run, which owns a nested client and an inter-process communication (IPC) cleanup scope. The helper preserves the caller's Effect services and Cause. It asks the parent for a permit immediately before each fresh gateway Identify. Identify authenticates a new gateway session. Resuming an existing session needs no permit. Only one parent permit can be outstanding. The child confirms its synchronous Identify send or cancels before sending. The parent spaces fresh sends by at least one second, unless identify.coordinator paces them. A stalled child must stop and exit before another permit is issued, followed by a full spacing interval

The supervisor can size the plan at start with totalShards "auto", share the Identify budget through identify.coordinator and include each child's client diagnostics in status. Children keep resumable sessions through clientOptions.sharding.sessions. The children share Fluxer's limits per bot account through the parent. When one child is rate-limited globally, the parent holds the other children's REST requests until the same time. Member requests from all children share one count of 12 in any 11 seconds, and a members.iterateChunks request past it fails at once with reason rateLimit and retryAfterMs. A child that gets no answer from the parent within one second counts only its own member requests and logs supervisor.memberRequestsLocal once. Per-route REST rate limits stay per child, and other processes using the same token are not counted. It installs no signal handlers and does not terminate the process. After the configured graceful deadline, the parent can terminate only its own unresponsive child and still waits for its exit. A crashed child restarts by default, up to three times in a row with exponentially increasing delays. Set restart to false to turn this off. The childEnvironment, args and execArgv options configure children but never appear in status or failures. Child output follows childOutput: Lines are forwarded with a child label by default, and inherit or ignore can be chosen instead

TypeScript
import { Effect } from "effect"
import { supervisor } from "@neontechspace/fluxerly/effect"

export const workers = Effect.gen(function* () {
    const managed = yield* supervisor.create({
        entry: "/srv/bot-worker.js",
        totalShards: 2,
        assignments: [
            { id: "one", shardIds: [0] },
            { id: "two", shardIds: [1] },
        ],
    })
    yield* managed.start().pipe(
        Effect.andThen(managed.waitForClose()),
        Effect.ensuring(managed.shutdown()),
    )
    return managed.status()
})

Interfaces#

Supervisor#

Parent that starts and stops the child processes in one fixed local shard plan

Asynchronous methods return lazy Effects. Calling a method does not execute it, while status reads immediately. Creating the parent does not start children or arrange automatic cleanup when a Scope closes. Execute shutdown to release its processes. Expected failures use SupervisorError. Unexpected defects remain in the Effect cause

interface Supervisor

shutdown#

Ask owned children to stop and succeed only after their processes exit

After shutdownTimeoutMs, force-terminate an owned child that has not exited, then keep waiting for its exit. Calls made together or repeated later share the same cleanup. Once cleanup starts, interrupting a caller does not stop it. Shutdown before startup closes the parent without launching children. Succeeds even after a supervisor failure or a child's message-channel loss. It does not erase waitForClose's retained failure

shutdown(): Effect<void>
Returns
Effect<void>

start#

Start the configured children and succeed when each child acknowledges its assignment and finishes configure

This means setup finished. It does not mean any gateway connection is ready. Execute waitForReady to observe connected gateway sessions. Concurrent executions share startup. Executing again does not launch extra children or await replacement startup. Interruption stops the whole supervisor, including when another caller is waiting for the same startup, and awaits owned process exits. Expected failure also awaits those exits. Start during or after shutdown fails with reason closed. With totalShards "auto" it first counts the bot's communities, and a failed count fails with reason shardCount. If a child remains alive after losing its message channel for shutdownTimeoutMs, pending startup fails with closed after cleanup

start(): Effect<void, SupervisorError>start(): Effect<
  void, SupervisorError
>
Returns
Effect<void, SupervisorError>
Fails with

status#

Return one immutable safe local status snapshot without child output, environment, arguments or paths

status(): SupervisorStatus

waitForClose#

Wait until the supervisor's lifetime ends and its owned child processes have exited

Succeeds after normal shutdown or fails with the retained SupervisorError after failure, even on a later execution. Does not start or stop the parent. Before startup, waits until a later shutdown or failure. Interrupting this wait detaches only the observer without stopping the supervisor

waitForClose(): Effect<void, SupervisorError>waitForClose(): Effect<
  void, SupervisorError
>
Returns
Effect<void, SupervisorError>
Fails with

waitForReady#

Succeed when every current child has reported its aggregate gateway state as Connected

Execute start first. This checks the latest child reports. It does not prove that every process is healthy at the same instant or will stay ready. Losing a child's message channel clears its readiness immediately. A later execution waits for current readiness again. Interrupting this wait cancels only this observer without stopping or restarting a child. An idle, stopping or closed supervisor fails with reason closed. A failed supervisor returns its retained failure

waitForReady(): Effect<void, SupervisorError>waitForReady(): Effect<
  void, SupervisorError
>
Returns
Effect<void, SupervisorError>
Fails with

SupervisorChildContext#

Client and fixed shard assignment available to configure before the helper starts the gateway connection

interface SupervisorChildContext
assignment#

Fixed assignment for this child process

It cannot be changed during this run

SupervisorAssignment
client#

Native client created and owned by child.run

Register application behavior rather than starting or stopping this client

Client

SupervisorChildOptions#

Bot credentials, native client settings and setup Effect for a module launched by a supervisor

E represents application failures and R represents required services. The helper provides Scope, which closes resources when this child run ends. Other services remain caller-provided. Unknown option keys fail with ConfigurationError before waiting for the parent, with a suggested name when one is close

interface SupervisorChildOptions<E = never, R = never>interface SupervisorChildOptions<
  E = never, R = never
>
clientOptions optional#

Every native client setting except token is read by property name and copied before configure, including inherited and non-enumerable properties

The supervisor assigns the shards, so sharding accepts only sessions. Runtime validation rejects a token, a shard plan or identify coordinator in sharding, and any other own key that is not a client option, with ConfigurationError

& Omit<ClientOptions<E, R, undefined>, "token" | "sharding">
& { readonly sharding?: SupervisorChildSharding }& Omit<
    ClientOptions<E, R, undefined>,
    "token" | "sharding"
  >
& {
    readonly sharding?:
      SupervisorChildSharding
  }
configure#

Register subscriptions and local application behavior before the helper executes client.run

Complete this Effect after setup, rather than keeping it running until the bot stops. Do not execute client.run, connect or shutdown here. Scope-bound tasks and resources belong to the helper's nested Scope, which closes before child.run settles. Parent stop interrupts unfinished configuration and awaits its cleanup without starting the client afterward. Application failures remain typed as E. Defects and cleanup failures remain in the Effect cause

(context: SupervisorChildContext) => Effect<void, E, Scope | R>(context: SupervisorChildContext)
  => Effect<void, E, Scope | R>
token#

Bot token for the client created by child.run, such as process.env.FLUXER_BOT_TOKEN

The parent assignment does not supply this credential. A missing or blank value fails child.run with ConfigurationError once the assignment arrives, as createClient does, and the parent sees the child fail during configuration

string | undefined

SupervisorTools#

Create a local parent supervisor or run its child module using the Effect public API

interface SupervisorTools
child#

Child-module helper

Execute run inside the module selected by the parent's entry option

{
    run<E = never, R = never>(
        options: SupervisorChildOptions<E, R>
    ): Effect<
        void,
        | ConfigurationError | SupervisorChildError | ConnectError
        | E,
        Exclude<R, Scope>
    >
}{
  run<E = never, R = never>(
    options:
      SupervisorChildOptions<E, R>
  ): Effect<
    void,
    | ConfigurationError
    | SupervisorChildError
    | ConnectError | E,
    Exclude<R, Scope>
  >
}

create#

Return a lazy Effect that validates and copies options, then succeeds with an idle supervisor

Invalid options are misuse and die with ConfigurationError. Unknown keys in parent, assignment, restart and Identify options include a suggested name when one is close. Does not start a process or check whether the entry module can execute. Launch failures are reported by start. The parent has no automatic Scope finalizer. Arrange to execute its shutdown Effect when the application stops

create(options: SupervisorOptions): Effect<Supervisor>create(
  options: SupervisorOptions
): Effect<Supervisor>

Parameters

Re-Exports#

Declared in JavaScript & TypeScript and documented there. Import them from @neontechspace/fluxerly/effect as well

fileSessionStore#
Create a SessionStore that keeps each shard's snapshot in its own file, shard-ID.json, inside one directory
IdentifyCoordinator#
Coordinates Identify commands for shards that start new sessions, so several processes serving one bot can respect Fluxer's shared Identify budget
SessionSnapshot#
The resumable state of one shard's gateway session, saved at shutdown and offered again at the next startup
SessionStore#
Persist resumable gateway sessions across restarts
ShardRecoveryDiagnostic#
Connection-attempt snapshot for one shard, a gateway connection owned by this client
ShardState#
Frozen connection-state snapshot for one gateway shard owned by this client
ShardingOptions#
Divide the bot's community events among gateway connections called shards
SupervisorAssignment#
Gateway connections assigned to one child process by its parent supervisor
SupervisorAssignmentOptions#
Name and shard IDs for one Node process that the supervisor starts and stops
SupervisorChildDiagnostics#
One diagnostics snapshot a child sent to its parent: Gateway latency and shard states, REST queue use, cache use and running counters, as its client's diagnostics method returns them
SupervisorChildSharding#
Sharding settings a supervised child may add to the shards its parent assigns
SupervisorChildStatus#
Frozen snapshot of one child assignment and its current process, without launch settings or child output
SupervisorFileUrl#
File URL identifying the JavaScript module to run in each child process
SupervisorIdentifyOptions#
Space out new gateway session starts across the children owned by one supervisor
SupervisorOptions#
Plan for running bot gateway connections in separate local Node processes
SupervisorRestartOptions#
Restart a child process after it exits, unless the supervisor has begun shutdown or failed
SupervisorStatus#
Immutable safe local snapshot without child paths, arguments, environment or stdio
SupervisorWaitOptions#
Cancel one default-API waitForReady call without stopping or restarting the supervisor
SupervisorChildState#
Local process state for a fixed child assignment, not its gateway connection state
SupervisorState#
Local parent-process lifetime state, not the bot's gateway readiness