@goatlab/tasks-adapter-bullmq 0.1.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,349 @@
1
+ "use strict";
2
+ /**
3
+ * BullMQ Benchmark Script
4
+ *
5
+ * Run with: npx tsx src/benchmark.ts [mode]
6
+ *
7
+ * Modes:
8
+ * (default) - Run full benchmark without persistence
9
+ * persist - Compare no-persist vs AOF persistence
10
+ *
11
+ * Uses testcontainers to spin up Redis automatically.
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ const tasks_core_1 = require("@goatlab/tasks-core");
15
+ const redis_1 = require("@testcontainers/redis");
16
+ const testcontainers_1 = require("testcontainers");
17
+ const BullMQConnector_js_1 = require("./BullMQConnector.js");
18
+ // Configuration - keep benchmarks short
19
+ const QUEUE_BATCH_SIZE = 500;
20
+ const WARMUP_COUNT = 50;
21
+ const BENCHMARK_DURATION_MS = 5000; // 5 seconds
22
+ const E2E_TASK_COUNT = 1000;
23
+ const LATENCY_SAMPLES = 50;
24
+ class BenchmarkTask extends tasks_core_1.ShouldQueue {
25
+ postUrl = "http://localhost/benchmark";
26
+ taskName;
27
+ constructor(connector, name) {
28
+ super({ connector });
29
+ this.taskName = name;
30
+ }
31
+ async handle() {
32
+ return undefined;
33
+ }
34
+ }
35
+ async function runQueueBenchmark(connector, task) {
36
+ console.log("\nšŸ“Š Queue Throughput (queue-only, no worker)");
37
+ console.log("=".repeat(50));
38
+ // Warmup
39
+ for (let i = 0; i < WARMUP_COUNT; i++) {
40
+ await task.queue({ index: i });
41
+ }
42
+ console.log(`Running for ${BENCHMARK_DURATION_MS / 1000}s...`);
43
+ let count = 0;
44
+ const startTime = Date.now();
45
+ const endTime = startTime + BENCHMARK_DURATION_MS;
46
+ while (Date.now() < endTime) {
47
+ const promises = [];
48
+ for (let i = 0; i < QUEUE_BATCH_SIZE; i++) {
49
+ promises.push(task.queue({ index: count++ }));
50
+ }
51
+ await Promise.all(promises);
52
+ }
53
+ const elapsed = Date.now() - startTime;
54
+ const throughput = (count / elapsed) * 1000;
55
+ console.log(`āœ… Queued: ${count.toLocaleString()} tasks`);
56
+ console.log(`āœ… Throughput: ${throughput.toFixed(0)} tasks/sec`);
57
+ return throughput;
58
+ }
59
+ async function runE2EBenchmark(connector, task) {
60
+ console.log("\nšŸ“Š End-to-End (queue + worker)");
61
+ console.log("=".repeat(50));
62
+ await connector.startWorker({
63
+ tasks: [task],
64
+ workerName: "benchmark-worker",
65
+ concurrency: 50,
66
+ });
67
+ await new Promise((r) => setTimeout(r, 500));
68
+ console.log(`Queuing ${E2E_TASK_COUNT} tasks...`);
69
+ const start = Date.now();
70
+ // Queue all tasks in parallel batches
71
+ for (let i = 0; i < E2E_TASK_COUNT; i += QUEUE_BATCH_SIZE) {
72
+ const batch = [];
73
+ for (let j = 0; j < QUEUE_BATCH_SIZE && i + j < E2E_TASK_COUNT; j++) {
74
+ batch.push(task.queue({ index: i + j }));
75
+ }
76
+ await Promise.all(batch);
77
+ }
78
+ const queueTime = Date.now() - start;
79
+ // Wait for completion (max 15s)
80
+ const timeout = 15000;
81
+ let completed = 0;
82
+ const waitStart = Date.now();
83
+ while (completed < E2E_TASK_COUNT && Date.now() - waitStart < timeout) {
84
+ const counts = await connector.getJobCounts(task.taskName);
85
+ completed = counts.completed || 0;
86
+ if (completed < E2E_TASK_COUNT) {
87
+ await new Promise((r) => setTimeout(r, 100));
88
+ }
89
+ }
90
+ const totalTime = Date.now() - start;
91
+ const throughput = (completed / totalTime) * 1000;
92
+ console.log(`āœ… Processed: ${completed.toLocaleString()} tasks`);
93
+ console.log(`āœ… Queue time: ${queueTime}ms`);
94
+ console.log(`āœ… Total time: ${totalTime}ms`);
95
+ console.log(`āœ… Throughput: ${throughput.toFixed(0)} tasks/sec`);
96
+ return throughput;
97
+ }
98
+ async function runLatencyBenchmark(connector, task) {
99
+ console.log("\nšŸ“Š Latency (round-trip)");
100
+ console.log("=".repeat(50));
101
+ await connector.startWorker({
102
+ tasks: [task],
103
+ workerName: "latency-worker",
104
+ concurrency: 10,
105
+ });
106
+ await new Promise((r) => setTimeout(r, 500));
107
+ const latencies = [];
108
+ for (let i = 0; i < LATENCY_SAMPLES; i++) {
109
+ const start = Date.now();
110
+ const status = await task.queue({ index: i });
111
+ // Poll for completion (max 2s per task)
112
+ const timeout = Date.now() + 2000;
113
+ while (Date.now() < timeout) {
114
+ const currentStatus = await task.getStatus(status.id);
115
+ if (currentStatus.status === "COMPLETED" ||
116
+ currentStatus.status === "FAILED") {
117
+ latencies.push(Date.now() - start);
118
+ break;
119
+ }
120
+ await new Promise((r) => setTimeout(r, 5));
121
+ }
122
+ }
123
+ latencies.sort((a, b) => a - b);
124
+ const avg = latencies.reduce((a, b) => a + b, 0) / latencies.length;
125
+ const p50 = latencies[Math.floor(latencies.length * 0.5)];
126
+ const p95 = latencies[Math.floor(latencies.length * 0.95)];
127
+ const p99 = latencies[Math.floor(latencies.length * 0.99)];
128
+ console.log(`āœ… Samples: ${latencies.length}`);
129
+ console.log(`āœ… Avg: ${avg.toFixed(1)}ms | P50: ${p50}ms | P95: ${p95}ms | P99: ${p99}ms`);
130
+ return { avg, p50, p95, p99 };
131
+ }
132
+ async function main() {
133
+ console.log("šŸš€ BullMQ Benchmark");
134
+ console.log("Starting Redis container...");
135
+ let redisContainer = null;
136
+ try {
137
+ redisContainer = await new redis_1.RedisContainer("redis:7-alpine").start();
138
+ const host = redisContainer.getHost();
139
+ const port = redisContainer.getMappedPort(6379);
140
+ console.log(`Redis: ${host}:${port}`);
141
+ // Queue throughput test (separate queue)
142
+ const connector1 = new BullMQConnector_js_1.BullMQConnector({ connection: { host, port } });
143
+ const task1 = new BenchmarkTask(connector1, "bench_queue");
144
+ const queueThroughput = await runQueueBenchmark(connector1, task1);
145
+ await connector1.close();
146
+ // E2E test (separate queue)
147
+ const connector2 = new BullMQConnector_js_1.BullMQConnector({ connection: { host, port } });
148
+ const task2 = new BenchmarkTask(connector2, "bench_e2e");
149
+ const e2eThroughput = await runE2EBenchmark(connector2, task2);
150
+ await connector2.close();
151
+ // Latency test (separate queue)
152
+ const connector3 = new BullMQConnector_js_1.BullMQConnector({ connection: { host, port } });
153
+ const task3 = new BenchmarkTask(connector3, "bench_latency");
154
+ const latency = await runLatencyBenchmark(connector3, task3);
155
+ await connector3.close();
156
+ // Summary
157
+ console.log("\n" + "=".repeat(50));
158
+ console.log("šŸ“ˆ BULLMQ SUMMARY");
159
+ console.log("=".repeat(50));
160
+ console.log(`Queue throughput: ${queueThroughput.toFixed(0)} tasks/sec`);
161
+ console.log(`E2E throughput: ${e2eThroughput.toFixed(0)} tasks/sec`);
162
+ console.log(`Latency (avg): ${latency.avg.toFixed(1)}ms`);
163
+ console.log(`Latency (p95): ${latency.p95}ms`);
164
+ }
165
+ finally {
166
+ if (redisContainer) {
167
+ console.log("\nStopping Redis container...");
168
+ await redisContainer.stop();
169
+ }
170
+ }
171
+ }
172
+ async function runPersistenceComparison() {
173
+ console.log("šŸš€ BullMQ Persistence Comparison");
174
+ console.log("=".repeat(50));
175
+ const results = [];
176
+ // Test 1: No persistence (default)
177
+ console.log("\nšŸ“Š Mode: NO PERSISTENCE (default)");
178
+ const container1 = await new redis_1.RedisContainer("redis:7-alpine").start();
179
+ const connector1 = new BullMQConnector_js_1.BullMQConnector({
180
+ connection: {
181
+ host: container1.getHost(),
182
+ port: container1.getMappedPort(6379),
183
+ },
184
+ });
185
+ const task1 = new BenchmarkTask(connector1, "bench_nopersist");
186
+ for (let i = 0; i < WARMUP_COUNT; i++)
187
+ await task1.queue({ index: i });
188
+ let count = 0;
189
+ const start1 = Date.now();
190
+ const end1 = start1 + BENCHMARK_DURATION_MS;
191
+ while (Date.now() < end1) {
192
+ const batch = [];
193
+ for (let i = 0; i < QUEUE_BATCH_SIZE; i++)
194
+ batch.push(task1.queue({ index: count++ }));
195
+ await Promise.all(batch);
196
+ }
197
+ const throughput1 = Math.round((count / (Date.now() - start1)) * 1000);
198
+ console.log(`āœ… Throughput: ${throughput1.toLocaleString()} tasks/sec`);
199
+ results.push({ mode: "No persistence", throughput: throughput1 });
200
+ await connector1.close();
201
+ await container1.stop();
202
+ // Test 2: AOF with appendfsync everysec (balanced)
203
+ console.log("\nšŸ“Š Mode: AOF (appendfsync everysec)");
204
+ const container2 = await new testcontainers_1.GenericContainer("redis:7-alpine")
205
+ .withCommand([
206
+ "redis-server",
207
+ "--appendonly",
208
+ "yes",
209
+ "--appendfsync",
210
+ "everysec",
211
+ ])
212
+ .withExposedPorts(6379)
213
+ .start();
214
+ const connector2 = new BullMQConnector_js_1.BullMQConnector({
215
+ connection: {
216
+ host: container2.getHost(),
217
+ port: container2.getMappedPort(6379),
218
+ },
219
+ });
220
+ const task2 = new BenchmarkTask(connector2, "bench_aof_sec");
221
+ for (let i = 0; i < WARMUP_COUNT; i++)
222
+ await task2.queue({ index: i });
223
+ count = 0;
224
+ const start2 = Date.now();
225
+ const end2 = start2 + BENCHMARK_DURATION_MS;
226
+ while (Date.now() < end2) {
227
+ const batch = [];
228
+ for (let i = 0; i < QUEUE_BATCH_SIZE; i++)
229
+ batch.push(task2.queue({ index: count++ }));
230
+ await Promise.all(batch);
231
+ }
232
+ const throughput2 = Math.round((count / (Date.now() - start2)) * 1000);
233
+ console.log(`āœ… Throughput: ${throughput2.toLocaleString()} tasks/sec`);
234
+ results.push({ mode: "AOF everysec", throughput: throughput2 });
235
+ await connector2.close();
236
+ await container2.stop();
237
+ // Test 3: AOF with appendfsync always (safest, slowest)
238
+ console.log("\nšŸ“Š Mode: AOF (appendfsync always) - SAFEST");
239
+ const container3 = await new testcontainers_1.GenericContainer("redis:7-alpine")
240
+ .withCommand([
241
+ "redis-server",
242
+ "--appendonly",
243
+ "yes",
244
+ "--appendfsync",
245
+ "always",
246
+ ])
247
+ .withExposedPorts(6379)
248
+ .start();
249
+ const connector3 = new BullMQConnector_js_1.BullMQConnector({
250
+ connection: {
251
+ host: container3.getHost(),
252
+ port: container3.getMappedPort(6379),
253
+ },
254
+ });
255
+ const task3 = new BenchmarkTask(connector3, "bench_aof_always");
256
+ for (let i = 0; i < WARMUP_COUNT; i++)
257
+ await task3.queue({ index: i });
258
+ count = 0;
259
+ const start3 = Date.now();
260
+ const end3 = start3 + BENCHMARK_DURATION_MS;
261
+ while (Date.now() < end3) {
262
+ const batch = [];
263
+ for (let i = 0; i < QUEUE_BATCH_SIZE; i++)
264
+ batch.push(task3.queue({ index: count++ }));
265
+ await Promise.all(batch);
266
+ }
267
+ const throughput3 = Math.round((count / (Date.now() - start3)) * 1000);
268
+ console.log(`āœ… Throughput: ${throughput3.toLocaleString()} tasks/sec`);
269
+ results.push({ mode: "AOF always", throughput: throughput3 });
270
+ await connector3.close();
271
+ await container3.stop();
272
+ // Summary
273
+ console.log("\n" + "=".repeat(50));
274
+ console.log("šŸ“ˆ PERSISTENCE COMPARISON");
275
+ console.log("=".repeat(50));
276
+ for (const r of results) {
277
+ const pct = Math.round((r.throughput / results[0].throughput) * 100);
278
+ console.log(`${r.mode.padEnd(20)} ${r.throughput.toLocaleString().padStart(10)} tasks/sec (${pct}%)`);
279
+ }
280
+ }
281
+ async function runPayloadComparison() {
282
+ console.log("šŸš€ BullMQ Payload Size Comparison");
283
+ console.log("=".repeat(50));
284
+ const container = await new redis_1.RedisContainer("redis:7-alpine").start();
285
+ const host = container.getHost();
286
+ const port = container.getMappedPort(6379);
287
+ console.log(`Redis: ${host}:${port}`);
288
+ const results = [];
289
+ // Different payload sizes
290
+ const payloads = [
291
+ { name: "Tiny (100B)", data: { id: 1, msg: "x".repeat(80) } },
292
+ {
293
+ name: "Small (1KB)",
294
+ data: { id: 1, msg: "x".repeat(900), extra: "y".repeat(100) },
295
+ },
296
+ { name: "Medium (10KB)", data: { id: 1, data: "x".repeat(10000) } },
297
+ { name: "Large (100KB)", data: { id: 1, data: "x".repeat(100000) } },
298
+ { name: "XL (500KB)", data: { id: 1, data: "x".repeat(500000) } },
299
+ ];
300
+ for (const payload of payloads) {
301
+ const bytes = JSON.stringify(payload.data).length;
302
+ console.log(`\nšŸ“Š Payload: ${payload.name} (~${bytes} bytes)`);
303
+ const connector = new BullMQConnector_js_1.BullMQConnector({ connection: { host, port } });
304
+ const queueName = `bench_${payload.name.replace(/[^a-z]/gi, "")}`;
305
+ // Queue directly using addJob to pass custom payload
306
+ const queue = connector.getQueue(queueName);
307
+ // Warmup
308
+ for (let i = 0; i < 20; i++) {
309
+ await queue.add("job", payload.data);
310
+ }
311
+ // Benchmark
312
+ let count = 0;
313
+ const start = Date.now();
314
+ const end = start + BENCHMARK_DURATION_MS;
315
+ while (Date.now() < end) {
316
+ const batch = [];
317
+ for (let i = 0; i < QUEUE_BATCH_SIZE; i++) {
318
+ batch.push(queue.add("job", payload.data));
319
+ count++;
320
+ }
321
+ await Promise.all(batch);
322
+ }
323
+ const throughput = Math.round((count / (Date.now() - start)) * 1000);
324
+ console.log(`āœ… Throughput: ${throughput.toLocaleString()} tasks/sec`);
325
+ results.push({ size: payload.name, bytes, throughput });
326
+ await connector.close();
327
+ }
328
+ await container.stop();
329
+ // Summary
330
+ console.log("\n" + "=".repeat(50));
331
+ console.log("šŸ“ˆ PAYLOAD SIZE COMPARISON");
332
+ console.log("=".repeat(50));
333
+ const maxThroughput = results[0].throughput;
334
+ for (const r of results) {
335
+ const pct = Math.round((r.throughput / maxThroughput) * 100);
336
+ const mbps = ((r.bytes * r.throughput) / 1024 / 1024).toFixed(1);
337
+ console.log(`${r.size.padEnd(18)} ${r.throughput.toLocaleString().padStart(10)} tasks/sec (${pct.toString().padStart(3)}%) ${mbps.padStart(6)} MB/s`);
338
+ }
339
+ }
340
+ if (process.argv[2] === "persist") {
341
+ runPersistenceComparison().catch(console.error);
342
+ }
343
+ else if (process.argv[2] === "payload") {
344
+ runPayloadComparison().catch(console.error);
345
+ }
346
+ else {
347
+ main().catch(console.error);
348
+ }
349
+ //# sourceMappingURL=benchmark.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"benchmark.js","sourceRoot":"","sources":["../src/benchmark.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ // npx vitest run ./src/bullmq.spec.ts
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const test_suite_1 = require("@goatlab/tasks-core/test-suite");
5
+ const vitest_1 = require("vitest");
6
+ const BullMQConnector_js_1 = require("./BullMQConnector.js");
7
+ const const_js_1 = require("./test/const.js");
8
+ // Create connector instance
9
+ const globalData = (0, const_js_1.getGlobalData)();
10
+ const bullmqConnector = new BullMQConnector_js_1.BullMQConnector({
11
+ connection: {
12
+ host: globalData.host || "localhost",
13
+ port: globalData.port || 6379,
14
+ },
15
+ });
16
+ // Run the standardized test suite
17
+ (0, test_suite_1.taskConnectorTestSuite)({ describe: vitest_1.describe, it: vitest_1.it, expect: vitest_1.expect, beforeAll: vitest_1.beforeAll, afterAll: vitest_1.afterAll, beforeEach: vitest_1.beforeEach, afterEach: vitest_1.afterEach }, () => bullmqConnector, {
18
+ taskCompletionTimeout: 10000,
19
+ statusCheckInterval: 500,
20
+ runLifecycleTests: true,
21
+ startWorker: async (tasks) => {
22
+ // Start a worker for all the provided tasks
23
+ await bullmqConnector.startWorker({
24
+ workerName: "test-suite-worker",
25
+ tasks,
26
+ concurrency: 10,
27
+ });
28
+ return async () => {
29
+ await bullmqConnector.close();
30
+ };
31
+ },
32
+ cleanup: async () => {
33
+ await bullmqConnector.close();
34
+ },
35
+ });
36
+ // Additional BullMQ-specific tests
37
+ (0, vitest_1.describe)("BullMQConnector Specific Tests", () => {
38
+ let connector;
39
+ (0, vitest_1.beforeAll)(async () => {
40
+ connector = new BullMQConnector_js_1.BullMQConnector({
41
+ connection: {
42
+ host: globalData.host || "localhost",
43
+ port: globalData.port || 6379,
44
+ },
45
+ });
46
+ });
47
+ (0, vitest_1.afterAll)(async () => {
48
+ await connector.close();
49
+ });
50
+ (0, vitest_1.it)("should get job counts for a queue", async () => {
51
+ const counts = await connector.getJobCounts("test_specific_queue");
52
+ (0, vitest_1.expect)(counts).toHaveProperty("waiting");
53
+ (0, vitest_1.expect)(counts).toHaveProperty("active");
54
+ (0, vitest_1.expect)(counts).toHaveProperty("completed");
55
+ (0, vitest_1.expect)(counts).toHaveProperty("failed");
56
+ (0, vitest_1.expect)(counts).toHaveProperty("delayed");
57
+ });
58
+ (0, vitest_1.it)("should add a job directly to a queue", async () => {
59
+ const job = await connector.addJob("direct_queue", "direct_job", {
60
+ data: "test",
61
+ });
62
+ (0, vitest_1.expect)(job).toHaveProperty("id");
63
+ (0, vitest_1.expect)(job).toHaveProperty("name", "direct_job");
64
+ (0, vitest_1.expect)(job.data).toEqual({ data: "test" });
65
+ });
66
+ (0, vitest_1.it)("should get a job by id", async () => {
67
+ const job = await connector.addJob("get_job_queue", "get_job_test", {
68
+ value: 123,
69
+ });
70
+ const retrievedJob = await connector.getJob("get_job_queue", job.id);
71
+ (0, vitest_1.expect)(retrievedJob).toBeDefined();
72
+ (0, vitest_1.expect)(retrievedJob?.data).toEqual({ value: 123 });
73
+ });
74
+ (0, vitest_1.it)("should remove a job", async () => {
75
+ const job = await connector.addJob("remove_job_queue", "remove_job_test", {
76
+ toRemove: true,
77
+ });
78
+ await connector.removeJob("remove_job_queue", job.id);
79
+ const removedJob = await connector.getJob("remove_job_queue", job.id);
80
+ (0, vitest_1.expect)(removedJob).toBeUndefined();
81
+ });
82
+ (0, vitest_1.it)("should pause and resume a queue", async () => {
83
+ await connector.pauseQueue("pause_test_queue");
84
+ // Queue should be paused
85
+ await connector.resumeQueue("pause_test_queue");
86
+ // Queue should be resumed
87
+ });
88
+ });
89
+ //# sourceMappingURL=bullmq.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bullmq.spec.js","sourceRoot":"","sources":["../src/bullmq.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export type { BullMQConnectionOptions, BullMQConnectorConfig, } from "./BullMQConnector.js";
2
+ export { BullMQConnector } from "./BullMQConnector.js";
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BullMQConnector = void 0;
4
+ var BullMQConnector_js_1 = require("./BullMQConnector.js");
5
+ Object.defineProperty(exports, "BullMQConnector", { enumerable: true, get: function () { return BullMQConnector_js_1.BullMQConnector; } });
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAIA,2DAAuD;AAA9C,qHAAA,eAAe,OAAA"}
@@ -0,0 +1,7 @@
1
+ export type GlobalTempData = {
2
+ host?: string;
3
+ port?: number;
4
+ };
5
+ export declare const getGlobalData: () => GlobalTempData;
6
+ export declare const writeGlobalData: (data: GlobalTempData) => void;
7
+ export declare const cleanGlobalData: () => void;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.cleanGlobalData = exports.writeGlobalData = exports.getGlobalData = void 0;
4
+ const node_fs_1 = require("node:fs");
5
+ const node_path_1 = require("node:path");
6
+ const tempDataFilePath = (0, node_path_1.resolve)((0, node_path_1.join)(__dirname, "../../"), "tempData.json");
7
+ const getGlobalData = () => {
8
+ const data = JSON.parse((0, node_fs_1.readFileSync)(tempDataFilePath, "utf-8"));
9
+ return data;
10
+ };
11
+ exports.getGlobalData = getGlobalData;
12
+ const writeGlobalData = (data) => {
13
+ (0, node_fs_1.writeFileSync)(tempDataFilePath, JSON.stringify(data), "utf-8");
14
+ };
15
+ exports.writeGlobalData = writeGlobalData;
16
+ const cleanGlobalData = () => {
17
+ if ((0, node_fs_1.existsSync)(tempDataFilePath)) {
18
+ (0, node_fs_1.unlinkSync)(tempDataFilePath);
19
+ }
20
+ };
21
+ exports.cleanGlobalData = cleanGlobalData;
22
+ //# sourceMappingURL=const.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"const.js","sourceRoot":"","sources":["../../src/test/const.ts"],"names":[],"mappings":";;;AAAA,qCAA8E;AAC9E,yCAA0C;AAO1C,MAAM,gBAAgB,GAAG,IAAA,mBAAO,EAAC,IAAA,gBAAI,EAAC,SAAS,EAAE,QAAQ,CAAC,EAAE,eAAe,CAAC,CAAC;AAEtE,MAAM,aAAa,GAAG,GAAmB,EAAE;IACjD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAA,sBAAY,EAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC,CAAC;IACjE,OAAO,IAAI,CAAC;AACb,CAAC,CAAC;AAHW,QAAA,aAAa,iBAGxB;AAEK,MAAM,eAAe,GAAG,CAAC,IAAoB,EAAE,EAAE;IACvD,IAAA,uBAAa,EAAC,gBAAgB,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;AAChE,CAAC,CAAC;AAFW,QAAA,eAAe,mBAE1B;AAEK,MAAM,eAAe,GAAG,GAAG,EAAE;IACnC,IAAI,IAAA,oBAAU,EAAC,gBAAgB,CAAC,EAAE;QACjC,IAAA,oBAAU,EAAC,gBAAgB,CAAC,CAAC;KAC7B;AACF,CAAC,CAAC;AAJW,QAAA,eAAe,mBAI1B"}
@@ -0,0 +1,2 @@
1
+ import { RedisContainer } from "@testcontainers/redis";
2
+ export declare const getRedisContainer: () => RedisContainer;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getRedisContainer = void 0;
4
+ const redis_1 = require("@testcontainers/redis");
5
+ const getRedisContainer = () => {
6
+ return new redis_1.RedisContainer("redis:7-alpine");
7
+ };
8
+ exports.getRedisContainer = getRedisContainer;
9
+ //# sourceMappingURL=redis.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis.js","sourceRoot":"","sources":["../../src/test/redis.ts"],"names":[],"mappings":";;;AAAA,iDAAuD;AAEhD,MAAM,iBAAiB,GAAG,GAAG,EAAE;IACrC,OAAO,IAAI,sBAAc,CAAC,gBAAgB,CAAC,CAAC;AAC7C,CAAC,CAAC;AAFW,QAAA,iBAAiB,qBAE5B"}