queen-mq 0.1.0 → 0.1.2
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/API.md +862 -752
- package/AUTH.md +2044 -0
- package/LICENSE.md +202 -0
- package/README.md +1705 -1051
- package/WEBAPP.md +1889 -0
- package/assets/dashboard-01.png +0 -0
- package/assets/queen-logo-blue.svg +210 -0
- package/assets/queen-logo-cyan.svg +210 -0
- package/assets/queen-logo-indigo.svg +210 -0
- package/assets/queen-logo-orange.svg +210 -0
- package/assets/queen-logo-pink.svg +210 -0
- package/assets/queen-logo-purple.svg +210 -0
- package/assets/queen-logo-rose.svg +239 -0
- package/assets/queen-logo.svg +263 -0
- package/examples/batch-processing.js +58 -0
- package/examples/test-complete-client.js +260 -0
- package/examples/test-dashboard-api.js +200 -0
- package/examples/test-traceid.js +147 -0
- package/package.json +17 -4
- package/server.log +1 -0
- package/src/benchmark/consumer.js +207 -0
- package/src/benchmark/consumer_multi.js +216 -0
- package/src/benchmark/producer.js +75 -0
- package/src/benchmark/producer_multi.js +115 -0
- package/src/client/client.js +300 -31
- package/src/client/queenClient.js +5 -0
- package/src/cluster-server.js +242 -0
- package/src/config.js +19 -5
- package/src/database/connection.js +42 -16
- package/src/database/poolManager.js +7 -0
- package/src/database/schema-v2.sql +194 -130
- package/src/managers/queueManagerOptimized.js +823 -933
- package/src/managers/systemEventManager.js +8 -3
- package/src/routes/messages.js +127 -57
- package/src/routes/pop.js +27 -43
- package/src/routes/resources.js +61 -27
- package/src/routes/status.js +1037 -0
- package/src/server.js +308 -272
- package/src/services/evictionService.js +57 -28
- package/src/services/retentionService.js +44 -11
- package/src/test/MIGRATION_ISSUES.md +174 -0
- package/src/test/README.md +203 -0
- package/src/test/advanced-pattern-tests.js +1137 -0
- package/src/test/bus-mode-tests.js +361 -0
- package/src/test/core-tests.js +342 -0
- package/src/test/edge-case-tests.js +561 -0
- package/src/test/enterprise-tests.js +637 -0
- package/src/test/partition-locking-tests.js +545 -0
- package/src/test/test-new.js +278 -0
- package/src/test/test.js +6 -3
- package/src/test/utils.js +169 -0
- package/src/utils/streaming.js +231 -0
- package/src/utils/uuid.js +2 -2
- package/src/websocket/wsServer.js +10 -3
- package/test-keepalive-v2.sh +22 -0
- package/webapp/COLOR_GUIDE.md +118 -0
- package/webapp/README.md +143 -0
- package/webapp/index.html +14 -0
- package/webapp/package-lock.json +3184 -0
- package/webapp/package.json +25 -0
- package/webapp/postcss.config.js +7 -0
- package/webapp/public/assets/queen-logo-blue.svg +210 -0
- package/webapp/public/assets/queen-logo-cyan.svg +210 -0
- package/webapp/public/assets/queen-logo-indigo.svg +210 -0
- package/webapp/public/assets/queen-logo-orange.svg +210 -0
- package/webapp/public/assets/queen-logo-pink.svg +210 -0
- package/webapp/public/assets/queen-logo-purple.svg +210 -0
- package/webapp/public/assets/queen-logo-rose.svg +239 -0
- package/webapp/public/assets/queen-logo.svg +263 -0
- package/webapp/src/App.vue +19 -0
- package/webapp/src/api/analytics.js +10 -0
- package/webapp/src/api/client.js +29 -0
- package/webapp/src/api/consumers.js +52 -0
- package/webapp/src/api/health.js +7 -0
- package/webapp/src/api/messages.js +26 -0
- package/webapp/src/api/queues.js +14 -0
- package/webapp/src/api/resources.js +8 -0
- package/webapp/src/assets/styles/main.css +357 -0
- package/webapp/src/components/analytics/AnalyticsFilters.vue +87 -0
- package/webapp/src/components/analytics/AnalyticsMetrics.vue +57 -0
- package/webapp/src/components/analytics/MessageDistributionChart.vue +111 -0
- package/webapp/src/components/analytics/MessageFlowChart.vue +173 -0
- package/webapp/src/components/analytics/TimeRangeSelector.vue +27 -0
- package/webapp/src/components/analytics/TopQueuesChart.vue +132 -0
- package/webapp/src/components/common/ConfirmDialog.vue +56 -0
- package/webapp/src/components/common/LoadingSpinner.vue +6 -0
- package/webapp/src/components/common/MetricCard.vue +43 -0
- package/webapp/src/components/common/StatusBadge.vue +45 -0
- package/webapp/src/components/dashboard/MessageStatusCard.vue +50 -0
- package/webapp/src/components/dashboard/PerformanceCard.vue +38 -0
- package/webapp/src/components/dashboard/ThroughputChart.vue +182 -0
- package/webapp/src/components/dashboard/TopQueuesTable.vue +53 -0
- package/webapp/src/components/layout/AppLayout.vue +110 -0
- package/webapp/src/components/layout/AppSidebar.vue +304 -0
- package/webapp/src/components/messages/MessageDetailPanel.vue +242 -0
- package/webapp/src/components/messages/MessageFilters.vue +114 -0
- package/webapp/src/components/queue-detail/PartitionList.vue +79 -0
- package/webapp/src/components/queue-detail/PushMessageModal.vue +175 -0
- package/webapp/src/components/queue-detail/QueueConfig.vue +63 -0
- package/webapp/src/components/queue-detail/QueueDetailHeader.vue +53 -0
- package/webapp/src/components/queue-detail/RecentMessages.vue +76 -0
- package/webapp/src/components/queues/CreateQueueModal.vue +193 -0
- package/webapp/src/components/queues/QueueFilters.vue +90 -0
- package/webapp/src/composables/useApi.js +34 -0
- package/webapp/src/composables/useTheme.js +36 -0
- package/webapp/src/main.js +11 -0
- package/webapp/src/router/index.js +42 -0
- package/webapp/src/utils/colors.js +96 -0
- package/webapp/src/utils/formatters.js +49 -0
- package/webapp/src/views/Analytics.vue +377 -0
- package/webapp/src/views/ConsumerGroups.vue +433 -0
- package/webapp/src/views/Dashboard.vue +418 -0
- package/webapp/src/views/Messages.vue +361 -0
- package/webapp/src/views/QueueDetail.vue +582 -0
- package/webapp/src/views/Queues.vue +496 -0
- package/webapp/tailwind.config.js +25 -0
- package/webapp/vite.config.js +10 -0
- package/CACHE.md +0 -519
- package/DASHBOARD-V3.md +0 -478
- package/DASHBOARD.md +0 -382
- package/MOD_QUEUE.md +0 -453
- package/PARTITION_LOCKING_DESIGN.md +0 -989
- package/PLAN.md +0 -707
- package/QUERY_ANALSYS.md +0 -72
- package/QUEUE_BUS.md +0 -334
- package/V2-PLAN.md +0 -236
- package/dashboard/.vscode/extensions.json +0 -3
- package/dashboard/README.md +0 -5
- package/dashboard/index.html +0 -14
- package/dashboard/package-lock.json +0 -1458
- package/dashboard/package.json +0 -25
- package/dashboard/public/vite.svg +0 -1
- package/dashboard/src/App.vue +0 -29
- package/dashboard/src/assets/styles/main.css +0 -908
- package/dashboard/src/assets/vue.svg +0 -1
- package/dashboard/src/components/cards/MetricCard.vue +0 -298
- package/dashboard/src/components/charts/QueueDepthChart.vue +0 -276
- package/dashboard/src/components/charts/QueueLagChart.vue +0 -436
- package/dashboard/src/components/charts/ThroughputChart.vue +0 -302
- package/dashboard/src/components/common/ActivityFeed.vue +0 -251
- package/dashboard/src/components/layout/AppHeader.vue +0 -208
- package/dashboard/src/components/layout/AppLayout.vue +0 -88
- package/dashboard/src/components/layout/AppSidebar.vue +0 -261
- package/dashboard/src/main.js +0 -44
- package/dashboard/src/router.js +0 -54
- package/dashboard/src/services/api.js +0 -187
- package/dashboard/src/services/websocket.js +0 -167
- package/dashboard/src/utils/constants.js +0 -56
- package/dashboard/src/utils/helpers.js +0 -118
- package/dashboard/src/views/Analytics.vue +0 -912
- package/dashboard/src/views/Dashboard.vue +0 -906
- package/dashboard/src/views/Messages.vue +0 -437
- package/dashboard/src/views/QueueDetail.vue +0 -501
- package/dashboard/src/views/Queues.vue +0 -333
- package/dashboard/vite.config.js +0 -30
- package/debug-namespace.js +0 -110
- package/docs/long-polling.md +0 -159
- package/docs/multi-server-cache-solutions.md +0 -185
- package/docs/performance-tuning.md +0 -222
- package/src/routes/analytics.js +0 -812
package/CACHE.md
DELETED
|
@@ -1,519 +0,0 @@
|
|
|
1
|
-
# Queen Internal Event Propagation System
|
|
2
|
-
|
|
3
|
-
## Overview
|
|
4
|
-
A general-purpose internal event system using Queen's own infrastructure to propagate system events (configuration changes, cache invalidations, etc.) across multiple server instances.
|
|
5
|
-
|
|
6
|
-
## Architecture
|
|
7
|
-
|
|
8
|
-
### Event Flow
|
|
9
|
-
```
|
|
10
|
-
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
|
11
|
-
│ Server #1 │ │ Server #2 │ │ Server #3 │
|
|
12
|
-
│ │ │ │ │ │
|
|
13
|
-
│ Event Producer │ │ Event Consumer │ │ Event Consumer │
|
|
14
|
-
│ Event Consumer │ │ │ │ │
|
|
15
|
-
└────────┬────────┘ └────────┬────────┘ └────────┬────────┘
|
|
16
|
-
│ │ │
|
|
17
|
-
└───────────┬───────────┴───────────────────────┘
|
|
18
|
-
▼
|
|
19
|
-
┌───────────────────────────┐
|
|
20
|
-
│ __system_events__ │
|
|
21
|
-
│ Queue │
|
|
22
|
-
└───────────────────────────┘
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
### Event Structure
|
|
26
|
-
```javascript
|
|
27
|
-
{
|
|
28
|
-
eventType: 'queue.updated', // queue.created, queue.updated, queue.deleted
|
|
29
|
-
entityType: 'queue', // queue, partition, consumer_group
|
|
30
|
-
entityId: 'user-tasks', // queue name or other identifier
|
|
31
|
-
changes: { // What changed
|
|
32
|
-
retryLimit: { old: 3, new: 5 },
|
|
33
|
-
priority: { old: 0, new: 10 }
|
|
34
|
-
},
|
|
35
|
-
timestamp: 1234567890,
|
|
36
|
-
sourceServer: 'server_1234',
|
|
37
|
-
version: 1 // Event schema version
|
|
38
|
-
}
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
## Implementation
|
|
42
|
-
|
|
43
|
-
### Phase 1: Core Event System
|
|
44
|
-
|
|
45
|
-
#### 1.1 System Event Manager
|
|
46
|
-
**File**: `src/managers/systemEventManager.js`
|
|
47
|
-
```javascript
|
|
48
|
-
import { generateUUID } from '../utils/uuid.js';
|
|
49
|
-
|
|
50
|
-
export const SYSTEM_QUEUE = '__system_events__';
|
|
51
|
-
|
|
52
|
-
export const EventTypes = {
|
|
53
|
-
// Queue events
|
|
54
|
-
QUEUE_CREATED: 'queue.created',
|
|
55
|
-
QUEUE_UPDATED: 'queue.updated',
|
|
56
|
-
QUEUE_DELETED: 'queue.deleted',
|
|
57
|
-
|
|
58
|
-
// Partition events
|
|
59
|
-
PARTITION_CREATED: 'partition.created',
|
|
60
|
-
PARTITION_DELETED: 'partition.deleted',
|
|
61
|
-
|
|
62
|
-
// Future events
|
|
63
|
-
CONSUMER_GROUP_CREATED: 'consumer_group.created',
|
|
64
|
-
CONSUMER_GROUP_UPDATED: 'consumer_group.updated'
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
export class SystemEventManager {
|
|
68
|
-
constructor(pool, serverInstanceId) {
|
|
69
|
-
this.pool = pool;
|
|
70
|
-
this.serverInstanceId = serverInstanceId;
|
|
71
|
-
this.handlers = new Map();
|
|
72
|
-
this.eventQueue = [];
|
|
73
|
-
this.batchTimer = null;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Register event handlers
|
|
77
|
-
on(eventType, handler) {
|
|
78
|
-
if (!this.handlers.has(eventType)) {
|
|
79
|
-
this.handlers.set(eventType, []);
|
|
80
|
-
}
|
|
81
|
-
this.handlers.get(eventType).push(handler);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Emit event locally and to system queue
|
|
85
|
-
async emit(eventType, data) {
|
|
86
|
-
const event = {
|
|
87
|
-
id: generateUUID(),
|
|
88
|
-
eventType,
|
|
89
|
-
...data,
|
|
90
|
-
timestamp: Date.now(),
|
|
91
|
-
sourceServer: this.serverInstanceId,
|
|
92
|
-
version: 1
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
// Handle locally first (immediate consistency for originating server)
|
|
96
|
-
await this.handleEventLocally(event);
|
|
97
|
-
|
|
98
|
-
// Queue for batch publishing
|
|
99
|
-
this.eventQueue.push(event);
|
|
100
|
-
this.scheduleBatch();
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// Process incoming event from system queue
|
|
104
|
-
async processSystemEvent(event) {
|
|
105
|
-
// Skip own events (already processed locally)
|
|
106
|
-
if (event.sourceServer === this.serverInstanceId) {
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
await this.handleEventLocally(event);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
async handleEventLocally(event) {
|
|
114
|
-
const handlers = this.handlers.get(event.eventType) || [];
|
|
115
|
-
for (const handler of handlers) {
|
|
116
|
-
try {
|
|
117
|
-
await handler(event);
|
|
118
|
-
} catch (error) {
|
|
119
|
-
console.error(`Handler failed for ${event.eventType}:`, error);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
scheduleBatch() {
|
|
125
|
-
if (this.batchTimer) return;
|
|
126
|
-
|
|
127
|
-
this.batchTimer = setTimeout(() => {
|
|
128
|
-
this.publishBatch();
|
|
129
|
-
}, 10); // 10ms batching
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
async publishBatch() {
|
|
133
|
-
if (this.eventQueue.length === 0) return;
|
|
134
|
-
|
|
135
|
-
const events = [...this.eventQueue];
|
|
136
|
-
this.eventQueue = [];
|
|
137
|
-
this.batchTimer = null;
|
|
138
|
-
|
|
139
|
-
try {
|
|
140
|
-
// Direct database insert to avoid circular dependency
|
|
141
|
-
const client = await this.pool.connect();
|
|
142
|
-
try {
|
|
143
|
-
for (const event of events) {
|
|
144
|
-
await this.insertSystemEvent(client, event);
|
|
145
|
-
}
|
|
146
|
-
} finally {
|
|
147
|
-
client.release();
|
|
148
|
-
}
|
|
149
|
-
} catch (error) {
|
|
150
|
-
console.error('Failed to publish system events:', error);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
async insertSystemEvent(client, event) {
|
|
155
|
-
// Direct insert bypassing queue manager to avoid circular dependency
|
|
156
|
-
await client.query(`
|
|
157
|
-
INSERT INTO queen.messages (
|
|
158
|
-
id, transaction_id, partition_id, payload,
|
|
159
|
-
created_at, trace_id
|
|
160
|
-
)
|
|
161
|
-
SELECT
|
|
162
|
-
$1, $2, p.id, $3, NOW(), $4
|
|
163
|
-
FROM queen.partitions p
|
|
164
|
-
JOIN queen.queues q ON p.queue_id = q.id
|
|
165
|
-
WHERE q.name = $5 AND p.name = 'Default'
|
|
166
|
-
`, [
|
|
167
|
-
generateUUID(),
|
|
168
|
-
generateUUID(),
|
|
169
|
-
JSON.stringify(event),
|
|
170
|
-
event.id,
|
|
171
|
-
SYSTEM_QUEUE
|
|
172
|
-
]);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
#### 1.2 Server Startup Synchronization
|
|
178
|
-
**File**: `src/services/startupSync.js`
|
|
179
|
-
```javascript
|
|
180
|
-
export async function syncSystemEvents(client, eventManager) {
|
|
181
|
-
console.log('Synchronizing system events...');
|
|
182
|
-
|
|
183
|
-
let processed = 0;
|
|
184
|
-
let hasMore = true;
|
|
185
|
-
|
|
186
|
-
while (hasMore) {
|
|
187
|
-
// Pop and process system events in batches
|
|
188
|
-
const result = await client.pop({
|
|
189
|
-
queue: SYSTEM_QUEUE,
|
|
190
|
-
batch: 100,
|
|
191
|
-
wait: false
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
if (!result.messages || result.messages.length === 0) {
|
|
195
|
-
hasMore = false;
|
|
196
|
-
break;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
for (const message of result.messages) {
|
|
200
|
-
await eventManager.processSystemEvent(message.payload);
|
|
201
|
-
await client.ack(message.transactionId, 'completed');
|
|
202
|
-
processed++;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
console.log(`Synchronized ${processed} system events`);
|
|
207
|
-
return processed;
|
|
208
|
-
}
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
#### 1.3 Resource Cache Integration
|
|
212
|
-
**File**: `src/managers/resourceCache.js` (additions)
|
|
213
|
-
```javascript
|
|
214
|
-
export const createResourceCache = () => {
|
|
215
|
-
// ... existing code ...
|
|
216
|
-
|
|
217
|
-
// Register event handlers
|
|
218
|
-
const registerEventHandlers = (eventManager) => {
|
|
219
|
-
// Invalidate cache on queue changes
|
|
220
|
-
eventManager.on(EventTypes.QUEUE_UPDATED, (event) => {
|
|
221
|
-
invalidateQueue(event.entityId);
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
eventManager.on(EventTypes.QUEUE_DELETED, (event) => {
|
|
225
|
-
invalidateQueue(event.entityId);
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
eventManager.on(EventTypes.PARTITION_CREATED, (event) => {
|
|
229
|
-
invalidate(event.queueName, event.entityId);
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
eventManager.on(EventTypes.PARTITION_DELETED, (event) => {
|
|
233
|
-
invalidate(event.queueName, event.entityId);
|
|
234
|
-
});
|
|
235
|
-
};
|
|
236
|
-
|
|
237
|
-
return {
|
|
238
|
-
// ... existing methods ...
|
|
239
|
-
registerEventHandlers
|
|
240
|
-
};
|
|
241
|
-
};
|
|
242
|
-
```
|
|
243
|
-
|
|
244
|
-
### Phase 2: Queue Manager Integration
|
|
245
|
-
|
|
246
|
-
#### 2.1 Emit Events on Configuration Changes
|
|
247
|
-
**File**: `src/managers/queueManagerOptimized.js` (modifications)
|
|
248
|
-
```javascript
|
|
249
|
-
const configureQueue = async (queueName, options = {}, namespace = null, task = null) => {
|
|
250
|
-
return withTransaction(pool, async (client) => {
|
|
251
|
-
// Check if queue exists (for update vs create detection)
|
|
252
|
-
const existingQueue = await client.query(
|
|
253
|
-
'SELECT * FROM queen.queues WHERE name = $1',
|
|
254
|
-
[queueName]
|
|
255
|
-
);
|
|
256
|
-
const isUpdate = existingQueue.rows.length > 0;
|
|
257
|
-
|
|
258
|
-
// ... existing configuration code ...
|
|
259
|
-
|
|
260
|
-
// Detect what changed
|
|
261
|
-
const changes = {};
|
|
262
|
-
if (isUpdate) {
|
|
263
|
-
const old = existingQueue.rows[0];
|
|
264
|
-
for (const [key, value] of Object.entries(options)) {
|
|
265
|
-
const dbKey = optionMappings[key];
|
|
266
|
-
if (old[dbKey] !== value) {
|
|
267
|
-
changes[key] = { old: old[dbKey], new: value };
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
// Emit appropriate event
|
|
273
|
-
await eventManager.emit(
|
|
274
|
-
isUpdate ? EventTypes.QUEUE_UPDATED : EventTypes.QUEUE_CREATED,
|
|
275
|
-
{
|
|
276
|
-
entityType: 'queue',
|
|
277
|
-
entityId: queueName,
|
|
278
|
-
changes: isUpdate ? changes : options,
|
|
279
|
-
namespace,
|
|
280
|
-
task
|
|
281
|
-
}
|
|
282
|
-
);
|
|
283
|
-
|
|
284
|
-
// Local cache invalidation (immediate)
|
|
285
|
-
resourceCache.invalidateQueue(queueName);
|
|
286
|
-
|
|
287
|
-
return result;
|
|
288
|
-
});
|
|
289
|
-
};
|
|
290
|
-
```
|
|
291
|
-
|
|
292
|
-
### Phase 3: Server Integration
|
|
293
|
-
|
|
294
|
-
#### 3.1 Server Initialization
|
|
295
|
-
**File**: `src/server.js` (modifications)
|
|
296
|
-
```javascript
|
|
297
|
-
import { SystemEventManager, SYSTEM_QUEUE } from './managers/systemEventManager.js';
|
|
298
|
-
import { syncSystemEvents } from './services/startupSync.js';
|
|
299
|
-
|
|
300
|
-
// Generate unique server instance ID
|
|
301
|
-
const SERVER_INSTANCE_ID = `server_${process.pid}_${Date.now()}`;
|
|
302
|
-
|
|
303
|
-
// Initialize system event manager
|
|
304
|
-
const systemEventManager = new SystemEventManager(pool, SERVER_INSTANCE_ID);
|
|
305
|
-
|
|
306
|
-
// Register cache event handlers
|
|
307
|
-
resourceCache.registerEventHandlers(systemEventManager);
|
|
308
|
-
|
|
309
|
-
// Initialize system queue
|
|
310
|
-
async function initializeSystemQueue() {
|
|
311
|
-
try {
|
|
312
|
-
// Direct database operation to create system queue
|
|
313
|
-
await pool.query(`
|
|
314
|
-
INSERT INTO queen.queues (name, ttl, priority, max_queue_size)
|
|
315
|
-
VALUES ($1, 300, 100, 10000)
|
|
316
|
-
ON CONFLICT (name) DO UPDATE SET
|
|
317
|
-
ttl = EXCLUDED.ttl,
|
|
318
|
-
priority = EXCLUDED.priority,
|
|
319
|
-
max_queue_size = EXCLUDED.max_queue_size
|
|
320
|
-
`, [SYSTEM_QUEUE]);
|
|
321
|
-
|
|
322
|
-
await pool.query(`
|
|
323
|
-
INSERT INTO queen.partitions (queue_id, name)
|
|
324
|
-
SELECT id, 'Default' FROM queen.queues WHERE name = $1
|
|
325
|
-
ON CONFLICT (queue_id, name) DO NOTHING
|
|
326
|
-
`, [SYSTEM_QUEUE]);
|
|
327
|
-
} catch (error) {
|
|
328
|
-
console.error('Failed to initialize system queue:', error);
|
|
329
|
-
throw error;
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
// Startup sequence
|
|
334
|
-
async function startServer() {
|
|
335
|
-
console.log('Starting Queen server...');
|
|
336
|
-
|
|
337
|
-
// 1. Initialize database connection
|
|
338
|
-
await testDatabaseConnection();
|
|
339
|
-
|
|
340
|
-
// 2. Initialize system queue
|
|
341
|
-
await initializeSystemQueue();
|
|
342
|
-
|
|
343
|
-
// 3. Create temporary client for synchronization
|
|
344
|
-
const syncClient = createQueenClient({
|
|
345
|
-
baseUrl: `http://localhost:${PORT}`
|
|
346
|
-
});
|
|
347
|
-
|
|
348
|
-
// 4. Synchronize system events (catch up on missed events)
|
|
349
|
-
await syncSystemEvents(syncClient, systemEventManager);
|
|
350
|
-
|
|
351
|
-
// 5. Start consuming system events
|
|
352
|
-
const systemEventConsumer = syncClient.consume({
|
|
353
|
-
queue: SYSTEM_QUEUE,
|
|
354
|
-
consumerGroup: SERVER_INSTANCE_ID,
|
|
355
|
-
handler: async (message) => {
|
|
356
|
-
await systemEventManager.processSystemEvent(message.payload);
|
|
357
|
-
},
|
|
358
|
-
options: {
|
|
359
|
-
batch: 10,
|
|
360
|
-
wait: true
|
|
361
|
-
}
|
|
362
|
-
});
|
|
363
|
-
|
|
364
|
-
// 6. Start HTTP server
|
|
365
|
-
app.listen(PORT, '0.0.0.0', (listenSocket) => {
|
|
366
|
-
if (listenSocket) {
|
|
367
|
-
console.log(`Queen server running on port ${PORT}`);
|
|
368
|
-
console.log(`Server Instance ID: ${SERVER_INSTANCE_ID}`);
|
|
369
|
-
}
|
|
370
|
-
});
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
// Graceful shutdown
|
|
374
|
-
process.on('SIGTERM', async () => {
|
|
375
|
-
console.log('Shutting down...');
|
|
376
|
-
systemEventConsumer?.stop();
|
|
377
|
-
await pool.end();
|
|
378
|
-
process.exit(0);
|
|
379
|
-
});
|
|
380
|
-
```
|
|
381
|
-
|
|
382
|
-
#### 3.2 Bypass Cache for System Queue
|
|
383
|
-
**File**: `src/managers/queueManagerOptimized.js` (modification)
|
|
384
|
-
```javascript
|
|
385
|
-
const ensureResources = async (client, queueName, partitionName = 'Default', namespace = null, task = null) => {
|
|
386
|
-
// CRITICAL: System queues bypass cache completely
|
|
387
|
-
if (queueName.startsWith('__system_')) {
|
|
388
|
-
// Direct database query for system queues
|
|
389
|
-
const result = await client.query(`
|
|
390
|
-
SELECT
|
|
391
|
-
q.id as queue_id,
|
|
392
|
-
q.name as queue_name,
|
|
393
|
-
p.id as partition_id,
|
|
394
|
-
q.*
|
|
395
|
-
FROM queen.queues q
|
|
396
|
-
JOIN queen.partitions p ON p.queue_id = q.id
|
|
397
|
-
WHERE q.name = $1 AND p.name = $2
|
|
398
|
-
`, [queueName, partitionName]);
|
|
399
|
-
|
|
400
|
-
if (result.rows.length === 0) {
|
|
401
|
-
throw new Error(`System queue ${queueName} not found`);
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
const row = result.rows[0];
|
|
405
|
-
return {
|
|
406
|
-
queueId: row.queue_id,
|
|
407
|
-
queueName: row.queue_name,
|
|
408
|
-
partitionId: row.partition_id,
|
|
409
|
-
queueConfig: {
|
|
410
|
-
leaseTime: row.lease_time,
|
|
411
|
-
retryLimit: row.retry_limit,
|
|
412
|
-
// ... other config fields
|
|
413
|
-
},
|
|
414
|
-
encryptionEnabled: false, // System queues never encrypted
|
|
415
|
-
maxWaitTimeSeconds: row.max_wait_time_seconds
|
|
416
|
-
};
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
// ... existing cache logic for regular queues ...
|
|
420
|
-
};
|
|
421
|
-
```
|
|
422
|
-
|
|
423
|
-
## Configuration
|
|
424
|
-
|
|
425
|
-
### Environment Variables
|
|
426
|
-
```bash
|
|
427
|
-
# System event configuration
|
|
428
|
-
QUEEN_SYSTEM_EVENTS_ENABLED=true # Enable system event propagation
|
|
429
|
-
QUEEN_SYSTEM_EVENTS_BATCH_MS=10 # Batching window for events
|
|
430
|
-
QUEEN_SYSTEM_EVENTS_SYNC_TIMEOUT=30000 # Timeout for startup synchronization
|
|
431
|
-
|
|
432
|
-
# Cache configuration (unchanged)
|
|
433
|
-
QUEEN_CACHE_TTL=60000 # Cache TTL when events are enabled
|
|
434
|
-
```
|
|
435
|
-
|
|
436
|
-
## Monitoring
|
|
437
|
-
|
|
438
|
-
### Key Metrics
|
|
439
|
-
```javascript
|
|
440
|
-
// System event metrics
|
|
441
|
-
{
|
|
442
|
-
systemEventsPublished: counter,
|
|
443
|
-
systemEventsProcessed: counter,
|
|
444
|
-
systemEventLag: gauge,
|
|
445
|
-
startupSyncDuration: histogram,
|
|
446
|
-
eventProcessingErrors: counter
|
|
447
|
-
}
|
|
448
|
-
```
|
|
449
|
-
|
|
450
|
-
### Health Checks
|
|
451
|
-
```javascript
|
|
452
|
-
// Add to health endpoint
|
|
453
|
-
async function checkSystemEventHealth() {
|
|
454
|
-
const result = await pool.query(`
|
|
455
|
-
SELECT COUNT(*) as pending
|
|
456
|
-
FROM queen.messages m
|
|
457
|
-
JOIN queen.partitions p ON m.partition_id = p.id
|
|
458
|
-
JOIN queen.queues q ON p.queue_id = q.id
|
|
459
|
-
WHERE q.name = $1
|
|
460
|
-
AND m.status = 'pending'
|
|
461
|
-
`, [SYSTEM_QUEUE]);
|
|
462
|
-
|
|
463
|
-
return {
|
|
464
|
-
systemEventQueueDepth: result.rows[0].pending,
|
|
465
|
-
healthy: result.rows[0].pending < 1000
|
|
466
|
-
};
|
|
467
|
-
}
|
|
468
|
-
```
|
|
469
|
-
|
|
470
|
-
## Migration Plan
|
|
471
|
-
|
|
472
|
-
### Step 1: Deploy with Feature Flag Off
|
|
473
|
-
```bash
|
|
474
|
-
QUEEN_SYSTEM_EVENTS_ENABLED=false
|
|
475
|
-
```
|
|
476
|
-
|
|
477
|
-
### Step 2: Enable and Monitor
|
|
478
|
-
```bash
|
|
479
|
-
QUEEN_SYSTEM_EVENTS_ENABLED=true
|
|
480
|
-
QUEEN_CACHE_TTL=60000 # Re-enable caching
|
|
481
|
-
```
|
|
482
|
-
|
|
483
|
-
### Step 3: Optimize
|
|
484
|
-
- Increase cache TTL once confidence is established
|
|
485
|
-
- Tune batching windows based on event volume
|
|
486
|
-
|
|
487
|
-
## Rollback Plan
|
|
488
|
-
|
|
489
|
-
### Immediate Rollback
|
|
490
|
-
```bash
|
|
491
|
-
# Disable system events
|
|
492
|
-
QUEEN_SYSTEM_EVENTS_ENABLED=false
|
|
493
|
-
QUEEN_CACHE_TTL=0 # Disable cache
|
|
494
|
-
```
|
|
495
|
-
|
|
496
|
-
### Gradual Rollback
|
|
497
|
-
```bash
|
|
498
|
-
# Keep events but reduce cache TTL
|
|
499
|
-
QUEEN_SYSTEM_EVENTS_ENABLED=true
|
|
500
|
-
QUEEN_CACHE_TTL=5000 # 5 second cache
|
|
501
|
-
```
|
|
502
|
-
|
|
503
|
-
## Future Extensions
|
|
504
|
-
|
|
505
|
-
The event system can be extended for:
|
|
506
|
-
- **Audit Logging**: Track all configuration changes
|
|
507
|
-
- **Metrics Collection**: Aggregate queue statistics
|
|
508
|
-
- **Distributed Locks**: Coordinate operations across servers
|
|
509
|
-
- **Leader Election**: Designate primary server for certain operations
|
|
510
|
-
- **Schema Migrations**: Coordinate database updates
|
|
511
|
-
- **Feature Flags**: Propagate feature flag changes
|
|
512
|
-
|
|
513
|
-
## Success Criteria
|
|
514
|
-
|
|
515
|
-
- [ ] System events published for all queue operations
|
|
516
|
-
- [ ] All servers process events and update caches
|
|
517
|
-
- [ ] Startup synchronization completes in < 5 seconds
|
|
518
|
-
- [ ] No circular dependencies with system queue
|
|
519
|
-
- [ ] Cache consistency across all servers within 100ms
|