@arbitro/client 0.2.0 → 0.5.0

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/index.d.ts CHANGED
@@ -86,6 +86,8 @@ interface SubjectInflightLimit {
86
86
  }
87
87
  interface ConsumerConfig {
88
88
  name?: string;
89
+ /** Shared consumer group name for round-robin delivery. Defaults to `name`. */
90
+ group?: string;
89
91
  filter?: string;
90
92
  fanout?: boolean;
91
93
  /** Consumer-side ACK policy. None = fire-and-forget delivery, Explicit = consumer must ACK. */
@@ -220,6 +222,35 @@ declare class ClientMetrics {
220
222
  snapshot(): ClientMetricsSnapshot;
221
223
  }
222
224
 
225
+ interface CreateCronBody {
226
+ readonly name: string;
227
+ readonly every: string;
228
+ readonly tz?: string | undefined;
229
+ readonly timeout_ms: number;
230
+ readonly overlap: boolean;
231
+ }
232
+
233
+ type CronHandler = (ctx: CronContext) => Promise<void>;
234
+ /** Context passed to the cron handler on each fire. */
235
+ interface CronContext {
236
+ /** Cron job name. */
237
+ readonly name: string;
238
+ /** UTC timestamp (ms since epoch) when the broker intended this fire. */
239
+ readonly fireTime: bigint;
240
+ /** Monotonic fire counter (1-based). */
241
+ readonly fireCount: bigint;
242
+ }
243
+ declare class CronState {
244
+ private readonly handlers;
245
+ register(name: string, config: CreateCronBody, handler: CronHandler): void;
246
+ remove(name: string): void;
247
+ getHandler(name: string): CronHandler | undefined;
248
+ allConfigs(): ReadonlyArray<{
249
+ name: string;
250
+ config: CreateCronBody;
251
+ }>;
252
+ }
253
+
223
254
  type DeliveryHandler = (frame: Buffer) => void;
224
255
  declare class Connection {
225
256
  private readonly reconnectAddr?;
@@ -234,6 +265,7 @@ declare class Connection {
234
265
  private readonly log;
235
266
  private activeSubs;
236
267
  private metrics?;
268
+ private cronState?;
237
269
  private constructor();
238
270
  private attachSocket;
239
271
  static connect(addr: string, timeoutMs?: number, tlsCfg?: TlsConfig, reconnectCfg?: ReconnectConfig, logger?: Logger): Promise<Connection>;
@@ -244,13 +276,17 @@ declare class Connection {
244
276
  * entry and `reconnects` on successful reconnections. Unset = no-op.
245
277
  */
246
278
  setMetrics(m: ClientMetrics): void;
279
+ /** Attach cron state so the connection can dispatch CronFire frames. */
280
+ setCronState(s: CronState): void;
247
281
  private resolvePending;
248
282
  private rejectPending;
249
283
  private onFrame;
250
284
  private handleBatchDeliver;
285
+ private dispatchCronFire;
251
286
  sendSubscribeV2(consumerId: number, filter: Buffer, handler: DeliveryHandler, onRenew?: (newConsumerId: number) => void): Promise<number>;
252
287
  cancelSubscription(consumerId: number): void;
253
288
  private resubscribeAll;
289
+ private replayCrons;
254
290
  registerRoute(consumerId: number, handler: DeliveryHandler): void;
255
291
  unregisterRoute(consumerId: number): void;
256
292
  send(frame: Buffer): void;
@@ -431,6 +467,30 @@ declare class Consumer {
431
467
  subscribe<T extends Record<string, unknown>>(codec: Encoding<T>, cb: (msg: LazyMessage<T>) => void, opts?: SubscribeOptions): Promise<Subscription>;
432
468
  }
433
469
 
470
+ declare class CronBuilder {
471
+ private readonly conn;
472
+ private readonly cronState;
473
+ private readonly cronName;
474
+ private expr;
475
+ private timezone;
476
+ private timeoutMs;
477
+ private allowOverlap;
478
+ constructor(conn: Connection, cronState: CronState, cronName: string);
479
+ every(expression: string): this;
480
+ tz(timezone: string): this;
481
+ timeout(ms: number): this;
482
+ overlap(allow: boolean): this;
483
+ run(handler: CronHandler): Promise<CronHandle>;
484
+ }
485
+ declare class CronHandle {
486
+ private readonly conn;
487
+ private readonly cronState;
488
+ private readonly cronName;
489
+ constructor(conn: Connection, cronState: CronState, cronName: string);
490
+ get name(): string;
491
+ stop(): Promise<void>;
492
+ }
493
+
434
494
  type MsgCallback = (msg: Message) => void;
435
495
  declare class ArbitroClient {
436
496
  private conn;
@@ -439,6 +499,7 @@ declare class ArbitroClient {
439
499
  private readonly logger;
440
500
  private readonly sidCache;
441
501
  private readonly _metrics;
502
+ private readonly _cronState;
442
503
  constructor(config: ClientConfig);
443
504
  connect(): Promise<this>;
444
505
  /**
@@ -494,6 +555,13 @@ declare class ArbitroClient {
494
555
  publishBatch(streamName: string, messages: BatchPublishEntry[]): Promise<bigint>;
495
556
  /** Request-reply. */
496
557
  request(streamName: string, subject: string, data: Buffer, timeoutMs?: number): Promise<Buffer>;
558
+ /**
559
+ * Publish a message with a delivery delay. The broker parks the message
560
+ * in its delayed journal and delivers it to consumers after `delayMs`
561
+ * milliseconds. Returns a Promise that resolves once the broker confirms
562
+ * receipt.
563
+ */
564
+ publishDelayed(streamName: string, subject: string, data: Buffer, delayMs: number): Promise<void>;
497
565
  /** Subscribe with explicit consumer config. */
498
566
  subscribe(streamName: string, config: ConsumerConfig, callback?: MsgCallback, opts?: SubscribeOptions): Promise<Subscription>;
499
567
  /** Subscribe by consumer name only (consumer must already exist). */
@@ -533,6 +601,8 @@ declare class ArbitroClient {
533
601
  /** Pre-resolve stream_id from server (GetStream). Required before sync publish(). */
534
602
  resolveStream(name: string): Promise<void>;
535
603
  stream(name: string, config?: StreamConfig): Stream;
604
+ /** Start building a cron job. Call `.every()` then `.run()` to register. */
605
+ cron(name: string): CronBuilder;
536
606
  close(): Promise<void>;
537
607
  }
538
608
 
@@ -586,6 +656,64 @@ declare class Topic<T extends Record<string, unknown>> {
586
656
 
587
657
  declare function streamId(name: Buffer | string): number;
588
658
 
659
+ declare class WorkflowHandle {
660
+ private readonly workflowName;
661
+ private readonly taskStreamName;
662
+ private readonly dlqStreamName;
663
+ private readonly sub;
664
+ private readonly triggerSub;
665
+ constructor(workflowName: string, taskStreamName: string, dlqStreamName: string, sub: unknown, triggerSub: unknown | undefined);
666
+ get name(): string;
667
+ get taskStream(): string;
668
+ get dlqStream(): string;
669
+ trigger(client: ArbitroClient, context: Buffer): Promise<number>;
670
+ }
671
+
672
+ interface StepContext {
673
+ readonly name: string;
674
+ readonly instanceId: number;
675
+ readonly stepIndex: number;
676
+ readonly attempt: number;
677
+ readonly context: Buffer;
678
+ }
679
+ interface StepResult {
680
+ readonly context: Buffer;
681
+ }
682
+ type StepHandler = (ctx: StepContext) => Promise<StepResult>;
683
+ declare class WorkflowBuilder {
684
+ private readonly client;
685
+ private readonly workflowName;
686
+ private triggerSubject;
687
+ private triggerStreamName;
688
+ private readonly steps;
689
+ private ackWaitMs;
690
+ private maxInflightVal;
691
+ private maxRetriesVal;
692
+ private maxContextSizeVal;
693
+ constructor(client: ArbitroClient, workflowName: string);
694
+ trigger(subject: string): this;
695
+ triggerStream(streamName: string): this;
696
+ step(name: string, handler: StepHandler): this;
697
+ /** Compensation handler for the most recently added step. */
698
+ compensate(_stepName: string, handler: StepHandler): this;
699
+ ackWait(ms: number): this;
700
+ inflight(n: number): this;
701
+ maxRetries(n: number): this;
702
+ maxContextSize(bytes: number): this;
703
+ start(): Promise<WorkflowHandle>;
704
+ private subscribeWorker;
705
+ private subscribeTrigger;
706
+ }
707
+
708
+ /** Bit flag set on stepIndex to mark compensation tasks. */
709
+ declare const COMPENSATION_BIT = 32768;
710
+ interface DecodedTask {
711
+ readonly instanceId: number;
712
+ readonly stepIndex: number;
713
+ readonly attempt: number;
714
+ readonly context: Buffer;
715
+ }
716
+
589
717
  /** Wraps a ZodObject schema as an Encoding<T>.
590
718
  *
591
719
  * - encode: msgpack (no Zod overhead — bytes out)
@@ -599,4 +727,4 @@ declare function zodCodec<S extends ZodRawShape>(zodSchema: ZodObject<S>): Encod
599
727
  readonly fields: string[];
600
728
  };
601
729
 
602
- export { AckPolicy, ArbitroClient, ArbitroError, type BatchPublishEntry, type ClientConfig, type ClientMetricsSnapshot, Codec, Consumer, type ConsumerConfig, type ConsumerInfo, type DeleteStreamOpts, DeliverPolicy, type Encoding, ErrorCode, type ErrorCodeValue, type FieldType, type FieldTypeMap, type FlushConfig, type InferSchema, type JournalConfig, JournalType, JsonCodec, type LazyMessage, type LogFn, type Logger, Message, type PublishOpts, type ReconnectConfig, type Schema, Stream, type StreamConfig, type StreamInfo, StringCodec, type SubjectInflightLimit, type SubscribeOptions, Subscription, type TlsConfig, Topic, decodeJson, decodeString, encodeJson, encodeString, makeLazyMessage, schema, streamId, zodCodec };
730
+ export { AckPolicy, ArbitroClient, ArbitroError, type BatchPublishEntry, COMPENSATION_BIT, type ClientConfig, type ClientMetricsSnapshot, Codec, Consumer, type ConsumerConfig, type ConsumerInfo, CronBuilder, type CronContext, CronHandle, type CronHandler, type DecodedTask, type DeleteStreamOpts, DeliverPolicy, type Encoding, ErrorCode, type ErrorCodeValue, type FieldType, type FieldTypeMap, type FlushConfig, type InferSchema, type JournalConfig, JournalType, JsonCodec, type LazyMessage, type LogFn, type Logger, Message, type PublishOpts, type ReconnectConfig, type Schema, type StepContext, type StepHandler, type StepResult, Stream, type StreamConfig, type StreamInfo, StringCodec, type SubjectInflightLimit, type SubscribeOptions, Subscription, type TlsConfig, Topic, WorkflowBuilder, WorkflowHandle, decodeJson, decodeString, encodeJson, encodeString, makeLazyMessage, schema, streamId, zodCodec };