@objectstack/service-queue 4.0.4 → 4.0.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@objectstack/service-queue",
3
- "version": "4.0.4",
3
+ "version": "4.0.5",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Queue Service for ObjectStack — implements IQueueService with in-memory and BullMQ adapters",
6
6
  "type": "module",
@@ -14,13 +14,38 @@
14
14
  }
15
15
  },
16
16
  "dependencies": {
17
- "@objectstack/core": "4.0.4",
18
- "@objectstack/spec": "4.0.4"
17
+ "@objectstack/core": "4.0.5",
18
+ "@objectstack/spec": "4.0.5"
19
19
  },
20
20
  "devDependencies": {
21
- "@types/node": "^25.6.0",
22
- "typescript": "^6.0.2",
23
- "vitest": "^4.1.4"
21
+ "@types/node": "^25.6.2",
22
+ "typescript": "^6.0.3",
23
+ "vitest": "^4.1.5"
24
+ },
25
+ "keywords": [
26
+ "objectstack",
27
+ "service",
28
+ "queue",
29
+ "jobs",
30
+ "background"
31
+ ],
32
+ "author": "ObjectStack",
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "https://github.com/objectstack-ai/framework.git",
36
+ "directory": "packages/services/service-queue"
37
+ },
38
+ "homepage": "https://objectstack.ai/docs",
39
+ "bugs": "https://github.com/objectstack-ai/framework/issues",
40
+ "publishConfig": {
41
+ "access": "public"
42
+ },
43
+ "files": [
44
+ "dist",
45
+ "README.md"
46
+ ],
47
+ "engines": {
48
+ "node": ">=18.0.0"
24
49
  },
25
50
  "scripts": {
26
51
  "build": "tsup --config ../../../tsup.config.ts",
@@ -1,22 +0,0 @@
1
-
2
- > @objectstack/service-queue@4.0.4 build /home/runner/work/framework/framework/packages/services/service-queue
3
- > tsup --config ../../../tsup.config.ts
4
-
5
- CLI Building entry: src/index.ts
6
- CLI Using tsconfig: tsconfig.json
7
- CLI tsup v8.5.1
8
- CLI Using tsup config: /home/runner/work/framework/framework/tsup.config.ts
9
- CLI Target: es2020
10
- CLI Cleaning output folder
11
- ESM Build start
12
- CJS Build start
13
- CJS dist/index.cjs 3.89 KB
14
- CJS dist/index.cjs.map 8.90 KB
15
- CJS ⚡️ Build success in 94ms
16
- ESM dist/index.js 2.78 KB
17
- ESM dist/index.js.map 8.33 KB
18
- ESM ⚡️ Build success in 96ms
19
- DTS Build start
20
- DTS ⚡️ Build success in 14371ms
21
- DTS dist/index.d.ts 3.63 KB
22
- DTS dist/index.d.cts 3.63 KB
package/CHANGELOG.md DELETED
@@ -1,177 +0,0 @@
1
- # @objectstack/service-queue
2
-
3
- ## 4.0.4
4
-
5
- ### Patch Changes
6
-
7
- - Updated dependencies [326b66b]
8
- - @objectstack/spec@4.0.4
9
- - @objectstack/core@4.0.4
10
-
11
- ## 4.0.3
12
-
13
- ### Patch Changes
14
-
15
- - @objectstack/spec@4.0.3
16
- - @objectstack/core@4.0.3
17
-
18
- ## 4.0.2
19
-
20
- ### Patch Changes
21
-
22
- - Updated dependencies [5f659e9]
23
- - @objectstack/spec@4.0.2
24
- - @objectstack/core@4.0.2
25
-
26
- ## 4.0.0
27
-
28
- ### Patch Changes
29
-
30
- - Updated dependencies [f08ffc3]
31
- - Updated dependencies [e0b0a78]
32
- - @objectstack/spec@4.0.0
33
- - @objectstack/core@4.0.0
34
-
35
- ## 3.3.1
36
-
37
- ### Patch Changes
38
-
39
- - @objectstack/spec@3.3.1
40
- - @objectstack/core@3.3.1
41
-
42
- ## 3.3.0
43
-
44
- ### Patch Changes
45
-
46
- - @objectstack/spec@3.3.0
47
- - @objectstack/core@3.3.0
48
-
49
- ## 3.2.9
50
-
51
- ### Patch Changes
52
-
53
- - @objectstack/spec@3.2.9
54
- - @objectstack/core@3.2.9
55
-
56
- ## 3.2.8
57
-
58
- ### Patch Changes
59
-
60
- - @objectstack/spec@3.2.8
61
- - @objectstack/core@3.2.8
62
-
63
- ## 3.2.7
64
-
65
- ### Patch Changes
66
-
67
- - @objectstack/spec@3.2.7
68
- - @objectstack/core@3.2.7
69
-
70
- ## 3.2.6
71
-
72
- ### Patch Changes
73
-
74
- - @objectstack/spec@3.2.6
75
- - @objectstack/core@3.2.6
76
-
77
- ## 3.2.5
78
-
79
- ### Patch Changes
80
-
81
- - @objectstack/spec@3.2.5
82
- - @objectstack/core@3.2.5
83
-
84
- ## 3.2.4
85
-
86
- ### Patch Changes
87
-
88
- - @objectstack/spec@3.2.4
89
- - @objectstack/core@3.2.4
90
-
91
- ## 3.2.3
92
-
93
- ### Patch Changes
94
-
95
- - @objectstack/spec@3.2.3
96
- - @objectstack/core@3.2.3
97
-
98
- ## 3.2.2
99
-
100
- ### Patch Changes
101
-
102
- - Updated dependencies [46defbb]
103
- - @objectstack/spec@3.2.2
104
- - @objectstack/core@3.2.2
105
-
106
- ## 3.2.1
107
-
108
- ### Patch Changes
109
-
110
- - Updated dependencies [850b546]
111
- - @objectstack/spec@3.2.1
112
- - @objectstack/core@3.2.1
113
-
114
- ## 3.2.0
115
-
116
- ### Patch Changes
117
-
118
- - Updated dependencies [5901c29]
119
- - @objectstack/spec@3.2.0
120
- - @objectstack/core@3.2.0
121
-
122
- ## 3.1.1
123
-
124
- ### Patch Changes
125
-
126
- - Updated dependencies [953d667]
127
- - @objectstack/spec@3.1.1
128
- - @objectstack/core@3.1.1
129
-
130
- ## 3.1.0
131
-
132
- ### Patch Changes
133
-
134
- - Updated dependencies [0088830]
135
- - @objectstack/spec@3.1.0
136
- - @objectstack/core@3.1.0
137
-
138
- ## 3.0.11
139
-
140
- ### Patch Changes
141
-
142
- - Updated dependencies [92d9d99]
143
- - @objectstack/spec@3.0.11
144
- - @objectstack/core@3.0.11
145
-
146
- ## 3.0.10
147
-
148
- ### Patch Changes
149
-
150
- - Updated dependencies [d1e5d31]
151
- - @objectstack/spec@3.0.10
152
- - @objectstack/core@3.0.10
153
-
154
- ## 3.0.9
155
-
156
- ### Patch Changes
157
-
158
- - Updated dependencies [15e0df6]
159
- - @objectstack/spec@3.0.9
160
- - @objectstack/core@3.0.9
161
-
162
- ## 3.0.8
163
-
164
- ### Patch Changes
165
-
166
- - Updated dependencies [5a968a2]
167
- - @objectstack/spec@3.0.8
168
- - @objectstack/core@3.0.8
169
-
170
- ## 3.0.7
171
-
172
- ### Patch Changes
173
-
174
- - Updated dependencies [0119bd7]
175
- - Updated dependencies [5426bdf]
176
- - @objectstack/spec@3.0.7
177
- - @objectstack/core@3.0.7
@@ -1,58 +0,0 @@
1
- // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
-
3
- import type { IQueueService, QueuePublishOptions, QueueHandler } from '@objectstack/spec/contracts';
4
-
5
- /**
6
- * Configuration for the BullMQ queue adapter.
7
- */
8
- export interface BullMQQueueAdapterOptions {
9
- /** Redis connection URL (e.g. 'redis://localhost:6379') */
10
- redisUrl: string;
11
- /** Default job options */
12
- defaultJobOptions?: {
13
- /** Number of retry attempts */
14
- attempts?: number;
15
- /** Backoff strategy */
16
- backoff?: { type: 'fixed' | 'exponential'; delay: number };
17
- };
18
- }
19
-
20
- /**
21
- * BullMQ queue adapter skeleton implementing IQueueService.
22
- *
23
- * This is a placeholder for future BullMQ integration.
24
- * Concrete implementation will use the `bullmq` package.
25
- *
26
- * @example
27
- * ```ts
28
- * const queue = new BullMQQueueAdapter({ redisUrl: 'redis://localhost:6379' });
29
- * await queue.publish('orders', { orderId: 123 });
30
- * ```
31
- */
32
- export class BullMQQueueAdapter implements IQueueService {
33
- private readonly redisUrl: string;
34
-
35
- constructor(options: BullMQQueueAdapterOptions) {
36
- this.redisUrl = options.redisUrl;
37
- }
38
-
39
- async publish<T = unknown>(_queue: string, _data: T, _options?: QueuePublishOptions): Promise<string> {
40
- throw new Error(`BullMQQueueAdapter not yet implemented (url: ${this.redisUrl})`);
41
- }
42
-
43
- async subscribe<T = unknown>(_queue: string, _handler: QueueHandler<T>): Promise<void> {
44
- throw new Error('BullMQQueueAdapter not yet implemented');
45
- }
46
-
47
- async unsubscribe(_queue: string): Promise<void> {
48
- throw new Error('BullMQQueueAdapter not yet implemented');
49
- }
50
-
51
- async getQueueSize(_queue: string): Promise<number> {
52
- throw new Error('BullMQQueueAdapter not yet implemented');
53
- }
54
-
55
- async purge(_queue: string): Promise<void> {
56
- throw new Error('BullMQQueueAdapter not yet implemented');
57
- }
58
- }
package/src/index.ts DELETED
@@ -1,8 +0,0 @@
1
- // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
-
3
- export { QueueServicePlugin } from './queue-service-plugin.js';
4
- export type { QueueServicePluginOptions } from './queue-service-plugin.js';
5
- export { MemoryQueueAdapter } from './memory-queue-adapter.js';
6
- export type { MemoryQueueAdapterOptions } from './memory-queue-adapter.js';
7
- export { BullMQQueueAdapter } from './bullmq-queue-adapter.js';
8
- export type { BullMQQueueAdapterOptions } from './bullmq-queue-adapter.js';
@@ -1,87 +0,0 @@
1
- // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
-
3
- import { describe, it, expect } from 'vitest';
4
- import { MemoryQueueAdapter } from './memory-queue-adapter';
5
- import type { IQueueService, QueueMessage } from '@objectstack/spec/contracts';
6
-
7
- describe('MemoryQueueAdapter', () => {
8
- it('should implement IQueueService contract', () => {
9
- const queue: IQueueService = new MemoryQueueAdapter();
10
- expect(typeof queue.publish).toBe('function');
11
- expect(typeof queue.subscribe).toBe('function');
12
- expect(typeof queue.unsubscribe).toBe('function');
13
- expect(typeof queue.getQueueSize).toBe('function');
14
- expect(typeof queue.purge).toBe('function');
15
- });
16
-
17
- it('should publish and deliver to subscriber', async () => {
18
- const queue = new MemoryQueueAdapter();
19
- const received: QueueMessage[] = [];
20
-
21
- await queue.subscribe('orders', async (msg) => {
22
- received.push(msg);
23
- });
24
-
25
- const id = await queue.publish('orders', { orderId: 123 });
26
- expect(id).toBe('msg-1');
27
- expect(received).toHaveLength(1);
28
- expect(received[0].data).toEqual({ orderId: 123 });
29
- expect(received[0].attempts).toBe(1);
30
- });
31
-
32
- it('should support multiple subscribers', async () => {
33
- const queue = new MemoryQueueAdapter();
34
- const log1: unknown[] = [];
35
- const log2: unknown[] = [];
36
-
37
- await queue.subscribe('events', async (msg) => { log1.push(msg.data); });
38
- await queue.subscribe('events', async (msg) => { log2.push(msg.data); });
39
-
40
- await queue.publish('events', 'hello');
41
- expect(log1).toEqual(['hello']);
42
- expect(log2).toEqual(['hello']);
43
- });
44
-
45
- it('should unsubscribe from a queue', async () => {
46
- const queue = new MemoryQueueAdapter();
47
- const received: unknown[] = [];
48
-
49
- await queue.subscribe('q1', async (msg) => { received.push(msg.data); });
50
- await queue.unsubscribe('q1');
51
- await queue.publish('q1', 'data');
52
- expect(received).toHaveLength(0);
53
- });
54
-
55
- it('should retain dead letters when no subscribers', async () => {
56
- const queue = new MemoryQueueAdapter();
57
- const id = await queue.publish('orphan', { lost: true });
58
- expect(id).toBe('msg-1');
59
- });
60
-
61
- it('should return queue size of 0 for in-memory queue', async () => {
62
- const queue = new MemoryQueueAdapter();
63
- expect(await queue.getQueueSize('test')).toBe(0);
64
- });
65
-
66
- it('should purge a queue by removing handlers', async () => {
67
- const queue = new MemoryQueueAdapter();
68
- const received: unknown[] = [];
69
-
70
- await queue.subscribe('q1', async (msg) => { received.push(msg.data); });
71
- await queue.purge('q1');
72
- await queue.publish('q1', 'data');
73
- expect(received).toHaveLength(0);
74
- });
75
-
76
- it('should increment message counter across publishes', async () => {
77
- const queue = new MemoryQueueAdapter();
78
- const ids: string[] = [];
79
-
80
- await queue.subscribe('q', async () => {});
81
- ids.push(await queue.publish('q', 'a'));
82
- ids.push(await queue.publish('q', 'b'));
83
- ids.push(await queue.publish('q', 'c'));
84
-
85
- expect(ids).toEqual(['msg-1', 'msg-2', 'msg-3']);
86
- });
87
- });
@@ -1,82 +0,0 @@
1
- // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
-
3
- import type { IQueueService, QueuePublishOptions, QueueMessage, QueueHandler } from '@objectstack/spec/contracts';
4
-
5
- /**
6
- * Configuration options for MemoryQueueAdapter.
7
- */
8
- export interface MemoryQueueAdapterOptions {
9
- /** Maximum number of messages retained per queue (0 = unlimited) */
10
- maxQueueSize?: number;
11
- }
12
-
13
- /**
14
- * In-memory queue adapter implementing IQueueService.
15
- *
16
- * Provides synchronous in-process pub/sub delivery.
17
- * Suitable for single-process environments, development, and testing.
18
- */
19
- export class MemoryQueueAdapter implements IQueueService {
20
- private readonly handlers = new Map<string, QueueHandler[]>();
21
- private readonly deadLetters: QueueMessage[] = [];
22
- private msgCounter = 0;
23
- private readonly maxQueueSize: number;
24
-
25
- constructor(options: MemoryQueueAdapterOptions = {}) {
26
- this.maxQueueSize = options.maxQueueSize ?? 0;
27
- }
28
-
29
- async publish<T = unknown>(queue: string, data: T, options?: QueuePublishOptions): Promise<string> {
30
- const id = `msg-${++this.msgCounter}`;
31
- const msg: QueueMessage<T> = {
32
- id,
33
- data,
34
- attempts: 0,
35
- timestamp: Date.now(),
36
- };
37
-
38
- const fns = this.handlers.get(queue) ?? [];
39
- if (fns.length === 0) {
40
- // No subscribers — retain as dead letter if within limits
41
- if (this.maxQueueSize === 0 || this.deadLetters.length < this.maxQueueSize) {
42
- this.deadLetters.push(msg);
43
- }
44
- return id;
45
- }
46
-
47
- const maxRetries = options?.retries ?? 0;
48
- for (const handler of fns) {
49
- let attempt = 0;
50
- let success = false;
51
- while (!success && attempt <= maxRetries) {
52
- try {
53
- msg.attempts = attempt + 1;
54
- await handler(msg as QueueMessage);
55
- success = true;
56
- } catch {
57
- attempt++;
58
- }
59
- }
60
- }
61
-
62
- return id;
63
- }
64
-
65
- async subscribe<T = unknown>(queue: string, handler: QueueHandler<T>): Promise<void> {
66
- const existing = this.handlers.get(queue) ?? [];
67
- this.handlers.set(queue, [...existing, handler as QueueHandler]);
68
- }
69
-
70
- async unsubscribe(queue: string): Promise<void> {
71
- this.handlers.delete(queue);
72
- }
73
-
74
- async getQueueSize(_queue: string): Promise<number> {
75
- // In-memory: no persistent queue depth tracking
76
- return 0;
77
- }
78
-
79
- async purge(queue: string): Promise<void> {
80
- this.handlers.delete(queue);
81
- }
82
- }
@@ -1,62 +0,0 @@
1
- // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2
-
3
- import type { Plugin, PluginContext } from '@objectstack/core';
4
- import { MemoryQueueAdapter } from './memory-queue-adapter.js';
5
- import type { MemoryQueueAdapterOptions } from './memory-queue-adapter.js';
6
-
7
- /**
8
- * Configuration options for the QueueServicePlugin.
9
- */
10
- export interface QueueServicePluginOptions {
11
- /** Queue adapter type (default: 'memory') */
12
- adapter?: 'memory' | 'bullmq';
13
- /** Options for the memory queue adapter */
14
- memory?: MemoryQueueAdapterOptions;
15
- /** Redis connection URL (used when adapter is 'bullmq') */
16
- redisUrl?: string;
17
- }
18
-
19
- /**
20
- * QueueServicePlugin — Production IQueueService implementation.
21
- *
22
- * Registers a queue service with the kernel during the init phase.
23
- * Supports in-memory and BullMQ adapters.
24
- *
25
- * @example
26
- * ```ts
27
- * import { ObjectKernel } from '@objectstack/core';
28
- * import { QueueServicePlugin } from '@objectstack/service-queue';
29
- *
30
- * const kernel = new ObjectKernel();
31
- * kernel.use(new QueueServicePlugin({ adapter: 'memory' }));
32
- * await kernel.bootstrap();
33
- *
34
- * const queue = kernel.getService('queue');
35
- * await queue.publish('orders', { orderId: 123 });
36
- * ```
37
- */
38
- export class QueueServicePlugin implements Plugin {
39
- name = 'com.objectstack.service.queue';
40
- version = '1.0.0';
41
- type = 'standard';
42
-
43
- private readonly options: QueueServicePluginOptions;
44
-
45
- constructor(options: QueueServicePluginOptions = {}) {
46
- this.options = { adapter: 'memory', ...options };
47
- }
48
-
49
- async init(ctx: PluginContext): Promise<void> {
50
- const adapter = this.options.adapter;
51
- if (adapter === 'bullmq') {
52
- throw new Error(
53
- 'BullMQ queue adapter is not yet implemented. ' +
54
- 'Use adapter: "memory" or provide a custom IQueueService via ctx.registerService("queue", impl).'
55
- );
56
- }
57
-
58
- const queue = new MemoryQueueAdapter(this.options.memory);
59
- ctx.registerService('queue', queue);
60
- ctx.logger.info('QueueServicePlugin: registered memory queue adapter');
61
- }
62
- }
package/tsconfig.json DELETED
@@ -1,17 +0,0 @@
1
- {
2
- "extends": "../../../tsconfig.json",
3
- "compilerOptions": {
4
- "outDir": "dist",
5
- "rootDir": "src",
6
- "types": [
7
- "node"
8
- ]
9
- },
10
- "include": [
11
- "src"
12
- ],
13
- "exclude": [
14
- "node_modules",
15
- "dist"
16
- ]
17
- }