@relaybus/core 0.3.0 → 0.3.1
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.
- package/dist/{chunk-3OHMEMZA.cjs → chunk-J76M7XTS.cjs} +127 -9
- package/dist/chunk-J76M7XTS.cjs.map +1 -0
- package/dist/{chunk-WS274DL3.js → chunk-NOR5JHVN.js} +121 -9
- package/dist/chunk-NOR5JHVN.js.map +1 -0
- package/dist/index.cjs +2232 -1898
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +82 -475
- package/dist/index.d.ts +82 -475
- package/dist/index.js +2259 -1931
- package/dist/index.js.map +1 -1
- package/dist/internal/index.cjs +335 -117
- package/dist/internal/index.cjs.map +1 -1
- package/dist/internal/index.d.cts +269 -2
- package/dist/internal/index.d.ts +269 -2
- package/dist/internal/index.js +293 -101
- package/dist/internal/index.js.map +1 -1
- package/dist/transport-BlfzIBZD.d.cts +535 -0
- package/dist/transport-BlfzIBZD.d.ts +535 -0
- package/package.json +1 -1
- package/dist/chunk-3OHMEMZA.cjs.map +0 -1
- package/dist/chunk-WS274DL3.js.map +0 -1
- package/dist/event-DCRTuYKI.d.cts +0 -142
- package/dist/event-DCRTuYKI.d.ts +0 -142
package/dist/internal/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { b as EventHeaders, E as EventEnvelope, h as Clock, L as LeaseReference, d as ErrorInfo, j as ClaimRequest, C as ClaimedDelivery, T as Transport, U as TransportMessageHandler, V as TransportSubscriptionHooks, p as CloseOptions, D as Duration } from '../transport-BlfzIBZD.js';
|
|
2
2
|
|
|
3
3
|
/** Returns `value` when it is an integer of at least 1, else throws a {@link ConfigurationError} naming the option. */
|
|
4
4
|
declare function assertPositiveInteger(value: number, name: string): number;
|
|
@@ -168,4 +168,271 @@ declare function createJsonEnvelopeFormat(mapping: JsonEnvelopeMapping<string>,
|
|
|
168
168
|
readonly failures: JsonEnvelopeFailures;
|
|
169
169
|
}): JsonEnvelopeFormat;
|
|
170
170
|
|
|
171
|
-
|
|
171
|
+
/** What a ledger remembers of a claim: at least who it was handed to and which delivery. */
|
|
172
|
+
interface HandedOutEntry {
|
|
173
|
+
readonly owner: string;
|
|
174
|
+
readonly deliveryId: string;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* The claims a store instance handed out and has not seen settled, keyed by
|
|
178
|
+
* {@link DeliveryLeaseIdentity} (delivery id and exact lease token). After a failed claim the
|
|
179
|
+
* store keeps exactly these listed as running and gives the rest back.
|
|
180
|
+
*/
|
|
181
|
+
declare class HandedOutLedger<TEntry extends HandedOutEntry> {
|
|
182
|
+
#private;
|
|
183
|
+
register(lease: LeaseReference, entry: TEntry): void;
|
|
184
|
+
/** Whether the claim with this identity ({@link DeliveryLeaseIdentity.of}) is handed out. */
|
|
185
|
+
has(identity: string): boolean;
|
|
186
|
+
forget(lease: LeaseReference): void;
|
|
187
|
+
/** Forgets every entry `settled` says is settled. */
|
|
188
|
+
forgetWhere(settled: (entry: TEntry, identity: string) => boolean): void;
|
|
189
|
+
/** The entries handed out to `owner`. */
|
|
190
|
+
entriesOf(owner: string): TEntry[];
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/** How a claim ends without completing: retried later, given back, or dead-lettered. */
|
|
194
|
+
type SettlementChange = {
|
|
195
|
+
readonly kind: 'reschedule';
|
|
196
|
+
readonly availableAt: Date;
|
|
197
|
+
readonly error: ErrorInfo;
|
|
198
|
+
readonly now: Date;
|
|
199
|
+
} | {
|
|
200
|
+
readonly kind: 'release';
|
|
201
|
+
readonly now: Date;
|
|
202
|
+
} | {
|
|
203
|
+
readonly kind: 'bury';
|
|
204
|
+
readonly error: ErrorInfo;
|
|
205
|
+
readonly now: Date;
|
|
206
|
+
};
|
|
207
|
+
/** A change of the claim a lease names. */
|
|
208
|
+
type LeaseChange = {
|
|
209
|
+
readonly lease: LeaseReference;
|
|
210
|
+
readonly change: SettlementChange;
|
|
211
|
+
};
|
|
212
|
+
/** A lease renewal; `now` for a store that records when it happened. */
|
|
213
|
+
type LeaseExtension = {
|
|
214
|
+
readonly lease: LeaseReference;
|
|
215
|
+
readonly leaseExpiresAt: Date;
|
|
216
|
+
readonly now?: Date;
|
|
217
|
+
};
|
|
218
|
+
/**
|
|
219
|
+
* What a store answers about a lease: at once when it answers from memory, later when it asks a
|
|
220
|
+
* database. Answering at once keeps the in-memory store as fast (in microtasks) as it always was.
|
|
221
|
+
*/
|
|
222
|
+
type StoreAnswer = boolean | Promise<boolean>;
|
|
223
|
+
/**
|
|
224
|
+
* The fenced settlement skeleton every event store shares: find the claim a lease names (a lease
|
|
225
|
+
* this store cannot have issued, or whose claim ended, is not held and changes nothing), apply the
|
|
226
|
+
* change fenced by the lease, then forget the lease as handed out once the store answered.
|
|
227
|
+
* A store supplies only how it finds a held claim, how it writes a change and a renewal, and its
|
|
228
|
+
* bookkeeping of handed-out leases.
|
|
229
|
+
*/
|
|
230
|
+
declare abstract class LeaseSettlement<THeld> {
|
|
231
|
+
#private;
|
|
232
|
+
/** Renews the lease when it is still held; false otherwise. */
|
|
233
|
+
extendLease(extension: LeaseExtension): StoreAnswer;
|
|
234
|
+
/**
|
|
235
|
+
* Applies `change` when the lease is still held. Once the store answered (either way) the lease
|
|
236
|
+
* is forgotten as handed out; when the write throws it stays registered, since the caller may
|
|
237
|
+
* retry with the same lease.
|
|
238
|
+
*/
|
|
239
|
+
changeClaim(request: LeaseChange): StoreAnswer;
|
|
240
|
+
/** The claim `lease` names, when this store issued the lease; undefined otherwise. */
|
|
241
|
+
protected abstract findHeld(lease: LeaseReference): THeld | undefined;
|
|
242
|
+
protected abstract writeChange(held: THeld, request: LeaseChange): StoreAnswer;
|
|
243
|
+
protected abstract writeExtension(held: THeld, extension: LeaseExtension): StoreAnswer;
|
|
244
|
+
/** Drops `lease` from the store's handed-out bookkeeping; nothing for a store that keeps none. */
|
|
245
|
+
protected abstract forgetHandedOut(lease: LeaseReference): void;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* The claim skeleton of the database stores: a request for no handlers or no deliveries claims
|
|
250
|
+
* nothing, and the claims of one owner run one after the other. Claims of one owner read the same
|
|
251
|
+
* held lanes and the same bookkeeping of what was handed out, so they must not overlap (the
|
|
252
|
+
* dispatcher claims one batch at a time anyway; `runOnce` next to a running dispatcher is what
|
|
253
|
+
* this guards against). A store supplies only {@link OwnerSerializedClaims.claimInTurn}.
|
|
254
|
+
*/
|
|
255
|
+
declare abstract class OwnerSerializedClaims {
|
|
256
|
+
#private;
|
|
257
|
+
claim(request: ClaimRequest): Promise<ClaimedDelivery[]>;
|
|
258
|
+
/** Whether the request cannot claim anything: no handlers, or a limit that is not above 0. */
|
|
259
|
+
protected claimsNothing(request: ClaimRequest): boolean;
|
|
260
|
+
/** Claims for `request` once the earlier claims of its owner settled. */
|
|
261
|
+
protected abstract claimInTurn(request: ClaimRequest): Promise<ClaimedDelivery[]>;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/** The event a transport's decoder extracted from a message; see the transport's `DecodedEvent`. */
|
|
265
|
+
interface DecodedEventFields {
|
|
266
|
+
readonly id: string;
|
|
267
|
+
readonly type: string;
|
|
268
|
+
readonly payload: unknown;
|
|
269
|
+
readonly source?: string;
|
|
270
|
+
readonly key?: string | null;
|
|
271
|
+
readonly headers?: EventHeaders;
|
|
272
|
+
readonly correlationId?: string | null;
|
|
273
|
+
readonly causationId?: string | null;
|
|
274
|
+
readonly occurredAt?: Date;
|
|
275
|
+
}
|
|
276
|
+
/** A fixed value, or an extractor that reads it from a plain message. */
|
|
277
|
+
type TextOption<TPlain, TValue extends string | null> = TValue | ((message: TPlain) => TValue | undefined) | undefined;
|
|
278
|
+
/**
|
|
279
|
+
* Observes the rejection of a promise an async decoder or extractor returned by
|
|
280
|
+
* mistake: the value is refused as malformed, and an unobserved rejection would
|
|
281
|
+
* otherwise crash the process.
|
|
282
|
+
*/
|
|
283
|
+
declare function observeRejection(value: unknown): void;
|
|
284
|
+
/**
|
|
285
|
+
* The inbound plumbing a transport shares with every other: completing what a user decoder
|
|
286
|
+
* returned and reading the extractor options of a plain JSON decoder. A transport supplies only its
|
|
287
|
+
* malformed-message error and the defaults its messages carry (source, key, time).
|
|
288
|
+
*/
|
|
289
|
+
declare abstract class DecodedEventReader<TMessage, TPlain> {
|
|
290
|
+
/**
|
|
291
|
+
* Fills the fields a decoder left out and guards against a decoder that returned no object,
|
|
292
|
+
* which would otherwise surface as a retried `TypeError` instead of a malformed message.
|
|
293
|
+
*/
|
|
294
|
+
complete(decoded: unknown, message: TMessage): EventEnvelope;
|
|
295
|
+
/** The text an option gives for `plain`; undefined when it gives none or `''`. */
|
|
296
|
+
text<TValue extends string | null>(option: TextOption<TPlain, TValue>, { plain, name }: {
|
|
297
|
+
readonly plain: TPlain;
|
|
298
|
+
readonly name: string;
|
|
299
|
+
}): string | undefined;
|
|
300
|
+
/** The error of a malformed message, which the transport dead-letters instead of retrying. */
|
|
301
|
+
abstract invalid(reason: string): Error;
|
|
302
|
+
protected abstract defaultSource(message: TMessage): string;
|
|
303
|
+
protected abstract defaultKey(message: TMessage): string | null;
|
|
304
|
+
protected abstract defaultTime(message: TMessage): Date;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/** One subscription of a transport: what it consumes and where the messages go. */
|
|
308
|
+
interface TransportSubscription {
|
|
309
|
+
readonly destinations: readonly string[];
|
|
310
|
+
readonly onMessage: TransportMessageHandler;
|
|
311
|
+
readonly hooks: TransportSubscriptionHooks | undefined;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* The skeleton of a broker transport that publishes and subscribes: the {@link Transport} port
|
|
315
|
+
* with its subscribe signature in one place. A transport supplies how it publishes, opens its one
|
|
316
|
+
* subscription, reports readiness and closes.
|
|
317
|
+
*/
|
|
318
|
+
declare abstract class SubscribingTransport implements Transport {
|
|
319
|
+
abstract readonly name: string;
|
|
320
|
+
abstract readonly system: string;
|
|
321
|
+
/**
|
|
322
|
+
* Subscribes to `destinations`. Not async itself: the subscription's own promise is returned
|
|
323
|
+
* as it is, so its checks reject rather than throw.
|
|
324
|
+
*/
|
|
325
|
+
subscribe(destinations: readonly string[], onMessage: TransportMessageHandler, hooks?: TransportSubscriptionHooks): Promise<void>;
|
|
326
|
+
abstract publish(envelope: EventEnvelope, destination: string): Promise<void>;
|
|
327
|
+
abstract isReady(): boolean;
|
|
328
|
+
abstract close(options?: CloseOptions): Promise<void>;
|
|
329
|
+
/** Opens the transport's one subscription; rejects when it cannot. */
|
|
330
|
+
protected abstract openSubscription(subscription: TransportSubscription): Promise<void>;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Two identifiers joined into one map or set key, such as an event id and a handler id, or a
|
|
335
|
+
* handler id and an ordering key. The NUL separator keeps `('a:b', 'c')` and `('a', 'b:c')` apart.
|
|
336
|
+
* Keys are plain strings, so they cost nothing more than the template literal they replace.
|
|
337
|
+
*/
|
|
338
|
+
declare abstract class CompositeKey {
|
|
339
|
+
static of(first: string, second: string): string;
|
|
340
|
+
/** The start every key of `first` shares, to find them all by prefix. */
|
|
341
|
+
static startOf(first: string): string;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/** The range a {@link BoundedInteger} option allows. */
|
|
345
|
+
interface IntegerBounds {
|
|
346
|
+
readonly name: string;
|
|
347
|
+
readonly minimum: number;
|
|
348
|
+
readonly maximum: number;
|
|
349
|
+
}
|
|
350
|
+
/** An integer option with fixed lower and upper bounds. */
|
|
351
|
+
declare abstract class BoundedInteger {
|
|
352
|
+
/** Returns `value` when it is an integer within the bounds, else throws a {@link ConfigurationError}. */
|
|
353
|
+
static of(value: number, { name, minimum, maximum }: IntegerBounds): number;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Identifies one claim of a delivery: the delivery id with the exact lease token it was handed out
|
|
358
|
+
* with. Two claims of the same delivery (an expired one and the current one) have different
|
|
359
|
+
* identities, so bookkeeping of the older can never replace or remove the newer one's.
|
|
360
|
+
*/
|
|
361
|
+
declare abstract class DeliveryLeaseIdentity {
|
|
362
|
+
static of(deliveryId: string, leaseToken: string): string;
|
|
363
|
+
/** The start of the identity of every claim of `deliveryId`. */
|
|
364
|
+
static prefixOf(deliveryId: string): string;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Delays that double with every attempt, from `initialMs` up to `maxMs`: the first retry waits
|
|
369
|
+
* `initialMs`, the second twice that, and so on. Without jitter, for in-process retries.
|
|
370
|
+
*/
|
|
371
|
+
declare class ExponentialBackoff {
|
|
372
|
+
readonly initialMs: number;
|
|
373
|
+
readonly maxMs: number;
|
|
374
|
+
constructor({ initialMs, maxMs }: {
|
|
375
|
+
readonly initialMs: number;
|
|
376
|
+
readonly maxMs: number;
|
|
377
|
+
});
|
|
378
|
+
/** The delay after failed attempt `attempt` (1-based). */
|
|
379
|
+
delayFor(attempt: number): number;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/** The claim a lane lease token names, as written in the token. */
|
|
383
|
+
interface LaneLeaseTokenParts {
|
|
384
|
+
readonly lane: number;
|
|
385
|
+
/** The lane's epoch, as decimal text: PostgreSQL epochs exceed the safe integers. */
|
|
386
|
+
readonly epoch: string;
|
|
387
|
+
/** The claim generation of the delivery. */
|
|
388
|
+
readonly claims: number;
|
|
389
|
+
}
|
|
390
|
+
/** How many digits each part of a token may have, and how many lanes there are. */
|
|
391
|
+
interface LaneLeaseTokenLimits {
|
|
392
|
+
readonly laneCount: number;
|
|
393
|
+
readonly epochDigits: number;
|
|
394
|
+
readonly claimsDigits: number;
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* The fencing token of a claim in a lane-leased store: `<lane>:<epoch>:<claims>`. Every state
|
|
398
|
+
* change checks the lane epoch and the delivery's claim generation it names. A store creates one
|
|
399
|
+
* format with its own digit limits and parses only the tokens it can have issued.
|
|
400
|
+
*/
|
|
401
|
+
declare class LaneLeaseTokenFormat {
|
|
402
|
+
#private;
|
|
403
|
+
constructor(limits: LaneLeaseTokenLimits);
|
|
404
|
+
format(lane: number, { epoch, claims }: {
|
|
405
|
+
readonly epoch: string | number;
|
|
406
|
+
readonly claims: number;
|
|
407
|
+
}): string;
|
|
408
|
+
/** The parts of `token`; undefined when the store cannot have issued it. */
|
|
409
|
+
parse(token: string): LaneLeaseTokenParts | undefined;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
/**
|
|
413
|
+
* A configured length of time, converted once from a {@link Duration} option. Each factory names
|
|
414
|
+
* the option, so its refusal says which one was wrong.
|
|
415
|
+
*/
|
|
416
|
+
declare abstract class Milliseconds {
|
|
417
|
+
/** Zero or more milliseconds. */
|
|
418
|
+
static of(value: Duration, name: string): number;
|
|
419
|
+
/** More than zero milliseconds: a wait, a timeout or an age that must pass at all. */
|
|
420
|
+
static positive(value: Duration, name: string): number;
|
|
421
|
+
/** A duration that drives a timer: more than zero, and no longer than timers can represent. */
|
|
422
|
+
static forTimer(value: Duration, name: string): number;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/** A text option that must not be empty: a name, an exchange, a queue. */
|
|
426
|
+
declare abstract class NonEmptyText {
|
|
427
|
+
static of(value: string, name: string): string;
|
|
428
|
+
/** Like {@link NonEmptyText.of}, for an option that may be left out. */
|
|
429
|
+
static optional(value: string | undefined, name: string): string | undefined;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/** A count option that must be a whole number of at least 1: a batch size, attempts, a limit. */
|
|
433
|
+
declare abstract class PositiveInteger {
|
|
434
|
+
/** Returns `value` when it is an integer of at least 1, else throws a {@link ConfigurationError} naming the option. */
|
|
435
|
+
static of(value: number, name: string): number;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
export { type BodyEnvelopeMapping, type BodyField, BoundedInteger, type CancelTimer, type CloudEventReaders, CompositeKey, type DecodedEventFields, DecodedEventReader, DeliveryLeaseIdentity, ExponentialBackoff, type FixedType, type HandedOutEntry, HandedOutLedger, type HeaderField, type IntegerBounds, type JsonEnvelopeFailures, type JsonEnvelopeFields, type JsonEnvelopeFormat, type JsonEnvelopeMapping, type JsonWireMessage, LaneLeaseTokenFormat, type LaneLeaseTokenLimits, type LaneLeaseTokenParts, type LeaseChange, type LeaseExtension, LeaseSettlement, Milliseconds, NonEmptyText, OwnerSerializedClaims, type PayloadOnlyMapping, PositiveInteger, type ScheduledTask, type SettlementChange, SubscribingTransport, type TextOption, type TransportSubscription, type WireField, assertPositiveInteger, createCloudEventReaders, createJsonEnvelopeFormat, fromHeader, fromPayloadField, isJsonObject, mediaTypeOf, observeRejection, schedule, sleep, writeStructuredCloudEvent };
|