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.
- package/README.md +467 -1775
- package/package.json +12 -14
- package/src/client/client.js +664 -5
- package/src/managers/queueManagerOptimized.js +250 -47
- package/src/routes/ack.js +3 -3
- package/src/server.js +131 -3
- package/src/test/advanced-client-tests.js +761 -0
- package/src/test/advanced-pattern-tests.js +2 -2
- package/src/test/bus-mode-tests.js +6 -6
- package/src/test/core-tests.js +1 -1
- package/src/test/edge-case-tests.js +2 -2
- package/src/test/test-new.js +36 -1
- package/src/webapp-dist/assets/Analytics-DJrE4Rz2.css +1 -0
- package/src/webapp-dist/assets/Analytics-HEMXKmfJ.js +1 -0
- package/src/webapp-dist/assets/ConfirmDialog-YEoCdE7x.js +1 -0
- package/src/webapp-dist/assets/ConsumerGroups-CC5VJywp.css +1 -0
- package/src/webapp-dist/assets/ConsumerGroups-D8Z20HhZ.js +1 -0
- package/src/webapp-dist/assets/Dashboard-BRFOz6it.css +1 -0
- package/src/webapp-dist/assets/Dashboard-Bpx9I32h.js +1 -0
- package/src/webapp-dist/assets/LoadingSpinner-BPttXcbs.js +1 -0
- package/src/webapp-dist/assets/Messages-BOfVHKma.css +1 -0
- package/src/webapp-dist/assets/Messages-EKURCbLl.js +1 -0
- package/src/webapp-dist/assets/QueueDetail-BXXA7xoZ.css +1 -0
- package/src/webapp-dist/assets/QueueDetail-Bmxg0KiA.js +1 -0
- package/src/webapp-dist/assets/Queues-CvrJkrZT.css +1 -0
- package/src/webapp-dist/assets/Queues-yUx9_3-9.js +1 -0
- package/src/webapp-dist/assets/StatusBadge-C1bBtXHh.css +1 -0
- package/src/webapp-dist/assets/StatusBadge-C6N84XmO.js +1 -0
- package/src/webapp-dist/assets/analytics-BapTekLM.js +1 -0
- package/src/webapp-dist/assets/colors-5z6Q_kUr.js +18 -0
- package/src/webapp-dist/assets/index-B7w2bKT6.css +1 -0
- package/src/webapp-dist/assets/index-CUSnwYTH.js +31 -0
- package/src/webapp-dist/assets/messages-CRV6E-xU.js +1 -0
- package/src/webapp-dist/assets/queues-BdUbxfBC.js +1 -0
- package/src/webapp-dist/assets/resources-Bs9U-ceF.js +1 -0
- package/{webapp → src/webapp-dist}/index.html +2 -1
- package/API.md +0 -1226
- package/AUTH.md +0 -2044
- package/CHANGELOG_STATIC_SERVING.md +0 -213
- package/DEPLOYMENT.md +0 -425
- package/PROGRAMMATIC_SERVER.md +0 -239
- package/WEBAPP.md +0 -1889
- package/assets/dashboard-01.png +0 -0
- package/assets/dashboard.png +0 -0
- package/examples/batch-processing.js +0 -58
- package/examples/bus-mode.js +0 -239
- package/examples/continuous-consumer-optimized.js +0 -215
- package/examples/continuous-consumer.js +0 -159
- package/examples/continuous-producer.js +0 -343
- package/examples/mixed-mode.js +0 -277
- package/examples/multi-server-test.js +0 -305
- package/examples/programmatic-server.js +0 -58
- package/examples/server-with-frontend.js +0 -46
- package/examples/single.js +0 -64
- package/examples/smartchat-dealyed.js +0 -42
- package/examples/smartchat.js +0 -52
- package/examples/test-cache-invalidation.js +0 -119
- package/examples/test-cache-multi-server.js +0 -245
- package/examples/test-complete-client.js +0 -260
- package/examples/test-connection-recovery.js +0 -66
- package/examples/test-dashboard-api.js +0 -200
- package/examples/test-minimal-client.js +0 -112
- package/examples/test-queue-creation-policy.js +0 -137
- package/examples/test-traceid.js +0 -147
- package/server.log +0 -1
- package/test-keepalive-v2.sh +0 -22
- package/webapp/COLOR_GUIDE.md +0 -118
- package/webapp/README.md +0 -143
- package/webapp/package-lock.json +0 -3184
- package/webapp/package.json +0 -25
- package/webapp/postcss.config.js +0 -7
- package/webapp/public/assets/queen-logo-blue.svg +0 -210
- package/webapp/public/assets/queen-logo-cyan.svg +0 -210
- package/webapp/public/assets/queen-logo-indigo.svg +0 -210
- package/webapp/public/assets/queen-logo-orange.svg +0 -210
- package/webapp/public/assets/queen-logo-pink.svg +0 -210
- package/webapp/public/assets/queen-logo-purple.svg +0 -210
- package/webapp/public/assets/queen-logo-rose.svg +0 -239
- package/webapp/public/assets/queen-logo.svg +0 -263
- package/webapp/src/App.vue +0 -19
- package/webapp/src/api/analytics.js +0 -10
- package/webapp/src/api/client.js +0 -34
- package/webapp/src/api/consumers.js +0 -52
- package/webapp/src/api/health.js +0 -7
- package/webapp/src/api/messages.js +0 -26
- package/webapp/src/api/queues.js +0 -14
- package/webapp/src/api/resources.js +0 -8
- package/webapp/src/assets/styles/main.css +0 -357
- package/webapp/src/components/analytics/AnalyticsFilters.vue +0 -87
- package/webapp/src/components/analytics/AnalyticsMetrics.vue +0 -57
- package/webapp/src/components/analytics/MessageDistributionChart.vue +0 -111
- package/webapp/src/components/analytics/MessageFlowChart.vue +0 -173
- package/webapp/src/components/analytics/TimeRangeSelector.vue +0 -27
- package/webapp/src/components/analytics/TopQueuesChart.vue +0 -132
- package/webapp/src/components/common/ConfirmDialog.vue +0 -56
- package/webapp/src/components/common/LoadingSpinner.vue +0 -6
- package/webapp/src/components/common/MetricCard.vue +0 -43
- package/webapp/src/components/common/StatusBadge.vue +0 -45
- package/webapp/src/components/dashboard/MessageStatusCard.vue +0 -50
- package/webapp/src/components/dashboard/PerformanceCard.vue +0 -38
- package/webapp/src/components/dashboard/ThroughputChart.vue +0 -182
- package/webapp/src/components/dashboard/TopQueuesTable.vue +0 -53
- package/webapp/src/components/layout/AppLayout.vue +0 -110
- package/webapp/src/components/layout/AppSidebar.vue +0 -304
- package/webapp/src/components/messages/MessageDetailPanel.vue +0 -242
- package/webapp/src/components/messages/MessageFilters.vue +0 -101
- package/webapp/src/components/queue-detail/PartitionList.vue +0 -79
- package/webapp/src/components/queue-detail/PushMessageModal.vue +0 -175
- package/webapp/src/components/queue-detail/QueueConfig.vue +0 -63
- package/webapp/src/components/queue-detail/QueueDetailHeader.vue +0 -53
- package/webapp/src/components/queue-detail/RecentMessages.vue +0 -76
- package/webapp/src/components/queues/CreateQueueModal.vue +0 -193
- package/webapp/src/components/queues/QueueFilters.vue +0 -90
- package/webapp/src/composables/useApi.js +0 -34
- package/webapp/src/composables/useTheme.js +0 -36
- package/webapp/src/main.js +0 -11
- package/webapp/src/router/index.js +0 -42
- package/webapp/src/utils/colors.js +0 -96
- package/webapp/src/utils/formatters.js +0 -49
- package/webapp/src/views/Analytics.vue +0 -377
- package/webapp/src/views/ConsumerGroups.vue +0 -433
- package/webapp/src/views/Dashboard.vue +0 -418
- package/webapp/src/views/Messages.vue +0 -363
- package/webapp/src/views/QueueDetail.vue +0 -582
- package/webapp/src/views/Queues.vue +0 -496
- package/webapp/tailwind.config.js +0 -25
- package/webapp/vite.config.js +0 -10
- /package/{assets → src/webapp-dist/assets}/queen-logo-blue.svg +0 -0
- /package/{assets → src/webapp-dist/assets}/queen-logo-cyan.svg +0 -0
- /package/{assets → src/webapp-dist/assets}/queen-logo-indigo.svg +0 -0
- /package/{assets → src/webapp-dist/assets}/queen-logo-orange.svg +0 -0
- /package/{assets → src/webapp-dist/assets}/queen-logo-pink.svg +0 -0
- /package/{assets → src/webapp-dist/assets}/queen-logo-purple.svg +0 -0
- /package/{assets → src/webapp-dist/assets}/queen-logo-rose.svg +0 -0
- /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
|
-
|