queen-mq 0.1.5 → 0.2.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 (135) hide show
  1. package/README.md +467 -1775
  2. package/package.json +12 -14
  3. package/src/client/client.js +664 -5
  4. package/src/managers/queueManagerOptimized.js +250 -47
  5. package/src/routes/ack.js +3 -3
  6. package/src/server.js +131 -3
  7. package/src/test/advanced-client-tests.js +761 -0
  8. package/src/test/advanced-pattern-tests.js +2 -2
  9. package/src/test/bus-mode-tests.js +6 -6
  10. package/src/test/core-tests.js +1 -1
  11. package/src/test/edge-case-tests.js +2 -2
  12. package/src/test/test-new.js +36 -1
  13. package/src/webapp-dist/assets/Analytics-DJrE4Rz2.css +1 -0
  14. package/src/webapp-dist/assets/Analytics-HEMXKmfJ.js +1 -0
  15. package/src/webapp-dist/assets/ConfirmDialog-YEoCdE7x.js +1 -0
  16. package/src/webapp-dist/assets/ConsumerGroups-CC5VJywp.css +1 -0
  17. package/src/webapp-dist/assets/ConsumerGroups-D8Z20HhZ.js +1 -0
  18. package/src/webapp-dist/assets/Dashboard-BRFOz6it.css +1 -0
  19. package/src/webapp-dist/assets/Dashboard-Bpx9I32h.js +1 -0
  20. package/src/webapp-dist/assets/LoadingSpinner-BPttXcbs.js +1 -0
  21. package/src/webapp-dist/assets/Messages-BOfVHKma.css +1 -0
  22. package/src/webapp-dist/assets/Messages-EKURCbLl.js +1 -0
  23. package/src/webapp-dist/assets/QueueDetail-BXXA7xoZ.css +1 -0
  24. package/src/webapp-dist/assets/QueueDetail-Bmxg0KiA.js +1 -0
  25. package/src/webapp-dist/assets/Queues-CvrJkrZT.css +1 -0
  26. package/src/webapp-dist/assets/Queues-yUx9_3-9.js +1 -0
  27. package/src/webapp-dist/assets/StatusBadge-C1bBtXHh.css +1 -0
  28. package/src/webapp-dist/assets/StatusBadge-C6N84XmO.js +1 -0
  29. package/src/webapp-dist/assets/analytics-BapTekLM.js +1 -0
  30. package/src/webapp-dist/assets/colors-5z6Q_kUr.js +18 -0
  31. package/src/webapp-dist/assets/index-B7w2bKT6.css +1 -0
  32. package/src/webapp-dist/assets/index-CUSnwYTH.js +31 -0
  33. package/src/webapp-dist/assets/messages-CRV6E-xU.js +1 -0
  34. package/src/webapp-dist/assets/queues-BdUbxfBC.js +1 -0
  35. package/src/webapp-dist/assets/resources-Bs9U-ceF.js +1 -0
  36. package/{webapp → src/webapp-dist}/index.html +2 -1
  37. package/API.md +0 -1226
  38. package/AUTH.md +0 -2044
  39. package/CHANGELOG_STATIC_SERVING.md +0 -213
  40. package/DEPLOYMENT.md +0 -425
  41. package/PROGRAMMATIC_SERVER.md +0 -239
  42. package/WEBAPP.md +0 -1889
  43. package/assets/dashboard-01.png +0 -0
  44. package/assets/dashboard.png +0 -0
  45. package/examples/batch-processing.js +0 -58
  46. package/examples/bus-mode.js +0 -239
  47. package/examples/continuous-consumer-optimized.js +0 -215
  48. package/examples/continuous-consumer.js +0 -159
  49. package/examples/continuous-producer.js +0 -343
  50. package/examples/mixed-mode.js +0 -277
  51. package/examples/multi-server-test.js +0 -305
  52. package/examples/programmatic-server.js +0 -58
  53. package/examples/server-with-frontend.js +0 -46
  54. package/examples/single.js +0 -64
  55. package/examples/smartchat-dealyed.js +0 -42
  56. package/examples/smartchat.js +0 -52
  57. package/examples/test-cache-invalidation.js +0 -119
  58. package/examples/test-cache-multi-server.js +0 -245
  59. package/examples/test-complete-client.js +0 -260
  60. package/examples/test-connection-recovery.js +0 -66
  61. package/examples/test-dashboard-api.js +0 -200
  62. package/examples/test-minimal-client.js +0 -112
  63. package/examples/test-queue-creation-policy.js +0 -137
  64. package/examples/test-traceid.js +0 -147
  65. package/server.log +0 -1
  66. package/test-keepalive-v2.sh +0 -22
  67. package/webapp/COLOR_GUIDE.md +0 -118
  68. package/webapp/README.md +0 -143
  69. package/webapp/package-lock.json +0 -3184
  70. package/webapp/package.json +0 -25
  71. package/webapp/postcss.config.js +0 -7
  72. package/webapp/public/assets/queen-logo-blue.svg +0 -210
  73. package/webapp/public/assets/queen-logo-cyan.svg +0 -210
  74. package/webapp/public/assets/queen-logo-indigo.svg +0 -210
  75. package/webapp/public/assets/queen-logo-orange.svg +0 -210
  76. package/webapp/public/assets/queen-logo-pink.svg +0 -210
  77. package/webapp/public/assets/queen-logo-purple.svg +0 -210
  78. package/webapp/public/assets/queen-logo-rose.svg +0 -239
  79. package/webapp/public/assets/queen-logo.svg +0 -263
  80. package/webapp/src/App.vue +0 -19
  81. package/webapp/src/api/analytics.js +0 -10
  82. package/webapp/src/api/client.js +0 -34
  83. package/webapp/src/api/consumers.js +0 -52
  84. package/webapp/src/api/health.js +0 -7
  85. package/webapp/src/api/messages.js +0 -26
  86. package/webapp/src/api/queues.js +0 -14
  87. package/webapp/src/api/resources.js +0 -8
  88. package/webapp/src/assets/styles/main.css +0 -357
  89. package/webapp/src/components/analytics/AnalyticsFilters.vue +0 -87
  90. package/webapp/src/components/analytics/AnalyticsMetrics.vue +0 -57
  91. package/webapp/src/components/analytics/MessageDistributionChart.vue +0 -111
  92. package/webapp/src/components/analytics/MessageFlowChart.vue +0 -173
  93. package/webapp/src/components/analytics/TimeRangeSelector.vue +0 -27
  94. package/webapp/src/components/analytics/TopQueuesChart.vue +0 -132
  95. package/webapp/src/components/common/ConfirmDialog.vue +0 -56
  96. package/webapp/src/components/common/LoadingSpinner.vue +0 -6
  97. package/webapp/src/components/common/MetricCard.vue +0 -43
  98. package/webapp/src/components/common/StatusBadge.vue +0 -45
  99. package/webapp/src/components/dashboard/MessageStatusCard.vue +0 -50
  100. package/webapp/src/components/dashboard/PerformanceCard.vue +0 -38
  101. package/webapp/src/components/dashboard/ThroughputChart.vue +0 -182
  102. package/webapp/src/components/dashboard/TopQueuesTable.vue +0 -53
  103. package/webapp/src/components/layout/AppLayout.vue +0 -110
  104. package/webapp/src/components/layout/AppSidebar.vue +0 -304
  105. package/webapp/src/components/messages/MessageDetailPanel.vue +0 -242
  106. package/webapp/src/components/messages/MessageFilters.vue +0 -101
  107. package/webapp/src/components/queue-detail/PartitionList.vue +0 -79
  108. package/webapp/src/components/queue-detail/PushMessageModal.vue +0 -175
  109. package/webapp/src/components/queue-detail/QueueConfig.vue +0 -63
  110. package/webapp/src/components/queue-detail/QueueDetailHeader.vue +0 -53
  111. package/webapp/src/components/queue-detail/RecentMessages.vue +0 -76
  112. package/webapp/src/components/queues/CreateQueueModal.vue +0 -193
  113. package/webapp/src/components/queues/QueueFilters.vue +0 -90
  114. package/webapp/src/composables/useApi.js +0 -34
  115. package/webapp/src/composables/useTheme.js +0 -36
  116. package/webapp/src/main.js +0 -11
  117. package/webapp/src/router/index.js +0 -42
  118. package/webapp/src/utils/colors.js +0 -96
  119. package/webapp/src/utils/formatters.js +0 -49
  120. package/webapp/src/views/Analytics.vue +0 -377
  121. package/webapp/src/views/ConsumerGroups.vue +0 -433
  122. package/webapp/src/views/Dashboard.vue +0 -418
  123. package/webapp/src/views/Messages.vue +0 -363
  124. package/webapp/src/views/QueueDetail.vue +0 -582
  125. package/webapp/src/views/Queues.vue +0 -496
  126. package/webapp/tailwind.config.js +0 -25
  127. package/webapp/vite.config.js +0 -10
  128. /package/{assets → src/webapp-dist/assets}/queen-logo-blue.svg +0 -0
  129. /package/{assets → src/webapp-dist/assets}/queen-logo-cyan.svg +0 -0
  130. /package/{assets → src/webapp-dist/assets}/queen-logo-indigo.svg +0 -0
  131. /package/{assets → src/webapp-dist/assets}/queen-logo-orange.svg +0 -0
  132. /package/{assets → src/webapp-dist/assets}/queen-logo-pink.svg +0 -0
  133. /package/{assets → src/webapp-dist/assets}/queen-logo-purple.svg +0 -0
  134. /package/{assets → src/webapp-dist/assets}/queen-logo-rose.svg +0 -0
  135. /package/{assets → src/webapp-dist/assets}/queen-logo.svg +0 -0
@@ -1,245 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Cache Testing with Multiple Servers
5
- *
6
- * This script helps test if cache is causing issues when using multiple servers.
7
- * It sends requests alternately to different servers to check cache consistency.
8
- *
9
- * Usage:
10
- * 1. Start two Queen servers on different ports:
11
- * PORT=6632 node src/server.js
12
- * PORT=6633 node src/server.js
13
- *
14
- * 2. Run this test:
15
- * node examples/test-cache-multi-server.js
16
- */
17
-
18
- import { createQueenClient, LoadBalancingStrategy } from '../src/client/index.js';
19
-
20
- const servers = [
21
- 'http://localhost:6632',
22
- 'http://localhost:6633'
23
- ];
24
-
25
- const TEST_QUEUE = 'cache-test';
26
- const TEST_NAMESPACE = 'cache-verification';
27
-
28
- // Helper to log with server info
29
- const log = (message, server = null) => {
30
- const timestamp = new Date().toISOString().split('T')[1].slice(0, -1);
31
- const serverInfo = server ? ` [${server}]` : '';
32
- console.log(`${timestamp}${serverInfo} | ${message}`);
33
- };
34
-
35
- async function testCacheConsistency() {
36
- console.log('=' .repeat(80));
37
- console.log('Testing Cache Consistency Across Multiple Servers');
38
- console.log('=' .repeat(80));
39
-
40
- // Create client with ROUND_ROBIN to alternate between servers
41
- const roundRobinClient = createQueenClient({
42
- baseUrls: servers,
43
- loadBalancingStrategy: LoadBalancingStrategy.ROUND_ROBIN,
44
- enableFailover: false // Disable failover to see actual server responses
45
- });
46
-
47
- // Create client with SESSION to stick to one server
48
- const sessionClient = createQueenClient({
49
- baseUrls: servers,
50
- loadBalancingStrategy: LoadBalancingStrategy.SESSION,
51
- enableFailover: false
52
- });
53
-
54
- try {
55
- // Step 1: Configure queue on both servers via round-robin
56
- log('Step 1: Configuring queue on both servers...');
57
-
58
- for (let i = 0; i < servers.length; i++) {
59
- await roundRobinClient.configure({
60
- queue: TEST_QUEUE,
61
- namespace: TEST_NAMESPACE,
62
- task: 'cache-test',
63
- options: {
64
- maxRetries: 3,
65
- retryDelay: 1000,
66
- priority: 5
67
- }
68
- });
69
- const stats = roundRobinClient.getLoadBalancerStats();
70
- log(`Configuration sent to server ${i + 1}`, servers[i]);
71
- }
72
-
73
- // Step 2: Push messages alternating between servers
74
- log('\nStep 2: Pushing messages to alternate servers...');
75
-
76
- for (let i = 1; i <= 6; i++) {
77
- const result = await roundRobinClient.push({
78
- items: [{
79
- queue: TEST_QUEUE,
80
- partition: 'Default',
81
- payload: {
82
- messageId: i,
83
- server: `push-${i % 2 === 0 ? 2 : 1}`,
84
- timestamp: Date.now()
85
- }
86
- }]
87
- });
88
-
89
- const stats = roundRobinClient.getLoadBalancerStats();
90
- log(`Message ${i} pushed`, servers[(i - 1) % servers.length]);
91
- }
92
-
93
- // Step 3: Check queue stats from both servers
94
- log('\nStep 3: Checking queue stats from each server...');
95
-
96
- for (let i = 0; i < servers.length; i++) {
97
- try {
98
- const analytics = await roundRobinClient.analytics.queue(TEST_QUEUE);
99
- log(`Queue stats from server ${i + 1}: ${JSON.stringify(analytics)}`, servers[i]);
100
- } catch (error) {
101
- log(`Failed to get stats from server ${i + 1}: ${error.message}`, servers[i]);
102
- }
103
- }
104
-
105
- // Step 4: Pop messages from different servers
106
- log('\nStep 4: Popping messages from different servers...');
107
-
108
- // Pop from server 1 (using session client for consistency)
109
- const sessionClient1 = createQueenClient({
110
- baseUrl: servers[0],
111
- enableFailover: false
112
- });
113
-
114
- const pop1 = await sessionClient1.pop({
115
- queue: TEST_QUEUE,
116
- batch: 3,
117
- wait: false
118
- });
119
-
120
- log(`Server 1 returned ${pop1.messages?.length || 0} messages`, servers[0]);
121
- if (pop1.messages && pop1.messages.length > 0) {
122
- for (const msg of pop1.messages) {
123
- log(` - Message: ${JSON.stringify(msg.data)}`, servers[0]);
124
- await sessionClient1.ack(msg.transactionId, 'completed');
125
- }
126
- }
127
-
128
- // Pop from server 2
129
- const sessionClient2 = createQueenClient({
130
- baseUrl: servers[1],
131
- enableFailover: false
132
- });
133
-
134
- const pop2 = await sessionClient2.pop({
135
- queue: TEST_QUEUE,
136
- batch: 3,
137
- wait: false
138
- });
139
-
140
- log(`Server 2 returned ${pop2.messages?.length || 0} messages`, servers[1]);
141
- if (pop2.messages && pop2.messages.length > 0) {
142
- for (const msg of pop2.messages) {
143
- log(` - Message: ${JSON.stringify(msg.data)}`, servers[1]);
144
- await sessionClient2.ack(msg.transactionId, 'completed');
145
- }
146
- }
147
-
148
- // Step 5: Test resource cache consistency
149
- log('\nStep 5: Testing resource cache consistency...');
150
-
151
- // Update configuration on server 1
152
- const updateClient1 = createQueenClient({
153
- baseUrl: servers[0],
154
- enableFailover: false
155
- });
156
-
157
- await updateClient1.configure({
158
- queue: TEST_QUEUE,
159
- namespace: TEST_NAMESPACE,
160
- task: 'cache-test-updated',
161
- options: {
162
- maxRetries: 5, // Changed from 3
163
- retryDelay: 2000, // Changed from 1000
164
- priority: 10 // Changed from 5
165
- }
166
- });
167
-
168
- log('Configuration updated on server 1', servers[0]);
169
-
170
- // Wait a moment for potential cache propagation
171
- await new Promise(resolve => setTimeout(resolve, 1000));
172
-
173
- // Check if server 2 sees the update
174
- log('Checking if configuration changes are visible on both servers...');
175
-
176
- // Push a message to server 2 and see if it uses new or old config
177
- const testClient2 = createQueenClient({
178
- baseUrl: servers[1],
179
- enableFailover: false
180
- });
181
-
182
- await testClient2.push({
183
- items: [{
184
- queue: TEST_QUEUE,
185
- partition: 'CacheTest',
186
- payload: {
187
- test: 'cache-verification',
188
- expectedConfig: 'Should use database config, not cached'
189
- }
190
- }]
191
- });
192
-
193
- log('Test message pushed to server 2', servers[1]);
194
-
195
- // Pop and check the message properties
196
- const verifyPop = await testClient2.pop({
197
- queue: TEST_QUEUE,
198
- partition: 'CacheTest',
199
- wait: false
200
- });
201
-
202
- if (verifyPop.messages && verifyPop.messages.length > 0) {
203
- const msg = verifyPop.messages[0];
204
- log(`Message from server 2: priority=${msg.priority}, retryCount=${msg.retryCount}`, servers[1]);
205
-
206
- // Check queue configuration directly to verify cache consistency
207
- const queueStats = await testClient2.analytics.queue(TEST_QUEUE);
208
- log(`Queue config from server 2: ${JSON.stringify(queueStats)}`, servers[1]);
209
-
210
- // Priority is included in the message and should reflect the updated value
211
- if (msg.priority === 10) {
212
- log('✅ Cache consistency verified! Server 2 sees updated priority configuration', servers[1]);
213
- } else {
214
- log(`⚠️ Potential cache issue: Server 2 may be using cached configuration (priority=${msg.priority} instead of 10)`, servers[1]);
215
- }
216
-
217
- await testClient2.ack(msg.transactionId, 'completed');
218
- }
219
-
220
- // Step 6: Clean up
221
- log('\nStep 6: Cleaning up test data...');
222
-
223
- // Clear the queue on both servers
224
- await roundRobinClient.queues.clear(TEST_QUEUE);
225
- log('Test queue cleared');
226
-
227
- console.log('\n' + '=' .repeat(80));
228
- log('✅ Cache consistency test completed!');
229
- console.log('=' .repeat(80));
230
-
231
- // Print summary
232
- console.log('\nSummary:');
233
- console.log('- If both servers returned the same messages, they share the same database');
234
- console.log('- If configuration changes were visible on both servers, cache is properly invalidated');
235
- console.log('- If you see cache issues, check the resourceCache implementation in queueManagerOptimized.js');
236
-
237
- } catch (error) {
238
- log(`❌ Test failed: ${error.message}`);
239
- console.error(error);
240
- process.exit(1);
241
- }
242
- }
243
-
244
- // Run the test
245
- testCacheConsistency().catch(console.error);
@@ -1,260 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Complete test of the minimalist Queen client
5
- * Shows all features including namespace/task and message properties
6
- */
7
-
8
- import { Queen } from '../src/client/client.js';
9
-
10
- async function main() {
11
- console.log('🧪 Testing Complete Minimalist Queen Client Features\n');
12
-
13
- const client = new Queen({
14
- baseUrls: ['http://localhost:6632'],
15
- timeout: 30000
16
- });
17
-
18
- try {
19
- // ============================================
20
- // 1. Queue Configuration with Namespace/Task
21
- // ============================================
22
- console.log('1️⃣ Configuring queues with namespace and task...');
23
-
24
- // Configure queue with namespace and task
25
- await client.queue('orders-processing', {
26
- leaseTime: 300,
27
- retryLimit: 3,
28
- priority: 10
29
- }, {
30
- namespace: 'ecommerce',
31
- task: 'process'
32
- });
33
-
34
- await client.queue('inventory-updates', {
35
- leaseTime: 300,
36
- priority: 5
37
- }, {
38
- namespace: 'ecommerce',
39
- task: 'update'
40
- });
41
-
42
- await client.queue('notifications', {
43
- priority: 8
44
- }, {
45
- namespace: 'ecommerce',
46
- task: 'notify'
47
- });
48
-
49
- console.log('✅ Queues configured with namespace/task metadata\n');
50
-
51
- // ============================================
52
- // 2. Push with Message Properties
53
- // ============================================
54
- console.log('2️⃣ Pushing messages with properties...');
55
-
56
- // Method 1: Properties in options
57
- await client.push('orders-processing', {
58
- orderId: 123,
59
- amount: 99.99
60
- }, {
61
- transactionId: 'txn-123'
62
- });
63
-
64
- // Method 2: Properties in the message object
65
- await client.push('orders-processing', {
66
- orderId: 124,
67
- amount: 199.99,
68
- transactionId: 'txn-124' // Will be extracted
69
- });
70
-
71
- // Method 3: Batch with mixed properties
72
- await client.push('inventory-updates', [
73
- {
74
- sku: 'PROD-001',
75
- quantity: 5,
76
- transactionId: 'inv-001'
77
- },
78
- {
79
- sku: 'PROD-002',
80
- quantity: 10,
81
- transactionId: 'inv-002'
82
- }
83
- ]);
84
-
85
- // Method 4: Using special properties format
86
- await client.push('notifications', {
87
- _payload: { userId: 789, message: 'Order shipped' },
88
- _transactionId: 'notif-001'
89
- });
90
-
91
- console.log('✅ Messages pushed with various property patterns\n');
92
-
93
- // ============================================
94
- // 3. Take by Queue/Partition
95
- // ============================================
96
- console.log('3️⃣ Taking messages by queue/partition...');
97
-
98
- // Take from specific queue
99
- let count = 0;
100
- for await (const msg of client.take('orders-processing', { limit: 2 })) {
101
- count++;
102
- console.log(` 📩 Order ${count}:`, msg.data);
103
- console.log(` Transaction ID: ${msg.transactionId}`);
104
- await client.ack(msg);
105
- }
106
- console.log('✅ Processed orders\n');
107
-
108
- // ============================================
109
- // 4. Take by Namespace/Task
110
- // ============================================
111
- console.log('4️⃣ Taking messages by namespace/task...');
112
-
113
- // Take all messages from ecommerce namespace
114
- count = 0;
115
- for await (const msg of client.take('namespace:ecommerce', { limit: 2 })) {
116
- count++;
117
- console.log(` 📦 Namespace message ${count} from ${msg.queue}:`, msg.data);
118
- await client.ack(msg);
119
- }
120
-
121
- // Take only 'update' tasks
122
- for await (const msg of client.take('task:update', { limit: 2 })) {
123
- console.log(` 🔄 Update task from ${msg.queue}:`, msg.data);
124
- await client.ack(msg);
125
- }
126
-
127
- // Combine namespace and task
128
- for await (const msg of client.take('namespace:ecommerce/task:notify', { limit: 1 })) {
129
- console.log(` 🔔 Notification:`, msg.data);
130
- await client.ack(msg);
131
- }
132
-
133
- console.log('✅ Processed messages by namespace/task\n');
134
-
135
- // ============================================
136
- // 5. Consumer Groups with Subscription Modes
137
- // ============================================
138
- console.log('5️⃣ Testing consumer groups with subscription modes...');
139
-
140
- // Configure events queue first
141
- await client.queue('events', {
142
- leaseTime: 300,
143
- retryLimit: 3
144
- });
145
-
146
- // Push test events
147
- await client.push('events', [
148
- { event: 'user.signup', userId: 1 },
149
- { event: 'user.login', userId: 2 },
150
- { event: 'user.purchase', userId: 3 }
151
- ]);
152
-
153
- // Consumer group starting from all messages
154
- for await (const event of client.take('events@analytics', {
155
- limit: 1,
156
- subscriptionMode: 'all'
157
- })) {
158
- console.log(' 📊 Analytics (all):', event.data);
159
- await client.ack(event, true, { group: 'analytics' });
160
- }
161
-
162
- // Consumer group starting from new messages only
163
- for await (const event of client.take('events@realtime', {
164
- limit: 1,
165
- subscriptionMode: 'new'
166
- })) {
167
- console.log(' ⚡ Realtime (new only):', event.data);
168
- await client.ack(event, true, { group: 'realtime' });
169
- }
170
-
171
- console.log('✅ Consumer groups tested\n');
172
-
173
- // ============================================
174
- // 6. Advanced Patterns
175
- // ============================================
176
- console.log('6️⃣ Testing advanced patterns...');
177
-
178
- // Configure tasks queue
179
- await client.queue('tasks', {
180
- leaseTime: 300,
181
- priority: 8
182
- });
183
-
184
- // Pattern 1: Partitioned messages with properties
185
- await client.push('tasks/urgent', {
186
- taskId: 'TASK-001',
187
- priority: 'critical'
188
- }, {
189
- transactionId: 'task-txn-001'
190
- });
191
-
192
- // Pattern 2: Consumer group on specific partition
193
- for await (const task of client.take('tasks/urgent@workers', { limit: 1 })) {
194
- console.log(' 🚨 Urgent task for worker group:', task.data);
195
- await client.ack(task, true, { group: 'workers' });
196
- }
197
-
198
- // Configure logs queue
199
- await client.queue('logs', {
200
- leaseTime: 300,
201
- retentionSeconds: 86400 // Keep for 1 day
202
- });
203
-
204
- // Pattern 3: Batch push with partition
205
- await client.push('logs/audit', [
206
- { action: 'login', user: 'alice', timestamp: Date.now() },
207
- { action: 'update', user: 'bob', timestamp: Date.now() },
208
- { action: 'delete', user: 'charlie', timestamp: Date.now() }
209
- ]);
210
-
211
- console.log('✅ Advanced patterns tested\n');
212
-
213
- // ============================================
214
- // 7. Error Handling
215
- // ============================================
216
- console.log('7️⃣ Testing error handling...');
217
-
218
- // Configure error-test queue
219
- await client.queue('error-test', {
220
- leaseTime: 60,
221
- retryLimit: 2
222
- });
223
-
224
- // Push a message that will fail processing
225
- await client.push('error-test', {
226
- willFail: true,
227
- reason: 'Testing failure path'
228
- });
229
-
230
- for await (const msg of client.take('error-test', { limit: 1 })) {
231
- try {
232
- // Simulate processing error
233
- throw new Error('Simulated processing error');
234
- } catch (error) {
235
- console.log(' ❌ Failed to process:', msg.data);
236
- // Acknowledge with failure and error context
237
- await client.ack(msg, false, {
238
- error: error.message,
239
- retryable: true
240
- });
241
- }
242
- }
243
-
244
- console.log('✅ Error handling tested\n');
245
-
246
- console.log('🎉 All features tested successfully!');
247
-
248
- } catch (error) {
249
- console.error('❌ Test failed:', error.message);
250
- process.exit(1);
251
- } finally {
252
- await client.close();
253
- }
254
- }
255
-
256
- // Run tests
257
- main().catch(error => {
258
- console.error('Fatal error:', error);
259
- process.exit(1);
260
- });
@@ -1,66 +0,0 @@
1
- /**
2
- * Test connection recovery during take operations
3
- * This demonstrates how the client handles server disconnections gracefully
4
- */
5
-
6
- import { Queen } from '../src/client/index.js';
7
-
8
- async function testConnectionRecovery() {
9
- const client = new Queen({
10
- baseUrl: 'http://localhost:6632',
11
- retryDelay: 1000, // 1 second base retry delay
12
- retryAttempts: 3
13
- });
14
-
15
- try {
16
- // Configure a test queue
17
- await client.queue('test-recovery-queue');
18
- console.log('Queue configured');
19
-
20
- // Push some test messages
21
- await client.push('test-recovery-queue', [
22
- { message: 'Test message 1' },
23
- { message: 'Test message 2' },
24
- { message: 'Test message 3' }
25
- ]);
26
- console.log('Pushed 3 test messages');
27
-
28
- console.log('\nStarting consumer...');
29
- console.log('To test: Stop the server after receiving some messages');
30
- console.log('Expected behavior: Client will retry with exponential backoff indefinitely (max 30s between retries)');
31
- console.log(' When server comes back online, it will automatically reconnect\n');
32
-
33
- let messageCount = 0;
34
-
35
- // Consume messages with takeBatch
36
- for await (const batch of client.takeBatch('test-recovery-queue', {
37
- batch: 10,
38
- wait: true,
39
- timeout: 5000
40
- })) {
41
- console.log(`\nReceived batch of ${batch.length} messages:`);
42
-
43
- for (const message of batch) {
44
- messageCount++;
45
- console.log(` ${messageCount}. ${JSON.stringify(message.payload)}`);
46
-
47
- // Acknowledge the message
48
- await client.ack(message, true);
49
- }
50
- }
51
-
52
- console.log('\nConsumer loop completed');
53
- console.log(`Total messages processed: ${messageCount}`);
54
-
55
- } catch (error) {
56
- console.error('\nError in consumer:', error.message);
57
- console.error('Stack:', error.stack);
58
- } finally {
59
- await client.close();
60
- console.log('\nClient closed');
61
- }
62
- }
63
-
64
- console.log('=== Connection Recovery Test ===\n');
65
- testConnectionRecovery().catch(console.error);
66
-