queen-mq 0.3.0 โ†’ 0.4.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.
Files changed (39) hide show
  1. package/README.md +212 -144
  2. package/client-js/client-v2/Queen.js +28 -0
  3. package/client-js/client-v2/README.md +6 -2
  4. package/client-js/client-v2/builders/QueueBuilder.js +7 -1
  5. package/client-js/client-v2/builders/TransactionBuilder.js +20 -4
  6. package/client-js/client-v2/stream/StreamBuilder.js +72 -0
  7. package/client-js/client-v2/stream/StreamConsumer.js +156 -0
  8. package/client-js/client-v2/stream/Window.js +140 -0
  9. package/client-js/test-v2/MAINTENANCE_TEST.md +148 -0
  10. package/client-js/test-v2/consume.js +1 -0
  11. package/client-js/test-v2/maintenance.js +261 -0
  12. package/client-js/test-v2/retention.js +69 -0
  13. package/client-js/test-v2/run.js +7 -1
  14. package/package.json +2 -2
  15. package/client-js/client/client.js +0 -1536
  16. package/client-js/client/index.js +0 -4
  17. package/client-js/client/utils/http.js +0 -173
  18. package/client-js/client/utils/loadBalancer.js +0 -152
  19. package/client-js/client/utils/retry.js +0 -41
  20. package/client-js/services/encryptionService.js +0 -82
  21. package/client-js/services/evictionService.js +0 -160
  22. package/client-js/services/retentionService.js +0 -162
  23. package/client-js/services/startupSync.js +0 -35
  24. package/client-js/test/README.md +0 -224
  25. package/client-js/test/advanced-client-tests.js +0 -761
  26. package/client-js/test/advanced-pattern-tests.js +0 -1137
  27. package/client-js/test/bus-mode-tests.js +0 -361
  28. package/client-js/test/core-tests.js +0 -457
  29. package/client-js/test/edge-case-tests.js +0 -562
  30. package/client-js/test/enterprise-tests.js +0 -637
  31. package/client-js/test/human.js +0 -162
  32. package/client-js/test/partition-locking-tests.js +0 -545
  33. package/client-js/test/partition-transaction-tests.js +0 -482
  34. package/client-js/test/qos0-tests.js +0 -334
  35. package/client-js/test/test-new.js +0 -370
  36. package/client-js/test/utils.js +0 -169
  37. package/client-js/test/window-buffer-test.js +0 -114
  38. package/client-js/utils/logger.js +0 -44
  39. package/client-js/utils/uuid.js +0 -5
@@ -1,169 +0,0 @@
1
- /**
2
- * Shared test utilities for Queen test suite
3
- */
4
-
5
- import pg from 'pg';
6
-
7
- // Test configuration
8
- export const TEST_CONFIG = {
9
- baseUrls: ['http://localhost:6632'],
10
- dbConfig: {
11
- host: process.env.PG_HOST || 'localhost',
12
- port: process.env.PG_PORT || 5432,
13
- database: process.env.PG_DB || 'postgres',
14
- user: process.env.PG_USER || 'postgres',
15
- password: process.env.PG_PASSWORD || 'postgres'
16
- }
17
- };
18
-
19
- // Global test state
20
- export let dbPool;
21
- export let testResults = [];
22
- export let currentTest = '';
23
-
24
- // Initialize database pool
25
- export async function initDb() {
26
- dbPool = new pg.Pool(TEST_CONFIG.dbConfig);
27
- await dbPool.query('SELECT 1');
28
- return dbPool;
29
- }
30
-
31
- // Close database pool
32
- export async function closeDb() {
33
- if (dbPool) {
34
- await dbPool.end();
35
- }
36
- }
37
-
38
- // Test logging utilities
39
- export const log = (message, type = 'info') => {
40
- const timestamp = new Date().toISOString().substring(11, 23);
41
- const prefix = {
42
- info: '๐Ÿ“',
43
- success: 'โœ…',
44
- error: 'โŒ',
45
- warning: 'โš ๏ธ',
46
- test: '๐Ÿงช',
47
- enterprise: '๐Ÿข',
48
- edge: '๐Ÿ”',
49
- pattern: '๐ŸŽฏ',
50
- workflow: '๐Ÿ”„',
51
- priority: 'โšก'
52
- }[type] || '๐Ÿ“';
53
-
54
- console.log(`[${timestamp}] ${prefix} ${message}`);
55
- };
56
-
57
- export const startTest = (testName, category = 'test') => {
58
- currentTest = testName;
59
- log(`Starting: ${testName}`, category);
60
- };
61
-
62
- export const passTest = (message = '') => {
63
- const result = { test: currentTest, status: 'PASS', message };
64
- testResults.push(result);
65
- log(`PASS: ${currentTest} ${message}`, 'success');
66
- };
67
-
68
- export const failTest = (error) => {
69
- const result = { test: currentTest, status: 'FAIL', error: error.message };
70
- testResults.push(result);
71
- log(`FAIL: ${currentTest} - ${error.message}`, 'error');
72
- };
73
-
74
- export const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
75
-
76
- // Database utilities
77
- export const cleanupTestData = async () => {
78
- try {
79
- await dbPool.query(`
80
- DELETE FROM queen.messages
81
- WHERE partition_id IN (
82
- SELECT p.id FROM queen.partitions p
83
- JOIN queen.queues q ON p.queue_id = q.id
84
- WHERE q.name LIKE 'test-%' OR q.name LIKE 'edge-%' OR q.name LIKE 'pattern-%' OR q.name LIKE 'workflow-%'
85
- )
86
- `);
87
-
88
- await dbPool.query(`
89
- DELETE FROM queen.partitions
90
- WHERE queue_id IN (
91
- SELECT id FROM queen.queues WHERE name LIKE 'test-%' OR name LIKE 'edge-%' OR name LIKE 'pattern-%' OR name LIKE 'workflow-%'
92
- )
93
- `);
94
-
95
- await dbPool.query(`DELETE FROM queen.queues WHERE name LIKE 'test-%' OR name LIKE 'edge-%' OR name LIKE 'pattern-%' OR name LIKE 'workflow-%'`);
96
-
97
- await dbPool.query(`
98
- DELETE FROM queen.retention_history
99
- WHERE partition_id NOT IN (SELECT id FROM queen.partitions)
100
- `);
101
-
102
- log('Test data cleaned up');
103
- } catch (error) {
104
- log(`Cleanup error: ${error.message}`, 'warning');
105
- }
106
- };
107
-
108
- export const getMessageCount = async (queueName, partitionName = null) => {
109
- const query = partitionName
110
- ? `SELECT COUNT(*) as count FROM queen.messages m
111
- JOIN queen.partitions p ON m.partition_id = p.id
112
- JOIN queen.queues q ON p.queue_id = q.id
113
- WHERE q.name = $1 AND p.name = $2`
114
- : `SELECT COUNT(*) as count FROM queen.messages m
115
- JOIN queen.partitions p ON m.partition_id = p.id
116
- JOIN queen.queues q ON p.queue_id = q.id
117
- WHERE q.name = $1`;
118
-
119
- const params = partitionName ? [queueName, partitionName] : [queueName];
120
- const result = await dbPool.query(query, params);
121
- return parseInt(result.rows[0].count);
122
- };
123
-
124
- // Print test results summary
125
- export function printResults() {
126
- console.log('\n' + '='.repeat(80));
127
- console.log('๐Ÿ“Š TEST RESULTS SUMMARY');
128
- console.log('='.repeat(80));
129
-
130
- const passed = testResults.filter(r => r.status === 'PASS').length;
131
- const failed = testResults.filter(r => r.status === 'FAIL').length;
132
- const total = testResults.length;
133
-
134
- console.log(`\n๐Ÿ“ˆ Overall Results: ${passed}/${total} tests passed`);
135
-
136
- if (failed > 0) {
137
- console.log('\nโŒ Failed Tests:');
138
- testResults
139
- .filter(r => r.status === 'FAIL')
140
- .forEach(r => {
141
- console.log(` โ€ข ${r.test}: ${r.error}`);
142
- });
143
- }
144
-
145
- if (passed > 0) {
146
- console.log('\nโœ… Passed Tests:');
147
- testResults
148
- .filter(r => r.status === 'PASS')
149
- .forEach(r => {
150
- console.log(` โ€ข ${r.test}${r.message ? ': ' + r.message : ''}`);
151
- });
152
- }
153
-
154
- console.log('\n' + '='.repeat(80));
155
-
156
- if (failed === 0) {
157
- console.log('๐ŸŽ‰ ALL TESTS PASSED! Queen Message Queue System is working correctly.');
158
- console.log(' All features are operational.');
159
- } else {
160
- console.log(`โš ๏ธ ${failed} test(s) failed. Please review the failures above.`);
161
- process.exit(1);
162
- }
163
- }
164
-
165
- // Reset test results (useful for running tests in batches)
166
- export function resetResults() {
167
- testResults = [];
168
- }
169
-
@@ -1,114 +0,0 @@
1
- /**
2
- * Test to validate windowBuffer functionality
3
- * Ensures windowBuffer works correctly for all access modes:
4
- * - Direct partition access
5
- * - Queue-level access
6
- * - Namespace/task filtered access
7
- */
8
-
9
- import { Queen } from '../client/index.js';
10
- import { sleep } from './utils.js';
11
-
12
- const client = new Queen({
13
- baseUrl: 'http://localhost:6632'
14
- });
15
-
16
- async function testWindowBuffer() {
17
- console.log('\n๐Ÿงช Testing windowBuffer functionality...\n');
18
-
19
- const timestamp = Date.now();
20
- const queueName = 'test-window-buffer-' + timestamp;
21
- const partition = 'test-partition';
22
-
23
- // Delete queue if it exists (cleanup from previous runs)
24
- try {
25
- await client.queueDelete(queueName);
26
- console.log(`0. Deleted existing queue "${queueName}" (cleanup)`);
27
- } catch (err) {
28
- // Queue doesn't exist, that's fine
29
- }
30
-
31
- // Configure queue with 10 second window buffer
32
- console.log(`1. Creating queue "${queueName}" with windowBuffer: 10 seconds`);
33
- await client.queue(queueName, {
34
- windowBuffer: 10
35
- });
36
-
37
- // Push first message
38
- console.log('2. Pushing first message at', new Date().toISOString());
39
- await client.push(`${queueName}/${partition}`, { message: 'Message 1' });
40
-
41
- // Wait 2 seconds and push second message
42
- await sleep(2000);
43
- console.log('3. Pushing second message at', new Date().toISOString());
44
- await client.push(`${queueName}/${partition}`, { message: 'Message 2' });
45
-
46
- // Try to pop immediately (should get NOTHING due to windowBuffer)
47
- console.log('\n4. Trying to pop immediately (should get NOTHING due to 10s windowBuffer)...');
48
-
49
- // Test CASE 1: Direct partition access
50
- console.log('\n TEST CASE 1: Direct partition access');
51
- let case1Result = 0;
52
- for await (const msg of client.take(`${queueName}/${partition}`, { limit: 10, batch: 10 })) {
53
- case1Result++;
54
- await client.ack(msg, true);
55
- }
56
- const case1Status = case1Result === 0 ? 'โœ…' : 'โŒ';
57
- console.log(` ${case1Status} DIRECT ACCESS: Got ${case1Result} messages (expected 0)`);
58
-
59
- // Test CASE 2: Queue-level access
60
- console.log('\n TEST CASE 2: Queue-level access');
61
- let case2Result = 0;
62
- for await (const msg of client.take(queueName, { limit: 10, batch: 10 })) {
63
- case2Result++;
64
- await client.ack(msg, true);
65
- }
66
- const case2Status = case2Result === 0 ? 'โœ…' : 'โŒ';
67
- console.log(` ${case2Status} QUEUE ACCESS: Got ${case2Result} messages (expected 0)`);
68
-
69
- // Test CASE 3: Namespace/task filtered access (should work correctly)
70
- console.log('\n TEST CASE 3: Namespace/task filtered access');
71
-
72
- // Use unique namespace/task per test run to avoid collisions
73
- const testNamespace = `test-ns-${timestamp}`;
74
- const testTask = `test-task-${timestamp}`;
75
- const filteredQueue = `${queueName}-filtered`;
76
-
77
- // Delete queue if it exists
78
- try {
79
- await client.queueDelete(filteredQueue);
80
- } catch (err) {
81
- // Queue doesn't exist, that's fine
82
- }
83
-
84
- await client.queue(filteredQueue, {
85
- windowBuffer: 10
86
- }, testNamespace, testTask);
87
-
88
- await client.push(`${filteredQueue}/${partition}`, { message: 'Filtered message' });
89
-
90
- let case3Result = 0;
91
- for await (const msg of client.take(`namespace:${testNamespace}/task:${testTask}`, { limit: 10, batch: 10 })) {
92
- case3Result++;
93
- await client.ack(msg, true);
94
- }
95
- const case3Status = case3Result === 0 ? 'โœ…' : 'โŒ';
96
- console.log(` ${case3Status} FILTERED ACCESS: Got ${case3Result} messages (expected 0)`);
97
-
98
- console.log('\n๐Ÿ“Š SUMMARY:');
99
- const allPassed = case1Result === 0 && case2Result === 0 && case3Result === 0;
100
-
101
- if (allPassed) {
102
- console.log(' โœ… All tests PASSED! windowBuffer is working correctly in all access modes.');
103
- } else {
104
- console.log(' Issues found:');
105
- if (case1Result !== 0) console.log(' โŒ Direct partition access: windowBuffer NOT enforced');
106
- if (case2Result !== 0) console.log(' โŒ Queue-level access: windowBuffer NOT enforced');
107
- if (case3Result !== 0) console.log(' โŒ Namespace/task filtered access: windowBuffer NOT enforced');
108
- }
109
-
110
- console.log('\n' + (allPassed ? 'โœ… Test complete. All fixed!' : 'โŒ Test complete. Issues remain.') + '\n');
111
- }
112
-
113
- testWindowBuffer().catch(console.error);
114
-
@@ -1,44 +0,0 @@
1
- /**
2
- * Centralized logging utility for Queen message queue
3
- * Logs all state-changing operations with consistent formatting
4
- */
5
-
6
- /**
7
- * Log a message with timestamp and process ID
8
- * @param {...any} args - Arguments to log (objects will be JSON stringified)
9
- */
10
- export function log(...args) {
11
- args = args.map(arg => typeof arg === 'object' ? JSON.stringify(arg) : arg);
12
- const msg = args.join(' ');
13
- console.log(new Date(), `| ${process.pid} | #> ${msg}`);
14
- }
15
-
16
- /**
17
- * Log operation types for consistency
18
- */
19
- export const LogTypes = {
20
- // Message operations
21
- PUSH: 'PUSH',
22
- POP: 'POP',
23
- POP_FILTERED: 'POP_FILTERED',
24
- ACK: 'ACK',
25
- ACK_BATCH: 'ACK_BATCH',
26
-
27
- // Message state changes
28
- DELETE: 'DELETE',
29
- RETRY: 'RETRY',
30
- RETRY_SCHEDULED: 'RETRY_SCHEDULED',
31
- MOVED_TO_DLQ: 'MOVED_TO_DLQ',
32
- MANUAL_DLQ: 'MANUAL_DLQ',
33
-
34
- // Queue operations
35
- CLEAR_QUEUE: 'CLEAR_QUEUE',
36
- CONFIGURE_QUEUE: 'CONFIGURE_QUEUE',
37
-
38
- // System operations
39
- EVICTION: 'EVICTION',
40
- RETENTION: 'RETENTION',
41
- LEASE_EXPIRED: 'LEASE_EXPIRED'
42
- };
43
-
44
- export default log;
@@ -1,5 +0,0 @@
1
- import { v7 as uuidv7 } from 'uuid';
2
-
3
- export const generateUUID = () => {
4
- return uuidv7();
5
- };