queue-tool 1.0.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.
@@ -0,0 +1,102 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const redis_1 = require("./redis");
7
+ const ioredis_1 = __importDefault(require("ioredis"));
8
+ describe('RedisQueueAdapter Integration Tests', () => {
9
+ let adapter;
10
+ let redisClient;
11
+ const queueName = 'test-redis-integration-queue';
12
+ const connectionString = 'redis://localhost:6379';
13
+ let isAvailable = true;
14
+ beforeAll(async () => {
15
+ try {
16
+ redisClient = new ioredis_1.default(connectionString);
17
+ await redisClient.ping();
18
+ adapter = new redis_1.RedisQueueAdapter(connectionString);
19
+ await adapter.init();
20
+ }
21
+ catch (err) {
22
+ isAvailable = false;
23
+ console.warn('Redis is not running. Skipping Redis integration tests.');
24
+ }
25
+ });
26
+ afterAll(async () => {
27
+ if (!isAvailable)
28
+ return;
29
+ await adapter.close();
30
+ await redisClient.quit();
31
+ });
32
+ beforeEach(async () => {
33
+ if (!isAvailable)
34
+ return;
35
+ // Clean keys related to our test queue
36
+ const keys = await redisClient.keys(`*${queueName}*`);
37
+ if (keys.length > 0) {
38
+ await redisClient.del(...keys);
39
+ }
40
+ });
41
+ test('should enqueue a job successfully', async () => {
42
+ if (!isAvailable)
43
+ return;
44
+ const payload = { task: 'test-node-enqueue', value: 100 };
45
+ const job = await adapter.enqueue(queueName, payload, { priority: 10 });
46
+ expect(job.id).toBeDefined();
47
+ expect(job.queue).toBe(queueName);
48
+ expect(job.payload).toEqual(payload);
49
+ expect(job.status).toBe('pending');
50
+ expect(job.priority).toBe(10);
51
+ });
52
+ test('should fail validation on invalid priority bounds', async () => {
53
+ if (!isAvailable)
54
+ return;
55
+ const payload = { task: 'test-priority-bounds' };
56
+ await expect(adapter.enqueue(queueName, payload, { priority: 2000 })).rejects.toThrow('Priority must be in the range [-1000, 1000]');
57
+ });
58
+ test('should claim and complete a job successfully', async () => {
59
+ if (!isAvailable)
60
+ return;
61
+ const payload = { task: 'test-node-claim', value: 200 };
62
+ const job = await adapter.enqueue(queueName, payload);
63
+ const claimedJob = await adapter.claimJob(queueName, 'worker-test-node-1');
64
+ expect(claimedJob).not.toBeNull();
65
+ expect(claimedJob.id).toBe(job.id);
66
+ expect(claimedJob.status).toBe('processing');
67
+ expect(claimedJob.attempts).toBe(1);
68
+ await adapter.completeJob(claimedJob.id);
69
+ const finalJob = await adapter.getJob(job.id);
70
+ expect(finalJob).not.toBeNull();
71
+ expect(finalJob.status).toBe('completed');
72
+ });
73
+ test('should fail and retry job within maxAttempts limit', async () => {
74
+ if (!isAvailable)
75
+ return;
76
+ const payload = { task: 'test-node-retry' };
77
+ const job = await adapter.enqueue(queueName, payload, { maxAttempts: 2 });
78
+ const claimedJob = await adapter.claimJob(queueName, 'worker-test-node-2');
79
+ expect(claimedJob).not.toBeNull();
80
+ await adapter.failJob(claimedJob.id, 'First test error');
81
+ const retriedJob = await adapter.getJob(job.id);
82
+ expect(retriedJob).not.toBeNull();
83
+ expect(retriedJob.status).toBe('pending');
84
+ expect(retriedJob.error).toBe('First test error');
85
+ // Manually update run_at to past to bypass 5s retry delay
86
+ const jobKey = `job:${job.id}`;
87
+ const pastTime = Date.now() - 60000;
88
+ await redisClient.hset(jobKey, 'run_at', pastTime.toString());
89
+ const score = pastTime - (job.priority * 10000000000);
90
+ await redisClient.zadd(`queue:${queueName}:pending`, score, job.id);
91
+ // Claim again (2nd attempt)
92
+ const claimedJob2 = await adapter.claimJob(queueName, 'worker-test-node-2');
93
+ expect(claimedJob2).not.toBeNull();
94
+ expect(claimedJob2.attempts).toBe(2);
95
+ // Fail again -> terminal failure
96
+ await adapter.failJob(claimedJob2.id, 'Second test error');
97
+ const finalJob = await adapter.getJob(job.id);
98
+ expect(finalJob).not.toBeNull();
99
+ expect(finalJob.status).toBe('failed');
100
+ expect(finalJob.error).toBe('Second test error');
101
+ });
102
+ });
@@ -0,0 +1,4 @@
1
+ import { IQueueAdapter } from './types';
2
+ export declare class QueueFactory {
3
+ static create(connectionString: string): Promise<IQueueAdapter>;
4
+ }
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.QueueFactory = void 0;
4
+ const postgres_1 = require("./adapters/postgres");
5
+ const redis_1 = require("./adapters/redis");
6
+ const mongodb_1 = require("./adapters/mongodb");
7
+ const logger_1 = require("./utils/logger");
8
+ class QueueFactory {
9
+ static async create(connectionString) {
10
+ logger_1.logger.info('Creating queue adapter...', { connectionString });
11
+ if (connectionString.startsWith('postgres://') || connectionString.startsWith('postgresql://')) {
12
+ logger_1.logger.info('Selected Postgres Queue Adapter');
13
+ const adapter = new postgres_1.PostgresQueueAdapter(connectionString);
14
+ await adapter.init();
15
+ return adapter;
16
+ }
17
+ else if (connectionString.startsWith('redis://') || connectionString.startsWith('rediss://')) {
18
+ logger_1.logger.info('Selected Redis Queue Adapter');
19
+ const adapter = new redis_1.RedisQueueAdapter(connectionString);
20
+ await adapter.init();
21
+ return adapter;
22
+ }
23
+ else if (connectionString.startsWith('mongodb://') || connectionString.startsWith('mongodb+srv://')) {
24
+ logger_1.logger.info('Selected MongoDB Queue Adapter');
25
+ const adapter = new mongodb_1.MongoQueueAdapter(connectionString);
26
+ await adapter.init();
27
+ return adapter;
28
+ }
29
+ else {
30
+ logger_1.logger.error('Unsupported connection string', { connectionString });
31
+ throw new Error(`Unsupported connection string: ${connectionString}`);
32
+ }
33
+ }
34
+ }
35
+ exports.QueueFactory = QueueFactory;
@@ -0,0 +1,8 @@
1
+ export * from './types';
2
+ export { QueueFactory } from './factory';
3
+ export { PostgresQueueAdapter } from './adapters/postgres';
4
+ export { RedisQueueAdapter } from './adapters/redis';
5
+ export { MongoQueueAdapter } from './adapters/mongodb';
6
+ export { Worker, WorkerOptions } from './worker';
7
+ export { serialize, deserialize } from './utils/msgpack';
8
+ export { ICache, MemoryCache, RedisCache, PostgresCache, MongoCache, QueueCacheFactory } from './utils/cache';
package/dist/index.js ADDED
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.QueueCacheFactory = exports.MongoCache = exports.PostgresCache = exports.RedisCache = exports.MemoryCache = exports.deserialize = exports.serialize = exports.Worker = exports.MongoQueueAdapter = exports.RedisQueueAdapter = exports.PostgresQueueAdapter = exports.QueueFactory = void 0;
18
+ __exportStar(require("./types"), exports);
19
+ var factory_1 = require("./factory");
20
+ Object.defineProperty(exports, "QueueFactory", { enumerable: true, get: function () { return factory_1.QueueFactory; } });
21
+ var postgres_1 = require("./adapters/postgres");
22
+ Object.defineProperty(exports, "PostgresQueueAdapter", { enumerable: true, get: function () { return postgres_1.PostgresQueueAdapter; } });
23
+ var redis_1 = require("./adapters/redis");
24
+ Object.defineProperty(exports, "RedisQueueAdapter", { enumerable: true, get: function () { return redis_1.RedisQueueAdapter; } });
25
+ var mongodb_1 = require("./adapters/mongodb");
26
+ Object.defineProperty(exports, "MongoQueueAdapter", { enumerable: true, get: function () { return mongodb_1.MongoQueueAdapter; } });
27
+ var worker_1 = require("./worker");
28
+ Object.defineProperty(exports, "Worker", { enumerable: true, get: function () { return worker_1.Worker; } });
29
+ var msgpack_1 = require("./utils/msgpack");
30
+ Object.defineProperty(exports, "serialize", { enumerable: true, get: function () { return msgpack_1.serialize; } });
31
+ Object.defineProperty(exports, "deserialize", { enumerable: true, get: function () { return msgpack_1.deserialize; } });
32
+ var cache_1 = require("./utils/cache");
33
+ Object.defineProperty(exports, "MemoryCache", { enumerable: true, get: function () { return cache_1.MemoryCache; } });
34
+ Object.defineProperty(exports, "RedisCache", { enumerable: true, get: function () { return cache_1.RedisCache; } });
35
+ Object.defineProperty(exports, "PostgresCache", { enumerable: true, get: function () { return cache_1.PostgresCache; } });
36
+ Object.defineProperty(exports, "MongoCache", { enumerable: true, get: function () { return cache_1.MongoCache; } });
37
+ Object.defineProperty(exports, "QueueCacheFactory", { enumerable: true, get: function () { return cache_1.QueueCacheFactory; } });
@@ -0,0 +1,37 @@
1
+ export interface Job<T = any> {
2
+ id: string;
3
+ queue: string;
4
+ payload: T;
5
+ status: 'pending' | 'processing' | 'completed' | 'failed';
6
+ priority: number;
7
+ attempts: number;
8
+ maxAttempts: number;
9
+ runAt: Date;
10
+ lockedAt?: Date;
11
+ completedAt?: Date;
12
+ failedAt?: Date;
13
+ error?: string;
14
+ workerId?: string;
15
+ expiresAt?: Date;
16
+ }
17
+ export interface EnqueueOptions {
18
+ id?: string;
19
+ priority?: number;
20
+ maxAttempts?: number;
21
+ runAt?: Date;
22
+ delayMs?: number;
23
+ }
24
+ export interface QueueAdapterOptions {
25
+ completedJobTtlMs?: number;
26
+ failedJobTtlMs?: number;
27
+ lockTimeoutMs?: number;
28
+ pruneIntervalMs?: number;
29
+ }
30
+ export interface IQueueAdapter {
31
+ init?(): Promise<void>;
32
+ enqueue<T>(queueName: string, payload: T, options?: EnqueueOptions): Promise<Job<T>>;
33
+ claimJob(queueName: string, workerId: string): Promise<Job | null>;
34
+ completeJob(jobId: string): Promise<void>;
35
+ failJob(jobId: string, error: string): Promise<void>;
36
+ close(): Promise<void>;
37
+ }
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,40 @@
1
+ import Redis from 'ioredis';
2
+ import { Pool } from 'pg';
3
+ import { MongoClient, Collection } from 'mongodb';
4
+ export interface ICache {
5
+ get<T>(key: string): Promise<T | null>;
6
+ set<T>(key: string, value: T, ttlMs?: number): Promise<void>;
7
+ del(key: string): Promise<void>;
8
+ }
9
+ export declare class MemoryCache implements ICache {
10
+ private store;
11
+ get<T>(key: string): Promise<T | null>;
12
+ set<T>(key: string, value: T, ttlMs?: number): Promise<void>;
13
+ del(key: string): Promise<void>;
14
+ }
15
+ export declare class RedisCache implements ICache {
16
+ private redis;
17
+ constructor(redisOrUrl: Redis | string);
18
+ get<T>(key: string): Promise<T | null>;
19
+ set<T>(key: string, value: T, ttlMs?: number): Promise<void>;
20
+ del(key: string): Promise<void>;
21
+ }
22
+ export declare class PostgresCache implements ICache {
23
+ private pool;
24
+ constructor(poolOrConnectionString: Pool | string);
25
+ init(): Promise<void>;
26
+ get<T>(key: string): Promise<T | null>;
27
+ set<T>(key: string, value: T, ttlMs?: number): Promise<void>;
28
+ del(key: string): Promise<void>;
29
+ }
30
+ export declare class MongoCache implements ICache {
31
+ private collection;
32
+ constructor(clientOrCollection: MongoClient | Collection<any>, dbName?: string);
33
+ init(): Promise<void>;
34
+ get<T>(key: string): Promise<T | null>;
35
+ set<T>(key: string, value: T, ttlMs?: number): Promise<void>;
36
+ del(key: string): Promise<void>;
37
+ }
38
+ export declare class QueueCacheFactory {
39
+ static create(connectionString: string): Promise<ICache>;
40
+ }
@@ -0,0 +1,172 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.QueueCacheFactory = exports.MongoCache = exports.PostgresCache = exports.RedisCache = exports.MemoryCache = void 0;
7
+ const ioredis_1 = __importDefault(require("ioredis"));
8
+ const pg_1 = require("pg");
9
+ const mongodb_1 = require("mongodb");
10
+ class MemoryCache {
11
+ store = new Map();
12
+ async get(key) {
13
+ const item = this.store.get(key);
14
+ if (!item)
15
+ return null;
16
+ if (Date.now() > item.expiresAt) {
17
+ this.store.delete(key);
18
+ return null;
19
+ }
20
+ return item.value;
21
+ }
22
+ async set(key, value, ttlMs = 60000) {
23
+ this.store.set(key, { value, expiresAt: Date.now() + ttlMs });
24
+ }
25
+ async del(key) {
26
+ this.store.delete(key);
27
+ }
28
+ }
29
+ exports.MemoryCache = MemoryCache;
30
+ class RedisCache {
31
+ redis;
32
+ constructor(redisOrUrl) {
33
+ if (typeof redisOrUrl === 'string') {
34
+ this.redis = new ioredis_1.default(redisOrUrl);
35
+ }
36
+ else {
37
+ this.redis = redisOrUrl;
38
+ }
39
+ }
40
+ async get(key) {
41
+ const data = await this.redis.get(key);
42
+ if (!data)
43
+ return null;
44
+ try {
45
+ return JSON.parse(data);
46
+ }
47
+ catch {
48
+ return data;
49
+ }
50
+ }
51
+ async set(key, value, ttlMs = 60000) {
52
+ const data = typeof value === 'string' ? value : JSON.stringify(value);
53
+ await this.redis.set(key, data, 'PX', ttlMs);
54
+ }
55
+ async del(key) {
56
+ await this.redis.del(key);
57
+ }
58
+ }
59
+ exports.RedisCache = RedisCache;
60
+ class PostgresCache {
61
+ pool;
62
+ constructor(poolOrConnectionString) {
63
+ if (typeof poolOrConnectionString === 'string') {
64
+ this.pool = new pg_1.Pool({ connectionString: poolOrConnectionString });
65
+ }
66
+ else {
67
+ this.pool = poolOrConnectionString;
68
+ }
69
+ }
70
+ async init() {
71
+ const query = `
72
+ CREATE TABLE IF NOT EXISTS queue_cache (
73
+ key VARCHAR(255) PRIMARY KEY,
74
+ value TEXT NOT NULL,
75
+ expires_at TIMESTAMP WITH TIME ZONE NOT NULL
76
+ );
77
+ CREATE INDEX IF NOT EXISTS idx_cache_expires ON queue_cache (expires_at);
78
+ `;
79
+ await this.pool.query(query);
80
+ }
81
+ async get(key) {
82
+ const query = `
83
+ SELECT value, expires_at FROM queue_cache
84
+ WHERE key = $1 AND expires_at > NOW();
85
+ `;
86
+ const res = await this.pool.query(query, [key]);
87
+ if (res.rows.length === 0) {
88
+ return null;
89
+ }
90
+ try {
91
+ return JSON.parse(res.rows[0].value);
92
+ }
93
+ catch {
94
+ return res.rows[0].value;
95
+ }
96
+ }
97
+ async set(key, value, ttlMs = 60000) {
98
+ const expiresAt = new Date(Date.now() + ttlMs);
99
+ const serializedValue = typeof value === 'string' ? value : JSON.stringify(value);
100
+ const query = `
101
+ INSERT INTO queue_cache (key, value, expires_at)
102
+ VALUES ($1, $2, $3)
103
+ ON CONFLICT (key) DO UPDATE
104
+ SET value = EXCLUDED.value, expires_at = EXCLUDED.expires_at;
105
+ `;
106
+ await this.pool.query(query, [key, serializedValue, expiresAt]);
107
+ }
108
+ async del(key) {
109
+ const query = `DELETE FROM queue_cache WHERE key = $1;`;
110
+ await this.pool.query(query, [key]);
111
+ }
112
+ }
113
+ exports.PostgresCache = PostgresCache;
114
+ class MongoCache {
115
+ collection;
116
+ constructor(clientOrCollection, dbName = 'queue_tool') {
117
+ if (clientOrCollection instanceof mongodb_1.MongoClient) {
118
+ this.collection = clientOrCollection.db(dbName).collection('queue_cache');
119
+ }
120
+ else {
121
+ this.collection = clientOrCollection;
122
+ }
123
+ }
124
+ async init() {
125
+ await this.collection.createIndex({ expiresAt: 1 }, { name: 'idx_cache_ttl', expireAfterSeconds: 0 });
126
+ }
127
+ async get(key) {
128
+ const doc = await this.collection.findOne({
129
+ _id: key,
130
+ expiresAt: { $gt: new Date() }
131
+ });
132
+ if (!doc)
133
+ return null;
134
+ return doc.value;
135
+ }
136
+ async set(key, value, ttlMs = 60000) {
137
+ const expiresAt = new Date(Date.now() + ttlMs);
138
+ await this.collection.updateOne({ _id: key }, {
139
+ $set: {
140
+ value: value,
141
+ expiresAt: expiresAt
142
+ }
143
+ }, { upsert: true });
144
+ }
145
+ async del(key) {
146
+ await this.collection.deleteOne({ _id: key });
147
+ }
148
+ }
149
+ exports.MongoCache = MongoCache;
150
+ class QueueCacheFactory {
151
+ static async create(connectionString) {
152
+ if (connectionString.startsWith('postgres://') || connectionString.startsWith('postgresql://')) {
153
+ const cache = new PostgresCache(connectionString);
154
+ await cache.init();
155
+ return cache;
156
+ }
157
+ else if (connectionString.startsWith('redis://') || connectionString.startsWith('rediss://')) {
158
+ return new RedisCache(connectionString);
159
+ }
160
+ else if (connectionString.startsWith('mongodb://') || connectionString.startsWith('mongodb+srv://')) {
161
+ const client = new mongodb_1.MongoClient(connectionString);
162
+ await client.connect();
163
+ const cache = new MongoCache(client);
164
+ await cache.init();
165
+ return cache;
166
+ }
167
+ else {
168
+ return new MemoryCache();
169
+ }
170
+ }
171
+ }
172
+ exports.QueueCacheFactory = QueueCacheFactory;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const cache_1 = require("./cache");
4
+ describe('MemoryCache', () => {
5
+ let cache;
6
+ beforeEach(() => {
7
+ cache = new cache_1.MemoryCache();
8
+ });
9
+ it('should set and get values correctly', async () => {
10
+ await cache.set('mykey', 'myvalue');
11
+ const val = await cache.get('mykey');
12
+ expect(val).toBe('myvalue');
13
+ });
14
+ it('should return null for non-existent keys', async () => {
15
+ const val = await cache.get('non-existent');
16
+ expect(val).toBeNull();
17
+ });
18
+ it('should delete keys successfully', async () => {
19
+ await cache.set('mykey', 'myvalue');
20
+ await cache.del('mykey');
21
+ const val = await cache.get('mykey');
22
+ expect(val).toBeNull();
23
+ });
24
+ it('should respect TTL expiration', async () => {
25
+ jest.useFakeTimers();
26
+ await cache.set('tempkey', 'tempvalue', 100); // 100ms TTL
27
+ // Immediately gets value
28
+ expect(await cache.get('tempkey')).toBe('tempvalue');
29
+ // Advance time by 101ms
30
+ jest.advanceTimersByTime(101);
31
+ // Should be expired now
32
+ expect(await cache.get('tempkey')).toBeNull();
33
+ jest.useRealTimers();
34
+ });
35
+ });
@@ -0,0 +1,15 @@
1
+ export interface LogContext {
2
+ queue?: string;
3
+ jobId?: string;
4
+ workerId?: string;
5
+ error?: string;
6
+ [key: string]: any;
7
+ }
8
+ declare class JsonLogger {
9
+ private formatLog;
10
+ info(message: string, context?: LogContext): void;
11
+ error(message: string, context?: LogContext): void;
12
+ warn(message: string, context?: LogContext): void;
13
+ }
14
+ export declare const logger: JsonLogger;
15
+ export {};
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.logger = void 0;
4
+ class JsonLogger {
5
+ formatLog(level, message, context) {
6
+ return JSON.stringify({
7
+ timestamp: new Date().toISOString(),
8
+ level,
9
+ message,
10
+ ...context
11
+ });
12
+ }
13
+ info(message, context) {
14
+ console.log(this.formatLog('INFO', message, context));
15
+ }
16
+ error(message, context) {
17
+ console.error(this.formatLog('ERROR', message, context));
18
+ }
19
+ warn(message, context) {
20
+ console.warn(this.formatLog('WARN', message, context));
21
+ }
22
+ }
23
+ exports.logger = new JsonLogger();
@@ -0,0 +1,2 @@
1
+ export declare function serialize(data: any): Buffer;
2
+ export declare function deserialize<T = any>(buffer: Buffer | Uint8Array): T;
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.serialize = serialize;
4
+ exports.deserialize = deserialize;
5
+ const msgpack_1 = require("@msgpack/msgpack");
6
+ function serialize(data) {
7
+ const encoded = (0, msgpack_1.encode)(data);
8
+ return Buffer.from(encoded.buffer, encoded.byteOffset, encoded.byteLength);
9
+ }
10
+ function deserialize(buffer) {
11
+ const uint8 = buffer instanceof Buffer ? new Uint8Array(buffer) : buffer;
12
+ return (0, msgpack_1.decode)(uint8);
13
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const msgpack_1 = require("./msgpack");
4
+ describe('MessagePack Utility', () => {
5
+ it('should serialize and deserialize a simple object', () => {
6
+ const data = { foo: 'bar', age: 42 };
7
+ const serialized = (0, msgpack_1.serialize)(data);
8
+ expect(serialized).toBeInstanceOf(Buffer);
9
+ const deserialized = (0, msgpack_1.deserialize)(serialized);
10
+ expect(deserialized).toEqual(data);
11
+ });
12
+ it('should handle complex nested objects and arrays', () => {
13
+ const data = {
14
+ id: 'img-10293',
15
+ operations: ['resize', 'compress'],
16
+ metadata: {
17
+ width: 1920,
18
+ height: 1080,
19
+ tags: ['png', 'premium']
20
+ },
21
+ active: true
22
+ };
23
+ const serialized = (0, msgpack_1.serialize)(data);
24
+ const deserialized = (0, msgpack_1.deserialize)(serialized);
25
+ expect(deserialized).toEqual(data);
26
+ });
27
+ it('should handle primitives and null values', () => {
28
+ expect((0, msgpack_1.deserialize)((0, msgpack_1.serialize)(null))).toBeNull();
29
+ expect((0, msgpack_1.deserialize)((0, msgpack_1.serialize)(123.45))).toBe(123.45);
30
+ expect((0, msgpack_1.deserialize)((0, msgpack_1.serialize)('hello world'))).toBe('hello world');
31
+ expect((0, msgpack_1.deserialize)((0, msgpack_1.serialize)(false))).toBe(false);
32
+ });
33
+ });
@@ -0,0 +1,23 @@
1
+ import { IQueueAdapter, Job } from './types';
2
+ export interface WorkerOptions {
3
+ concurrency?: number;
4
+ pollIntervalMs?: number;
5
+ taskNameKey?: string;
6
+ }
7
+ export declare class Worker {
8
+ private queueName;
9
+ private connectionOrAdapter;
10
+ private processor;
11
+ private adapter;
12
+ private running;
13
+ private workerId;
14
+ private concurrency;
15
+ private pollIntervalMs;
16
+ private taskNameKey;
17
+ private ownAdapter;
18
+ private loops;
19
+ constructor(queueName: string, connectionOrAdapter: string | IQueueAdapter, processor: ((job: Job) => Promise<void>) | Record<string, (job: Job) => Promise<void>>, options?: WorkerOptions);
20
+ start(): Promise<void>;
21
+ stop(): Promise<void>;
22
+ private runLoop;
23
+ }