lunibee 0.3.2 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Leadership between several coordinators, so a standby `ClusterManager` can
3
+ * take over when the active one dies. Only the holder of the lock runs
4
+ * clusters; see `ClusterManagerOptions.leader`.
5
+ */
6
+ export interface LeaderLock {
7
+ /**
8
+ * Takes the lock for `ttlMs`, or extends it when this process already
9
+ * holds it. Resolves `true` while this process is the leader, `false` when
10
+ * another one holds it. A rejection counts as "unknown".
11
+ */
12
+ acquire(ttlMs: number): Promise<boolean>;
13
+ /** Gives the lock up if this process holds it. */
14
+ release(): Promise<void>;
15
+ }
16
+ /** The part of a Redis client the lock uses. `Bun.RedisClient` works as it is; for ioredis pass `{ send: (c, a) => redis.call(c, ...a) }`. */
17
+ export interface LeaderRedisClient {
18
+ send(command: string, args: string[]): Promise<unknown>;
19
+ }
20
+ /** Options for {@link RedisLeaderLock}. */
21
+ export interface RedisLeaderLockOptions {
22
+ client: LeaderRedisClient;
23
+ /** The key every coordinator of one deployment shares. Default `lunibee:cluster:leader`. */
24
+ key?: string;
25
+ /** This coordinator's identity in the key. Default: a random UUID. Must differ between coordinators. */
26
+ token?: string;
27
+ }
28
+ /** A {@link LeaderLock} on one Redis key, with an expiry so a dead leader's lock lapses on its own. */
29
+ export declare class RedisLeaderLock implements LeaderLock {
30
+ #private;
31
+ constructor(options: RedisLeaderLockOptions);
32
+ acquire(ttlMs: number): Promise<boolean>;
33
+ release(): Promise<void>;
34
+ }
@@ -62,6 +62,14 @@ export interface RemoteOptions {
62
62
  clientAddress?: (request: Request, peer: string | undefined) => string;
63
63
  /** Also run clusters on the coordinator's own machine. Default false: clusters run on the hosts only. */
64
64
  local?: boolean;
65
+ /**
66
+ * When a host is lost, restart its clusters on the connected host (or
67
+ * `local`) running the fewest, once the lost host has certainly fenced
68
+ * itself (two leases after the coordinator dropped it). They stay there
69
+ * when the host comes back. Default true; `false` restarts them on the
70
+ * same host only, so they wait for it.
71
+ */
72
+ moveClusters?: boolean;
65
73
  }
66
74
  /** A host as the coordinator sees it. */
67
75
  export interface HostStatus {
@@ -115,6 +123,16 @@ export declare class RemoteHosts {
115
123
  get port(): number | undefined;
116
124
  /** Host IDs that are connected now, sorted. */
117
125
  connected(): string[];
126
+ /** Whether `hostId` is connected now. */
127
+ isConnected(hostId: string): boolean;
128
+ /**
129
+ * When workers that ran on a lost host are certainly gone (epoch ms), or 0
130
+ * for a host that is connected or was never dropped. The host fences
131
+ * itself one lease after it last heard from the coordinator, checking
132
+ * every third of a lease; the coordinator sends nothing after the drop,
133
+ * and two leases leave room for the kill itself.
134
+ */
135
+ fencedAt(hostId: string): number;
118
136
  /** Opens the listener. Safe to call twice. */
119
137
  start(): void;
120
138
  /** Closes the listener and every host connection. */
@@ -0,0 +1,30 @@
1
+ import type { ChildProcess } from "node:child_process";
2
+ import { type ResourceLimits } from "node:worker_threads";
3
+ /** Options for {@link threadFork}. */
4
+ export interface ThreadForkOptions {
5
+ /** Heap limits for each cluster thread (`worker_threads` `resourceLimits`). */
6
+ resourceLimits?: ResourceLimits;
7
+ }
8
+ /**
9
+ * Runs each cluster as a worker thread of the manager's process instead of a
10
+ * forked process: pass it as `ClusterManager`'s `fork`. Threads start faster
11
+ * and use less memory; a crash that takes the process down (an out-of-memory
12
+ * abort, a native fault) takes every cluster with it. The worker script is the
13
+ * same: `ShardManager`, `ShardBus` and `ClusterWorker` find the parent through
14
+ * `parentPort`.
15
+ */
16
+ export declare function threadFork(options?: ThreadForkOptions): (script: string, env: Record<string, string | undefined>) => ChildProcess;
17
+ /** The parent link of a cluster thread: the part of `process` a worker uses. */
18
+ export interface ThreadEndpoint {
19
+ send(message: unknown): boolean;
20
+ on(event: string, listener: (...args: never[]) => void): ThreadEndpoint;
21
+ off(event: string, listener: (...args: never[]) => void): ThreadEndpoint;
22
+ }
23
+ /** The parent link when this code runs in a cluster thread started by {@link threadFork}, otherwise `undefined`. */
24
+ export declare function threadEndpoint(): ThreadEndpoint | undefined;
25
+ /** Wraps a message port as a worker endpoint. @internal */
26
+ export declare function portEndpoint(port: {
27
+ postMessage(message: unknown): void;
28
+ on(event: "message", listener: (frame: unknown) => void): unknown;
29
+ off(event: "message", listener: (frame: unknown) => void): unknown;
30
+ }): ThreadEndpoint;
@@ -164,7 +164,7 @@ class Channel extends BaseStructure {
164
164
  permissionOverwrites;
165
165
  partial;
166
166
  #context;
167
- constructor(data, context, options = {}) {
167
+ constructor(data, context, options) {
168
168
  super(data.id);
169
169
  if (!Number.isInteger(data.type) || data.type < 0)
170
170
  throw new RangeError("A Discord channel requires a valid channel type.");
@@ -177,7 +177,7 @@ class Channel extends BaseStructure {
177
177
  this.rateLimitPerUser = data.rate_limit_per_user;
178
178
  this.position = data.position;
179
179
  this.permissionOverwrites = (data.permission_overwrites ?? []).map((overwrite) => ({ ...overwrite }));
180
- this.partial = options.partial ?? false;
180
+ this.partial = options?.partial ?? false;
181
181
  this.#context = context;
182
182
  }
183
183
  send(options) {
@@ -2383,4 +2383,4 @@ export {
2383
2383
  stickerURL
2384
2384
  };
2385
2385
 
2386
- //# debugId=E9D552024AFDACBA64756E2164756E21
2386
+ //# debugId=AAE5FFB306F1F13364756E2164756E21