Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@ythub/jetstream-queue

Package Overview
Dependencies
Maintainers
1
Versions
16
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ythub/jetstream-queue - npm Package Compare versions

Comparing version
2.0.2
to
2.0.3
+212
BACKOFF-GUIDE.md
# Exponential Backoff Guide
This library supports NATS JetStream's exponential backoff features for reliable message redelivery.
## Understanding NATS Backoff Mechanisms
### 1. **Automatic Backoff (on timeout)**
Configured in `ConsumerOptions.backoffMs`, this applies when a message is **not acknowledged within the ackWait time**.
```typescript
const consumer = new PubSubConsumer({
durable: 'my-processor',
subject: 'events.>',
backoffMs: [1000, 5000, 30000], // 1s, 5s, 30s
maxDeliver: 3,
})
```
**How it works:**
- Message delivered → No ack received within timeout → Redelivery after 1s
- Still no ack → Redelivery after 5s
- Still no ack → Redelivery after 30s
- After `maxDeliver` attempts, message goes to dead letter or is discarded
**When to use:**
- Unexpected crashes or timeouts
- Long-running processes that might fail silently
- As a safety net for unhandled errors
### 2. **Manual Backoff with `nakWithDelay()`**
For explicit control over retry timing:
```typescript
for await (const message of subscription) {
try {
await processMessage(message.data)
message.ack()
} catch (error) {
if (error.code === 'RATE_LIMIT') {
// Retry after 10 seconds
message.nakWithDelay(10_000)
} else {
// Retry immediately
message.nak()
}
}
}
```
**When to use:**
- Known transient failures (rate limits, circuit breakers)
- Different retry strategies for different error types
- Immediate retry vs delayed retry logic
### 3. **Long Processing with `working()`**
Prevent timeout during legitimate long-running processing:
```typescript
for await (const message of subscription) {
// Start processing
const intervalId = setInterval(() => {
message.working() // Reset ack timer
}, 5000)
try {
await longRunningProcess(message.data)
message.ack()
} finally {
clearInterval(intervalId)
}
}
```
**When to use:**
- Processing legitimately takes longer than ackWait
- Batch operations
- External API calls with unpredictable response times
## Key Differences
| Feature | `backoff` | `nakWithDelay()` | `working()` |
|---------|-----------|------------------|-------------|
| Trigger | Automatic on timeout | Manual on error | Manual during processing |
| Control | Configuration-based | Programmatic | Programmatic |
| Use Case | Safety net | Known failures | Long operations |
| Applies to | Timeout only | Nak only | Current message |
## Important Notes
⚠️ **`backoff` does NOT apply to `nak()`**
According to [NATS documentation](https://github.com/nats-io/nats-server/issues/2042):
> "backoff is NOT applied to naked messages. A nak will result in immediate re-delivery unless nakWithDelay is used"
So:
- `message.nak()` → Immediate redelivery (ignores backoff)
- `message.nakWithDelay(5000)` → Redelivery after 5 seconds
- Timeout without ack → Uses backoff array
## Best Practices
### 1. **Combine Strategies**
```typescript
const consumer = new PubSubConsumer({
durable: 'resilient-processor',
backoffMs: [5000, 15000, 60000], // Fallback for timeouts
maxDeliver: 5,
ackWaitMs: 30000, // 30 second timeout
})
for await (const message of subscription) {
try {
await process(message.data)
message.ack()
} catch (error) {
// Programmatic retry control
if (error.retryable) {
const delay = calculateDelay(error)
message.nakWithDelay(delay)
} else {
// Non-retryable - don't requeue
message.term()
}
}
}
```
### 2. **Set Appropriate Timeouts**
```typescript
// Short-lived operations
const fastConsumer = new PubSubConsumer({
ackWaitMs: 5000, // 5 seconds
backoffMs: [1000, 3000], // Quick retries
maxDeliver: 3,
})
// Long-running operations
const slowConsumer = new PubSubConsumer({
ackWaitMs: 60000, // 1 minute
backoffMs: [10000, 30000, 120000], // Longer delays
maxDeliver: 5,
})
```
### 3. **Monitor Redelivery**
```typescript
for await (const message of subscription) {
const { redelivered, info } = message
if (redelivered) {
console.warn(`Message redelivered ${info.deliveryCount} times`)
// Consider different strategy on multiple retries
if (info.deliveryCount > 3) {
// Log for investigation, maybe send to DLQ
await sendToDeadLetterQueue(message.data)
message.ack() // Don't retry anymore
continue
}
}
await processMessage(message.data)
message.ack()
}
```
## Configuration Examples
### High-Frequency Events (clicks, metrics)
```typescript
new PubSubConsumer({
subject: 'analytics.clicks',
backoffMs: [100, 500, 2000], // Fast retries
maxDeliver: 3,
ackWaitMs: 2000,
})
```
### Critical Business Events (orders, payments)
```typescript
new PubSubConsumer({
durable: 'payment-processor',
subject: 'payments.>',
backoffMs: [5000, 30000, 300000], // 5s, 30s, 5min
maxDeliver: 10,
ackWaitMs: 60000, // 1 minute
})
```
### External API Integration
```typescript
new PubSubConsumer({
subject: 'webhooks.send',
backoffMs: [10000, 60000, 600000], // 10s, 1min, 10min
maxDeliver: 5,
ackWaitMs: 30000,
})
```
## References
- [NATS JetStream Backoff Feature Request](https://github.com/nats-io/nats-server/issues/2042)
- [NATS Consumer Configuration](https://docs.nats.io/nats-concepts/jetstream/consumers)
+15
-4

@@ -51,2 +51,3 @@ // @bun

import { jetstream } from "@nats-io/jetstream";
import ms from "ms";

@@ -172,3 +173,10 @@ // src/utils/createConditionalLogger.ts

nak: () => message.nak(),
data: decoded
nakWithDelay: (delayMs) => {
const delay = typeof delayMs === "number" ? delayMs : ms(delayMs);
message.nak(delay);
},
working: () => message.working(),
data: decoded,
deliveryCount: message.info.deliveryCount,
redelivered: message.redelivered
};

@@ -249,3 +257,3 @@ }

toConsumerConfig() {
const { durable, policy, maxAckPending, subject, inactiveThresholdMs } = this.params;
const { durable, policy, maxAckPending, subject, inactiveThresholdMs, ackWaitMs, backoffMs, maxDeliver } = this.params;
const base = {

@@ -255,3 +263,6 @@ deliver_policy: policy,

filter_subject: subject,
ack_policy: "explicit"
ack_policy: "explicit",
ack_wait: ackWaitMs ? Math.trunc(ackWaitMs * 1e6) : undefined,
backoff: backoffMs?.map((ms2) => Math.trunc(ms2 * 1e6)),
max_deliver: maxDeliver
};

@@ -292,3 +303,3 @@ if (durable) {

//# debugId=FB9C944FDEFB757464756E2164756E21
//# debugId=4729336DBA38C91864756E2164756E21
//# sourceMappingURL=index.js.map

@@ -9,9 +9,9 @@ {

"import type { StreamConfig } from '@nats-io/jetstream'\n\nexport class PubSubStream {\n constructor(private readonly options: Partial<StreamConfig>) {}\n\n getOptions(): Partial<StreamConfig> {\n return this.options\n }\n}\n",
"import { jetstream, type JetStreamClient, type JetStreamManager, type PubAck, type PurgeResponse, type StreamInfo } from '@nats-io/jetstream'\n\nimport { Logger } from '@ythub/logger'\n\nimport { PubSubConsumer } from './PubSubConsumer'\nimport { PubSubEvent } from './PubSubEvent'\nimport { PubSubMessage } from './PubSubMessage'\nimport { PubSubPrivateClient } from './PubSubPrivateClient'\nimport { PubSubStream } from './PubSubStream'\nimport { createConditionalLogger } from './utils'\n\nexport type PubSubSubscription<Data> = AsyncIterable<PubSubMessage<Data>> & {\n unsubscribe: () => Promise<void>\n}\n\nfunction escapeSubjectForRegex(subject: string): RegExp {\n return new RegExp(`^${subject.replaceAll('.', '\\\\.').replaceAll('>', '.*')}`)\n}\n\nfunction isNotFound(obj: any): boolean {\n return obj.code === 10014\n}\n\nexport class PubSubStreamContext {\n private logger: Logger = createConditionalLogger('app:PubSubStreamContext')\n\n constructor(\n private readonly stream: PubSubStream,\n private readonly client: PubSubPrivateClient,\n ) {}\n\n protected get jsManager(): JetStreamManager {\n return this.client.jsManager\n }\n\n protected get jetStream(): JetStreamClient {\n return jetstream(this.client.nats)\n }\n\n async deleteAllMessages(): Promise<PurgeResponse> {\n return this.client.jsManager.streams.purge(this.stream.getOptions().name)\n }\n\n /**\n * Initializes the stream, which must be called before calling any `.subscribe()`\n */\n async create(): Promise<StreamInfo> {\n const cfg = this.stream.getOptions()\n if (!cfg.name)\n throw new Error('stream name is required')\n return this.jsManager.streams.add(cfg as Required<Pick<typeof cfg, 'name'>> & typeof cfg)\n }\n\n isNameMatchingStreamSubjects(name: string): boolean {\n const allowedSubjects = this.stream.getOptions().subjects.map(subject => escapeSubjectForRegex(subject))\n\n return allowedSubjects.some(regexp => regexp.test(name))\n }\n\n async publish(subject: string, data: any, id?: string): Promise<PubAck> {\n if (!this.isNameMatchingStreamSubjects(subject)) {\n throw new Error('Subject of the message is not matching names allowed by the stream')\n }\n\n const payload = typeof data === 'string' || data instanceof Uint8Array ? data : JSON.stringify(data)\n return this.jetStream.publish(subject, payload, id ? { msgID: id } : {})\n }\n\n async publishEvent(event: PubSubEvent): Promise<PubAck> {\n this.logger.info('publishing event: ', event.$natsEventName)\n return this.publish(event.$natsEventName, { ...event })\n }\n\n deleteConsumer(consumer: PubSubConsumer) {\n return this.jsManager.consumers.delete(this.stream.getOptions().name, consumer.getConsumerName())\n }\n\n async retrieveOrCreateConsumer(consumer: PubSubConsumer) {\n const streamName = this.stream.getOptions().name\n const consumerName = consumer.getConsumerName()\n\n let info: unknown\n try {\n this.logger.info('querying info')\n info = await this.client.jsManager.consumers.info(streamName, consumerName)\n }\n catch (e: any) {\n this.logger.warn('Failed to acquire consumer info: ', { message: e.message, isNotFound: isNotFound(e) })\n if (isNotFound(e)) {\n info = null\n }\n else {\n throw e\n }\n }\n\n const notFound = info == null || isNotFound(info)\n\n if (notFound) {\n this.logger.info('creating consumer: ', consumerName)\n const created = await this.client.jsManager.consumers.add(streamName, consumer.toConsumerConfig())\n this.logger.info('Created consumer: ', created.name)\n }\n else {\n this.logger.info('updating consumer: ', consumerName)\n await this.client.jsManager.consumers.update(streamName, consumerName, consumer.toConsumerConfig())\n }\n\n return this.client.jsManager.jetstream().consumers.get(streamName, consumerName)\n }\n\n async subscribe<Data = Record<string, never>>(\n consumer: PubSubConsumer,\n subject?: string,\n ): Promise<PubSubSubscription<Data>> {\n const { logger } = this\n const decode = (bytes: Uint8Array) => {\n try {\n const s = new TextDecoder().decode(bytes)\n return JSON.parse(s) as Data\n }\n catch {\n return undefined as unknown as Data\n }\n }\n\n // Ensure the consumer exists and is filtered to the subject\n const effectiveConsumer = subject ? consumer.withSubject(subject) : consumer\n\n const natsConsumer = await this.retrieveOrCreateConsumer(effectiveConsumer)\n const sub = await natsConsumer.consume({\n max_messages: 20,\n idle_heartbeat: 15_000,\n expires: 30_000,\n })\n\n return {\n unsubscribe() {\n return sub\n .close()\n .then(() => undefined)\n .catch(() => undefined)\n },\n async* [Symbol.asyncIterator](): AsyncIterator<PubSubMessage<Data>> {\n for await (const message of sub) {\n const { data, redelivered, sid, seq } = message\n const decoded = decode(data)\n logger.info(\n {\n redelivered,\n sid,\n seq,\n decoded,\n },\n 'Received new message: ',\n )\n\n yield {\n ack: () => message.ack(),\n nak: () => message.nak(),\n data: decoded,\n }\n }\n },\n }\n }\n}\n",
"import { jetstream, type JetStreamClient, type JetStreamManager, type PubAck, type PurgeResponse, type StreamInfo } from '@nats-io/jetstream'\nimport ms from 'ms'\n\nimport { Logger } from '@ythub/logger'\n\nimport { PubSubConsumer } from './PubSubConsumer'\nimport { PubSubEvent } from './PubSubEvent'\nimport { PubSubMessage } from './PubSubMessage'\nimport { PubSubPrivateClient } from './PubSubPrivateClient'\nimport { PubSubStream } from './PubSubStream'\nimport { createConditionalLogger } from './utils'\n\nexport type PubSubSubscription<Data> = AsyncIterable<PubSubMessage<Data>> & {\n unsubscribe: () => Promise<void>\n}\n\nfunction escapeSubjectForRegex(subject: string): RegExp {\n return new RegExp(`^${subject.replaceAll('.', '\\\\.').replaceAll('>', '.*')}`)\n}\n\nfunction isNotFound(obj: any): boolean {\n return obj.code === 10014\n}\n\nexport class PubSubStreamContext {\n private logger: Logger = createConditionalLogger('app:PubSubStreamContext')\n\n constructor(\n private readonly stream: PubSubStream,\n private readonly client: PubSubPrivateClient,\n ) {}\n\n protected get jsManager(): JetStreamManager {\n return this.client.jsManager\n }\n\n protected get jetStream(): JetStreamClient {\n return jetstream(this.client.nats)\n }\n\n async deleteAllMessages(): Promise<PurgeResponse> {\n return this.client.jsManager.streams.purge(this.stream.getOptions().name)\n }\n\n /**\n * Initializes the stream, which must be called before calling any `.subscribe()`\n */\n async create(): Promise<StreamInfo> {\n const cfg = this.stream.getOptions()\n if (!cfg.name)\n throw new Error('stream name is required')\n return this.jsManager.streams.add(cfg as Required<Pick<typeof cfg, 'name'>> & typeof cfg)\n }\n\n isNameMatchingStreamSubjects(name: string): boolean {\n const allowedSubjects = this.stream.getOptions().subjects.map(subject => escapeSubjectForRegex(subject))\n\n return allowedSubjects.some(regexp => regexp.test(name))\n }\n\n async publish(subject: string, data: any, id?: string): Promise<PubAck> {\n if (!this.isNameMatchingStreamSubjects(subject)) {\n throw new Error('Subject of the message is not matching names allowed by the stream')\n }\n\n const payload = typeof data === 'string' || data instanceof Uint8Array ? data : JSON.stringify(data)\n return this.jetStream.publish(subject, payload, id ? { msgID: id } : {})\n }\n\n async publishEvent(event: PubSubEvent): Promise<PubAck> {\n this.logger.info('publishing event: ', event.$natsEventName)\n return this.publish(event.$natsEventName, { ...event })\n }\n\n deleteConsumer(consumer: PubSubConsumer) {\n return this.jsManager.consumers.delete(this.stream.getOptions().name, consumer.getConsumerName())\n }\n\n async retrieveOrCreateConsumer(consumer: PubSubConsumer) {\n const streamName = this.stream.getOptions().name\n const consumerName = consumer.getConsumerName()\n\n let info: unknown\n try {\n this.logger.info('querying info')\n info = await this.client.jsManager.consumers.info(streamName, consumerName)\n }\n catch (e: any) {\n this.logger.warn('Failed to acquire consumer info: ', { message: e.message, isNotFound: isNotFound(e) })\n if (isNotFound(e)) {\n info = null\n }\n else {\n throw e\n }\n }\n\n const notFound = info == null || isNotFound(info)\n\n if (notFound) {\n this.logger.info('creating consumer: ', consumerName)\n const created = await this.client.jsManager.consumers.add(streamName, consumer.toConsumerConfig())\n this.logger.info('Created consumer: ', created.name)\n }\n else {\n this.logger.info('updating consumer: ', consumerName)\n await this.client.jsManager.consumers.update(streamName, consumerName, consumer.toConsumerConfig())\n }\n\n return this.client.jsManager.jetstream().consumers.get(streamName, consumerName)\n }\n\n async subscribe<Data = Record<string, never>>(\n consumer: PubSubConsumer,\n subject?: string,\n ): Promise<PubSubSubscription<Data>> {\n const { logger } = this\n const decode = (bytes: Uint8Array) => {\n try {\n const s = new TextDecoder().decode(bytes)\n return JSON.parse(s) as Data\n }\n catch {\n return undefined as unknown as Data\n }\n }\n\n // Ensure the consumer exists and is filtered to the subject\n const effectiveConsumer = subject ? consumer.withSubject(subject) : consumer\n\n const natsConsumer = await this.retrieveOrCreateConsumer(effectiveConsumer)\n const sub = await natsConsumer.consume({\n max_messages: 20,\n idle_heartbeat: 15_000,\n expires: 30_000,\n })\n\n return {\n unsubscribe() {\n return sub\n .close()\n .then(() => undefined)\n .catch(() => undefined)\n },\n async* [Symbol.asyncIterator](): AsyncIterator<PubSubMessage<Data>> {\n for await (const message of sub) {\n const { data, redelivered, sid, seq } = message\n const decoded = decode(data)\n logger.info(\n {\n redelivered,\n sid,\n seq,\n decoded,\n },\n 'Received new message: ',\n )\n\n yield {\n ack: () => message.ack(),\n nak: () => message.nak(),\n nakWithDelay: (delayMs: number | ms.StringValue) => {\n const delay = typeof delayMs === 'number' ? delayMs : ms(delayMs)\n message.nak(delay)\n },\n working: () => message.working(),\n data: decoded,\n deliveryCount: message.info.deliveryCount,\n redelivered: message.redelivered,\n }\n }\n },\n }\n }\n}\n",
"import { createLogger, Logger } from '@ythub/logger'\n\nexport function createConditionalLogger(name: string): Logger {\n const level: any = process.env.JETSTREAM_QUEUE_DEBUG_LEVEL || 'fatal'\n\n return createLogger(name, level)\n}\n",
"import type { ConsumerConfig } from '@nats-io/jetstream'\n\nimport { DeliverPolicy } from '@nats-io/jetstream'\n\nexport interface ConsumerOptions {\n durable?: string\n subject?: string\n policy?: DeliverPolicy\n maxAckPending?: number\n /**\n * For ephemeral consumers only. If omitted, a unique name will be generated.\n */\n name?: string\n /**\n * For ephemeral consumers only. Auto-cleanup after this many milliseconds of inactivity.\n */\n inactiveThresholdMs?: number\n}\n\nexport { DeliverPolicy }\n\nexport class PubSubConsumer {\n private readonly ephemeralName?: string\n\n constructor(public readonly params: ConsumerOptions) {\n const { durable, name } = params\n if (!durable) {\n this.ephemeralName = name || `ephemeral-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`\n }\n }\n\n toConsumerConfig(): Partial<ConsumerConfig> {\n const { durable, policy, maxAckPending, subject, inactiveThresholdMs } = this.params\n\n const base: Partial<ConsumerConfig> = {\n deliver_policy: policy,\n max_ack_pending: maxAckPending,\n filter_subject: subject,\n ack_policy: 'explicit',\n }\n\n if (durable) {\n return {\n ...base,\n durable_name: durable,\n }\n }\n\n return {\n ...base,\n name: this.getConsumerName(),\n inactive_threshold: inactiveThresholdMs ? Math.trunc(inactiveThresholdMs * 1_000_000) : undefined,\n }\n }\n\n getConsumerName(): string {\n return this.params.durable || this.ephemeralName!\n }\n\n withSubject(subject: string): PubSubConsumer {\n return new PubSubConsumer({\n ...this.params,\n durable: this.params.durable,\n name: this.ephemeralName || this.params.name,\n subject,\n })\n }\n}\n"
"import type { ConsumerConfig } from '@nats-io/jetstream'\n\nimport { DeliverPolicy } from '@nats-io/jetstream'\n\nexport interface ConsumerOptions {\n durable?: string\n subject?: string\n policy?: DeliverPolicy\n maxAckPending?: number\n /**\n * For ephemeral consumers only. If omitted, a unique name will be generated.\n */\n name?: string\n /**\n * For ephemeral consumers only. Auto-cleanup after this many milliseconds of inactivity.\n */\n inactiveThresholdMs?: number\n /**\n * How long (in milliseconds) to wait for an acknowledgement before redelivering a message.\n * When backoff is set, this value is ignored and the first backoff value is used instead.\n */\n ackWaitMs?: number\n /**\n * Exponential backoff delays (in milliseconds) for redelivery on acknowledgment timeout.\n * Note: backoff only applies to timeout-based redelivery, NOT to nak().\n * For nak with delay, use nakWithDelay() on the message.\n * Example: [1000, 5000, 30000] will retry after 1s, 5s, then 30s on each timeout.\n */\n backoffMs?: number[]\n /**\n * Maximum number of delivery attempts before the message is considered failed.\n * Should be >= backoffMs.length if backoff is used.\n */\n maxDeliver?: number\n}\n\nexport { DeliverPolicy }\n\nexport class PubSubConsumer {\n private readonly ephemeralName?: string\n\n constructor(public readonly params: ConsumerOptions) {\n const { durable, name } = params\n if (!durable) {\n this.ephemeralName = name || `ephemeral-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`\n }\n }\n\n toConsumerConfig(): Partial<ConsumerConfig> {\n const { durable, policy, maxAckPending, subject, inactiveThresholdMs, ackWaitMs, backoffMs, maxDeliver } = this.params\n\n const base: Partial<ConsumerConfig> = {\n deliver_policy: policy,\n max_ack_pending: maxAckPending,\n filter_subject: subject,\n ack_policy: 'explicit',\n // Convert milliseconds to nanoseconds for NATS\n ack_wait: ackWaitMs ? Math.trunc(ackWaitMs * 1_000_000) : undefined,\n backoff: backoffMs?.map(ms => Math.trunc(ms * 1_000_000)),\n max_deliver: maxDeliver,\n }\n\n if (durable) {\n return {\n ...base,\n durable_name: durable,\n }\n }\n\n return {\n ...base,\n name: this.getConsumerName(),\n inactive_threshold: inactiveThresholdMs ? Math.trunc(inactiveThresholdMs * 1_000_000) : undefined,\n }\n }\n\n getConsumerName(): string {\n return this.params.durable || this.ephemeralName!\n }\n\n withSubject(subject: string): PubSubConsumer {\n return new PubSubConsumer({\n ...this.params,\n durable: this.params.durable,\n name: this.ephemeralName || this.params.name,\n subject,\n })\n }\n}\n"
],
"mappings": "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",
"debugId": "FB9C944FDEFB757464756E2164756E21",
"mappings": "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",
"debugId": "4729336DBA38C91864756E2164756E21",
"names": []
}

@@ -16,2 +16,19 @@ import type { ConsumerConfig } from "@nats-io/jetstream";

inactiveThresholdMs?: number;
/**
* How long (in milliseconds) to wait for an acknowledgement before redelivering a message.
* When backoff is set, this value is ignored and the first backoff value is used instead.
*/
ackWaitMs?: number;
/**
* Exponential backoff delays (in milliseconds) for redelivery on acknowledgment timeout.
* Note: backoff only applies to timeout-based redelivery, NOT to nak().
* For nak with delay, use nakWithDelay() on the message.
* Example: [1000, 5000, 30000] will retry after 1s, 5s, then 30s on each timeout.
*/
backoffMs?: number[];
/**
* Maximum number of delivery attempts before the message is considered failed.
* Should be >= backoffMs.length if backoff is used.
*/
maxDeliver?: number;
}

@@ -18,0 +35,0 @@ export { DeliverPolicy };

@@ -0,5 +1,34 @@

import type ms from "ms";
export interface PubSubMessage<T = Record<string, any>> {
/**
* Acknowledge successful processing of the message
*/
ack: () => void;
/**
* Negative acknowledge - requeue immediately for redelivery
*/
nak: () => void;
/**
* Negative acknowledge with delay - requeue after specified milliseconds or ms string
* @param delayMs - Delay in milliseconds (number) or ms string format ('1m', '10m', '1h', etc.)
*/
nakWithDelay: (delayMs: number | ms.StringValue) => void;
/**
* Signal that processing is ongoing to reset the ack wait timer.
* Prevents redelivery while you're still processing the message.
*/
working: () => void;
/**
* The message payload
*/
data: T;
/**
* The number of times this message has been delivered (starts at 1)
* Use this to calculate exponential backoff delays
*/
deliveryCount: number;
/**
* True if this message was redelivered (deliveryCount > 1)
*/
redelivered: boolean;
}
{
"name": "@ythub/jetstream-queue",
"version": "2.0.2",
"version": "2.0.3",
"type": "module",

@@ -22,2 +22,3 @@ "description": "YT queue module",

"@ythub/logger": "^1.1.4",
"ms": "^2.1.3",
"tslib": "^2.8.1"

@@ -24,0 +25,0 @@ },