@objectstack/service-queue 4.0.5 → 4.1.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/index.cjs +408 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +113 -20
- package/dist/index.d.ts +113 -20
- package/dist/index.js +407 -8
- package/dist/index.js.map +1 -1
- package/package.json +6 -5
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Plugin, PluginContext } from '@objectstack/core';
|
|
2
|
-
import { IQueueService, QueuePublishOptions, QueueHandler } from '@objectstack/spec/contracts';
|
|
2
|
+
import { IQueueService, QueuePublishOptions, QueueHandler, QueueMessageRecord } from '@objectstack/spec/contracts';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Configuration options for MemoryQueueAdapter.
|
|
@@ -27,43 +27,136 @@ declare class MemoryQueueAdapter implements IQueueService {
|
|
|
27
27
|
purge(queue: string): Promise<void>;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
/**
|
|
31
|
+
* Narrow ObjectQL engine surface used by job/queue adapters.
|
|
32
|
+
* Keeps the adapter testable without booting a real kernel.
|
|
33
|
+
*
|
|
34
|
+
* IMPORTANT: matches the canonical engine API:
|
|
35
|
+
* - find: `where:` (NOT `filter:`)
|
|
36
|
+
* - update: `(table, {id, ...patch}, opts)`
|
|
37
|
+
*/
|
|
38
|
+
interface JobEngine {
|
|
39
|
+
find(object: string, options?: any): Promise<any[]>;
|
|
40
|
+
insert(object: string, data: any, options?: any): Promise<any>;
|
|
41
|
+
update(object: string, idOrData: any, dataOrOptions?: any, options?: any): Promise<any>;
|
|
42
|
+
delete(object: string, options?: any): Promise<any>;
|
|
43
|
+
}
|
|
44
|
+
/** Stamped only in tests to make `now` deterministic. */
|
|
45
|
+
interface JobClock {
|
|
46
|
+
now(): Date;
|
|
47
|
+
}
|
|
48
|
+
interface JobLogger {
|
|
49
|
+
info(msg: string, meta?: unknown): void;
|
|
50
|
+
warn(msg: string, meta?: unknown): void;
|
|
51
|
+
error?(msg: string, meta?: unknown): void;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
interface DbQueueAdapterOptions {
|
|
55
|
+
/** Polling interval for the worker loop (ms, default 1000) */
|
|
56
|
+
pollIntervalMs?: number;
|
|
57
|
+
/** Max messages claimed per poll tick (default 10) */
|
|
58
|
+
batchSize?: number;
|
|
59
|
+
/** Lease duration before another worker may reclaim (ms, default 30000) */
|
|
60
|
+
leaseMs?: number;
|
|
61
|
+
/** Idempotency window — how long the same key blocks re-publish (ms, default 24h) */
|
|
62
|
+
idempotencyWindowMs?: number;
|
|
63
|
+
/** Default maxAttempts when publish doesn't specify (default 3) */
|
|
64
|
+
defaultMaxAttempts?: number;
|
|
65
|
+
/** Unique identifier for this worker (default: random) */
|
|
66
|
+
workerId?: string;
|
|
67
|
+
/** Whether to auto-start the polling worker (default true) */
|
|
68
|
+
autoStart?: boolean;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* DbQueueAdapter — durable, polling, DB-backed IQueueService.
|
|
72
|
+
*
|
|
73
|
+
* Persists every message to `sys_job_queue`. A polling worker leases
|
|
74
|
+
* pending messages (CAS update status pending→running with a lease),
|
|
75
|
+
* invokes registered subscribers, and retries with backoff on failure.
|
|
76
|
+
* Messages that exceed `max_attempts` land in `status='dlq'`.
|
|
77
|
+
*
|
|
78
|
+
* Idempotency: publish suppresses duplicates within a configurable
|
|
79
|
+
* window when `(queue, idempotencyKey)` is non-null.
|
|
80
|
+
*
|
|
81
|
+
* Designed for SQLite and Postgres alike — uses CAS via WHERE-clauses,
|
|
82
|
+
* not row-level locking.
|
|
83
|
+
*/
|
|
84
|
+
declare class DbQueueAdapter implements IQueueService {
|
|
85
|
+
private readonly engine;
|
|
86
|
+
private readonly logger?;
|
|
87
|
+
private readonly clock?;
|
|
88
|
+
private readonly opts;
|
|
89
|
+
private readonly handlers;
|
|
90
|
+
private timer?;
|
|
91
|
+
private running;
|
|
92
|
+
constructor(args: {
|
|
93
|
+
engine: JobEngine;
|
|
94
|
+
logger?: JobLogger;
|
|
95
|
+
clock?: JobClock;
|
|
96
|
+
options?: DbQueueAdapterOptions;
|
|
97
|
+
});
|
|
98
|
+
publish<T = unknown>(queue: string, data: T, options?: QueuePublishOptions): Promise<string>;
|
|
99
|
+
subscribe<T = unknown>(queue: string, handler: QueueHandler<T>): Promise<void>;
|
|
100
|
+
unsubscribe(queue: string): Promise<void>;
|
|
101
|
+
getQueueSize(queue: string): Promise<number>;
|
|
102
|
+
purge(queue: string): Promise<void>;
|
|
103
|
+
listFailed(queue?: string, options?: {
|
|
104
|
+
limit?: number;
|
|
105
|
+
offset?: number;
|
|
106
|
+
}): Promise<QueueMessageRecord[]>;
|
|
107
|
+
replay(messageId: string): Promise<void>;
|
|
108
|
+
purgeFailed(messageId: string): Promise<void>;
|
|
109
|
+
start(): void;
|
|
110
|
+
stop(): Promise<void>;
|
|
111
|
+
/** Test-friendly synchronous poll. */
|
|
112
|
+
pollOnce(): Promise<number>;
|
|
113
|
+
private claimBatch;
|
|
114
|
+
private dispatch;
|
|
115
|
+
private computeBackoff;
|
|
116
|
+
private releasePending;
|
|
117
|
+
private loadById;
|
|
118
|
+
private rowToRecord;
|
|
119
|
+
private now;
|
|
120
|
+
}
|
|
121
|
+
|
|
30
122
|
/**
|
|
31
123
|
* Configuration options for the QueueServicePlugin.
|
|
32
124
|
*/
|
|
33
125
|
interface QueueServicePluginOptions {
|
|
34
|
-
/**
|
|
35
|
-
|
|
126
|
+
/**
|
|
127
|
+
* Queue adapter type.
|
|
128
|
+
* - 'auto' (default): use DbQueueAdapter when objectql engine available, else MemoryQueueAdapter
|
|
129
|
+
* - 'db': require objectql; persists messages, retries, and DLQ to sys_job_queue
|
|
130
|
+
* - 'memory': in-process MemoryQueueAdapter (non-durable, dev/test)
|
|
131
|
+
* - 'bullmq': reserved for M10.43 (throws today)
|
|
132
|
+
*/
|
|
133
|
+
adapter?: 'auto' | 'db' | 'memory' | 'bullmq';
|
|
36
134
|
/** Options for the memory queue adapter */
|
|
37
135
|
memory?: MemoryQueueAdapterOptions;
|
|
38
|
-
/**
|
|
136
|
+
/** Options for the DB adapter (polling, batch, lease, idempotency window…) */
|
|
137
|
+
db?: DbQueueAdapterOptions;
|
|
138
|
+
/** Redis connection URL (reserved for bullmq) */
|
|
39
139
|
redisUrl?: string;
|
|
40
140
|
}
|
|
41
141
|
/**
|
|
42
142
|
* QueueServicePlugin — Production IQueueService implementation.
|
|
43
143
|
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
* import { QueueServicePlugin } from '@objectstack/service-queue';
|
|
51
|
-
*
|
|
52
|
-
* const kernel = new ObjectKernel();
|
|
53
|
-
* kernel.use(new QueueServicePlugin({ adapter: 'memory' }));
|
|
54
|
-
* await kernel.bootstrap();
|
|
55
|
-
*
|
|
56
|
-
* const queue = kernel.getService('queue');
|
|
57
|
-
* await queue.publish('orders', { orderId: 123 });
|
|
58
|
-
* ```
|
|
144
|
+
* Default: registers MemoryQueueAdapter synchronously so producers can
|
|
145
|
+
* publish during plugin init; upgrades to DbQueueAdapter on `kernel:ready`
|
|
146
|
+
* when an ObjectQL engine is available. Subscribers registered against
|
|
147
|
+
* the (now-replaced) memory queue must re-subscribe after upgrade — for
|
|
148
|
+
* that reason most plugins register subscribers inside their own
|
|
149
|
+
* `kernel:ready` hook, which fires after this one.
|
|
59
150
|
*/
|
|
60
151
|
declare class QueueServicePlugin implements Plugin {
|
|
61
152
|
name: string;
|
|
62
153
|
version: string;
|
|
63
154
|
type: string;
|
|
64
155
|
private readonly options;
|
|
156
|
+
private dbAdapter?;
|
|
65
157
|
constructor(options?: QueueServicePluginOptions);
|
|
66
158
|
init(ctx: PluginContext): Promise<void>;
|
|
159
|
+
destroy(): Promise<void>;
|
|
67
160
|
}
|
|
68
161
|
|
|
69
162
|
/**
|
|
@@ -105,4 +198,4 @@ declare class BullMQQueueAdapter implements IQueueService {
|
|
|
105
198
|
purge(_queue: string): Promise<void>;
|
|
106
199
|
}
|
|
107
200
|
|
|
108
|
-
export { BullMQQueueAdapter, type BullMQQueueAdapterOptions, MemoryQueueAdapter, type MemoryQueueAdapterOptions, QueueServicePlugin, type QueueServicePluginOptions };
|
|
201
|
+
export { BullMQQueueAdapter, type BullMQQueueAdapterOptions, DbQueueAdapter, type DbQueueAdapterOptions, type JobClock, type JobEngine, type JobLogger, MemoryQueueAdapter, type MemoryQueueAdapterOptions, QueueServicePlugin, type QueueServicePluginOptions };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Plugin, PluginContext } from '@objectstack/core';
|
|
2
|
-
import { IQueueService, QueuePublishOptions, QueueHandler } from '@objectstack/spec/contracts';
|
|
2
|
+
import { IQueueService, QueuePublishOptions, QueueHandler, QueueMessageRecord } from '@objectstack/spec/contracts';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Configuration options for MemoryQueueAdapter.
|
|
@@ -27,43 +27,136 @@ declare class MemoryQueueAdapter implements IQueueService {
|
|
|
27
27
|
purge(queue: string): Promise<void>;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
/**
|
|
31
|
+
* Narrow ObjectQL engine surface used by job/queue adapters.
|
|
32
|
+
* Keeps the adapter testable without booting a real kernel.
|
|
33
|
+
*
|
|
34
|
+
* IMPORTANT: matches the canonical engine API:
|
|
35
|
+
* - find: `where:` (NOT `filter:`)
|
|
36
|
+
* - update: `(table, {id, ...patch}, opts)`
|
|
37
|
+
*/
|
|
38
|
+
interface JobEngine {
|
|
39
|
+
find(object: string, options?: any): Promise<any[]>;
|
|
40
|
+
insert(object: string, data: any, options?: any): Promise<any>;
|
|
41
|
+
update(object: string, idOrData: any, dataOrOptions?: any, options?: any): Promise<any>;
|
|
42
|
+
delete(object: string, options?: any): Promise<any>;
|
|
43
|
+
}
|
|
44
|
+
/** Stamped only in tests to make `now` deterministic. */
|
|
45
|
+
interface JobClock {
|
|
46
|
+
now(): Date;
|
|
47
|
+
}
|
|
48
|
+
interface JobLogger {
|
|
49
|
+
info(msg: string, meta?: unknown): void;
|
|
50
|
+
warn(msg: string, meta?: unknown): void;
|
|
51
|
+
error?(msg: string, meta?: unknown): void;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
interface DbQueueAdapterOptions {
|
|
55
|
+
/** Polling interval for the worker loop (ms, default 1000) */
|
|
56
|
+
pollIntervalMs?: number;
|
|
57
|
+
/** Max messages claimed per poll tick (default 10) */
|
|
58
|
+
batchSize?: number;
|
|
59
|
+
/** Lease duration before another worker may reclaim (ms, default 30000) */
|
|
60
|
+
leaseMs?: number;
|
|
61
|
+
/** Idempotency window — how long the same key blocks re-publish (ms, default 24h) */
|
|
62
|
+
idempotencyWindowMs?: number;
|
|
63
|
+
/** Default maxAttempts when publish doesn't specify (default 3) */
|
|
64
|
+
defaultMaxAttempts?: number;
|
|
65
|
+
/** Unique identifier for this worker (default: random) */
|
|
66
|
+
workerId?: string;
|
|
67
|
+
/** Whether to auto-start the polling worker (default true) */
|
|
68
|
+
autoStart?: boolean;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* DbQueueAdapter — durable, polling, DB-backed IQueueService.
|
|
72
|
+
*
|
|
73
|
+
* Persists every message to `sys_job_queue`. A polling worker leases
|
|
74
|
+
* pending messages (CAS update status pending→running with a lease),
|
|
75
|
+
* invokes registered subscribers, and retries with backoff on failure.
|
|
76
|
+
* Messages that exceed `max_attempts` land in `status='dlq'`.
|
|
77
|
+
*
|
|
78
|
+
* Idempotency: publish suppresses duplicates within a configurable
|
|
79
|
+
* window when `(queue, idempotencyKey)` is non-null.
|
|
80
|
+
*
|
|
81
|
+
* Designed for SQLite and Postgres alike — uses CAS via WHERE-clauses,
|
|
82
|
+
* not row-level locking.
|
|
83
|
+
*/
|
|
84
|
+
declare class DbQueueAdapter implements IQueueService {
|
|
85
|
+
private readonly engine;
|
|
86
|
+
private readonly logger?;
|
|
87
|
+
private readonly clock?;
|
|
88
|
+
private readonly opts;
|
|
89
|
+
private readonly handlers;
|
|
90
|
+
private timer?;
|
|
91
|
+
private running;
|
|
92
|
+
constructor(args: {
|
|
93
|
+
engine: JobEngine;
|
|
94
|
+
logger?: JobLogger;
|
|
95
|
+
clock?: JobClock;
|
|
96
|
+
options?: DbQueueAdapterOptions;
|
|
97
|
+
});
|
|
98
|
+
publish<T = unknown>(queue: string, data: T, options?: QueuePublishOptions): Promise<string>;
|
|
99
|
+
subscribe<T = unknown>(queue: string, handler: QueueHandler<T>): Promise<void>;
|
|
100
|
+
unsubscribe(queue: string): Promise<void>;
|
|
101
|
+
getQueueSize(queue: string): Promise<number>;
|
|
102
|
+
purge(queue: string): Promise<void>;
|
|
103
|
+
listFailed(queue?: string, options?: {
|
|
104
|
+
limit?: number;
|
|
105
|
+
offset?: number;
|
|
106
|
+
}): Promise<QueueMessageRecord[]>;
|
|
107
|
+
replay(messageId: string): Promise<void>;
|
|
108
|
+
purgeFailed(messageId: string): Promise<void>;
|
|
109
|
+
start(): void;
|
|
110
|
+
stop(): Promise<void>;
|
|
111
|
+
/** Test-friendly synchronous poll. */
|
|
112
|
+
pollOnce(): Promise<number>;
|
|
113
|
+
private claimBatch;
|
|
114
|
+
private dispatch;
|
|
115
|
+
private computeBackoff;
|
|
116
|
+
private releasePending;
|
|
117
|
+
private loadById;
|
|
118
|
+
private rowToRecord;
|
|
119
|
+
private now;
|
|
120
|
+
}
|
|
121
|
+
|
|
30
122
|
/**
|
|
31
123
|
* Configuration options for the QueueServicePlugin.
|
|
32
124
|
*/
|
|
33
125
|
interface QueueServicePluginOptions {
|
|
34
|
-
/**
|
|
35
|
-
|
|
126
|
+
/**
|
|
127
|
+
* Queue adapter type.
|
|
128
|
+
* - 'auto' (default): use DbQueueAdapter when objectql engine available, else MemoryQueueAdapter
|
|
129
|
+
* - 'db': require objectql; persists messages, retries, and DLQ to sys_job_queue
|
|
130
|
+
* - 'memory': in-process MemoryQueueAdapter (non-durable, dev/test)
|
|
131
|
+
* - 'bullmq': reserved for M10.43 (throws today)
|
|
132
|
+
*/
|
|
133
|
+
adapter?: 'auto' | 'db' | 'memory' | 'bullmq';
|
|
36
134
|
/** Options for the memory queue adapter */
|
|
37
135
|
memory?: MemoryQueueAdapterOptions;
|
|
38
|
-
/**
|
|
136
|
+
/** Options for the DB adapter (polling, batch, lease, idempotency window…) */
|
|
137
|
+
db?: DbQueueAdapterOptions;
|
|
138
|
+
/** Redis connection URL (reserved for bullmq) */
|
|
39
139
|
redisUrl?: string;
|
|
40
140
|
}
|
|
41
141
|
/**
|
|
42
142
|
* QueueServicePlugin — Production IQueueService implementation.
|
|
43
143
|
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
* import { QueueServicePlugin } from '@objectstack/service-queue';
|
|
51
|
-
*
|
|
52
|
-
* const kernel = new ObjectKernel();
|
|
53
|
-
* kernel.use(new QueueServicePlugin({ adapter: 'memory' }));
|
|
54
|
-
* await kernel.bootstrap();
|
|
55
|
-
*
|
|
56
|
-
* const queue = kernel.getService('queue');
|
|
57
|
-
* await queue.publish('orders', { orderId: 123 });
|
|
58
|
-
* ```
|
|
144
|
+
* Default: registers MemoryQueueAdapter synchronously so producers can
|
|
145
|
+
* publish during plugin init; upgrades to DbQueueAdapter on `kernel:ready`
|
|
146
|
+
* when an ObjectQL engine is available. Subscribers registered against
|
|
147
|
+
* the (now-replaced) memory queue must re-subscribe after upgrade — for
|
|
148
|
+
* that reason most plugins register subscribers inside their own
|
|
149
|
+
* `kernel:ready` hook, which fires after this one.
|
|
59
150
|
*/
|
|
60
151
|
declare class QueueServicePlugin implements Plugin {
|
|
61
152
|
name: string;
|
|
62
153
|
version: string;
|
|
63
154
|
type: string;
|
|
64
155
|
private readonly options;
|
|
156
|
+
private dbAdapter?;
|
|
65
157
|
constructor(options?: QueueServicePluginOptions);
|
|
66
158
|
init(ctx: PluginContext): Promise<void>;
|
|
159
|
+
destroy(): Promise<void>;
|
|
67
160
|
}
|
|
68
161
|
|
|
69
162
|
/**
|
|
@@ -105,4 +198,4 @@ declare class BullMQQueueAdapter implements IQueueService {
|
|
|
105
198
|
purge(_queue: string): Promise<void>;
|
|
106
199
|
}
|
|
107
200
|
|
|
108
|
-
export { BullMQQueueAdapter, type BullMQQueueAdapterOptions, MemoryQueueAdapter, type MemoryQueueAdapterOptions, QueueServicePlugin, type QueueServicePluginOptions };
|
|
201
|
+
export { BullMQQueueAdapter, type BullMQQueueAdapterOptions, DbQueueAdapter, type DbQueueAdapterOptions, type JobClock, type JobEngine, type JobLogger, MemoryQueueAdapter, type MemoryQueueAdapterOptions, QueueServicePlugin, type QueueServicePluginOptions };
|