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.
Files changed (160) hide show
  1. package/API.md +862 -752
  2. package/AUTH.md +2044 -0
  3. package/LICENSE.md +202 -0
  4. package/README.md +1705 -1051
  5. package/WEBAPP.md +1889 -0
  6. package/assets/dashboard-01.png +0 -0
  7. package/assets/queen-logo-blue.svg +210 -0
  8. package/assets/queen-logo-cyan.svg +210 -0
  9. package/assets/queen-logo-indigo.svg +210 -0
  10. package/assets/queen-logo-orange.svg +210 -0
  11. package/assets/queen-logo-pink.svg +210 -0
  12. package/assets/queen-logo-purple.svg +210 -0
  13. package/assets/queen-logo-rose.svg +239 -0
  14. package/assets/queen-logo.svg +263 -0
  15. package/examples/batch-processing.js +58 -0
  16. package/examples/test-complete-client.js +260 -0
  17. package/examples/test-dashboard-api.js +200 -0
  18. package/examples/test-traceid.js +147 -0
  19. package/package.json +17 -4
  20. package/server.log +1 -0
  21. package/src/benchmark/consumer.js +207 -0
  22. package/src/benchmark/consumer_multi.js +216 -0
  23. package/src/benchmark/producer.js +75 -0
  24. package/src/benchmark/producer_multi.js +115 -0
  25. package/src/client/client.js +300 -31
  26. package/src/client/queenClient.js +5 -0
  27. package/src/cluster-server.js +242 -0
  28. package/src/config.js +19 -5
  29. package/src/database/connection.js +42 -16
  30. package/src/database/poolManager.js +7 -0
  31. package/src/database/schema-v2.sql +194 -130
  32. package/src/managers/queueManagerOptimized.js +823 -933
  33. package/src/managers/systemEventManager.js +8 -3
  34. package/src/routes/messages.js +127 -57
  35. package/src/routes/pop.js +27 -43
  36. package/src/routes/resources.js +61 -27
  37. package/src/routes/status.js +1037 -0
  38. package/src/server.js +308 -272
  39. package/src/services/evictionService.js +57 -28
  40. package/src/services/retentionService.js +44 -11
  41. package/src/test/MIGRATION_ISSUES.md +174 -0
  42. package/src/test/README.md +203 -0
  43. package/src/test/advanced-pattern-tests.js +1137 -0
  44. package/src/test/bus-mode-tests.js +361 -0
  45. package/src/test/core-tests.js +342 -0
  46. package/src/test/edge-case-tests.js +561 -0
  47. package/src/test/enterprise-tests.js +637 -0
  48. package/src/test/partition-locking-tests.js +545 -0
  49. package/src/test/test-new.js +278 -0
  50. package/src/test/test.js +6 -3
  51. package/src/test/utils.js +169 -0
  52. package/src/utils/streaming.js +231 -0
  53. package/src/utils/uuid.js +2 -2
  54. package/src/websocket/wsServer.js +10 -3
  55. package/test-keepalive-v2.sh +22 -0
  56. package/webapp/COLOR_GUIDE.md +118 -0
  57. package/webapp/README.md +143 -0
  58. package/webapp/index.html +14 -0
  59. package/webapp/package-lock.json +3184 -0
  60. package/webapp/package.json +25 -0
  61. package/webapp/postcss.config.js +7 -0
  62. package/webapp/public/assets/queen-logo-blue.svg +210 -0
  63. package/webapp/public/assets/queen-logo-cyan.svg +210 -0
  64. package/webapp/public/assets/queen-logo-indigo.svg +210 -0
  65. package/webapp/public/assets/queen-logo-orange.svg +210 -0
  66. package/webapp/public/assets/queen-logo-pink.svg +210 -0
  67. package/webapp/public/assets/queen-logo-purple.svg +210 -0
  68. package/webapp/public/assets/queen-logo-rose.svg +239 -0
  69. package/webapp/public/assets/queen-logo.svg +263 -0
  70. package/webapp/src/App.vue +19 -0
  71. package/webapp/src/api/analytics.js +10 -0
  72. package/webapp/src/api/client.js +29 -0
  73. package/webapp/src/api/consumers.js +52 -0
  74. package/webapp/src/api/health.js +7 -0
  75. package/webapp/src/api/messages.js +26 -0
  76. package/webapp/src/api/queues.js +14 -0
  77. package/webapp/src/api/resources.js +8 -0
  78. package/webapp/src/assets/styles/main.css +357 -0
  79. package/webapp/src/components/analytics/AnalyticsFilters.vue +87 -0
  80. package/webapp/src/components/analytics/AnalyticsMetrics.vue +57 -0
  81. package/webapp/src/components/analytics/MessageDistributionChart.vue +111 -0
  82. package/webapp/src/components/analytics/MessageFlowChart.vue +173 -0
  83. package/webapp/src/components/analytics/TimeRangeSelector.vue +27 -0
  84. package/webapp/src/components/analytics/TopQueuesChart.vue +132 -0
  85. package/webapp/src/components/common/ConfirmDialog.vue +56 -0
  86. package/webapp/src/components/common/LoadingSpinner.vue +6 -0
  87. package/webapp/src/components/common/MetricCard.vue +43 -0
  88. package/webapp/src/components/common/StatusBadge.vue +45 -0
  89. package/webapp/src/components/dashboard/MessageStatusCard.vue +50 -0
  90. package/webapp/src/components/dashboard/PerformanceCard.vue +38 -0
  91. package/webapp/src/components/dashboard/ThroughputChart.vue +182 -0
  92. package/webapp/src/components/dashboard/TopQueuesTable.vue +53 -0
  93. package/webapp/src/components/layout/AppLayout.vue +110 -0
  94. package/webapp/src/components/layout/AppSidebar.vue +304 -0
  95. package/webapp/src/components/messages/MessageDetailPanel.vue +242 -0
  96. package/webapp/src/components/messages/MessageFilters.vue +114 -0
  97. package/webapp/src/components/queue-detail/PartitionList.vue +79 -0
  98. package/webapp/src/components/queue-detail/PushMessageModal.vue +175 -0
  99. package/webapp/src/components/queue-detail/QueueConfig.vue +63 -0
  100. package/webapp/src/components/queue-detail/QueueDetailHeader.vue +53 -0
  101. package/webapp/src/components/queue-detail/RecentMessages.vue +76 -0
  102. package/webapp/src/components/queues/CreateQueueModal.vue +193 -0
  103. package/webapp/src/components/queues/QueueFilters.vue +90 -0
  104. package/webapp/src/composables/useApi.js +34 -0
  105. package/webapp/src/composables/useTheme.js +36 -0
  106. package/webapp/src/main.js +11 -0
  107. package/webapp/src/router/index.js +42 -0
  108. package/webapp/src/utils/colors.js +96 -0
  109. package/webapp/src/utils/formatters.js +49 -0
  110. package/webapp/src/views/Analytics.vue +377 -0
  111. package/webapp/src/views/ConsumerGroups.vue +433 -0
  112. package/webapp/src/views/Dashboard.vue +418 -0
  113. package/webapp/src/views/Messages.vue +361 -0
  114. package/webapp/src/views/QueueDetail.vue +582 -0
  115. package/webapp/src/views/Queues.vue +496 -0
  116. package/webapp/tailwind.config.js +25 -0
  117. package/webapp/vite.config.js +10 -0
  118. package/CACHE.md +0 -519
  119. package/DASHBOARD-V3.md +0 -478
  120. package/DASHBOARD.md +0 -382
  121. package/MOD_QUEUE.md +0 -453
  122. package/PARTITION_LOCKING_DESIGN.md +0 -989
  123. package/PLAN.md +0 -707
  124. package/QUERY_ANALSYS.md +0 -72
  125. package/QUEUE_BUS.md +0 -334
  126. package/V2-PLAN.md +0 -236
  127. package/dashboard/.vscode/extensions.json +0 -3
  128. package/dashboard/README.md +0 -5
  129. package/dashboard/index.html +0 -14
  130. package/dashboard/package-lock.json +0 -1458
  131. package/dashboard/package.json +0 -25
  132. package/dashboard/public/vite.svg +0 -1
  133. package/dashboard/src/App.vue +0 -29
  134. package/dashboard/src/assets/styles/main.css +0 -908
  135. package/dashboard/src/assets/vue.svg +0 -1
  136. package/dashboard/src/components/cards/MetricCard.vue +0 -298
  137. package/dashboard/src/components/charts/QueueDepthChart.vue +0 -276
  138. package/dashboard/src/components/charts/QueueLagChart.vue +0 -436
  139. package/dashboard/src/components/charts/ThroughputChart.vue +0 -302
  140. package/dashboard/src/components/common/ActivityFeed.vue +0 -251
  141. package/dashboard/src/components/layout/AppHeader.vue +0 -208
  142. package/dashboard/src/components/layout/AppLayout.vue +0 -88
  143. package/dashboard/src/components/layout/AppSidebar.vue +0 -261
  144. package/dashboard/src/main.js +0 -44
  145. package/dashboard/src/router.js +0 -54
  146. package/dashboard/src/services/api.js +0 -187
  147. package/dashboard/src/services/websocket.js +0 -167
  148. package/dashboard/src/utils/constants.js +0 -56
  149. package/dashboard/src/utils/helpers.js +0 -118
  150. package/dashboard/src/views/Analytics.vue +0 -912
  151. package/dashboard/src/views/Dashboard.vue +0 -906
  152. package/dashboard/src/views/Messages.vue +0 -437
  153. package/dashboard/src/views/QueueDetail.vue +0 -501
  154. package/dashboard/src/views/Queues.vue +0 -333
  155. package/dashboard/vite.config.js +0 -30
  156. package/debug-namespace.js +0 -110
  157. package/docs/long-polling.md +0 -159
  158. package/docs/multi-server-cache-solutions.md +0 -185
  159. package/docs/performance-tuning.md +0 -222
  160. package/src/routes/analytics.js +0 -812
@@ -1,436 +0,0 @@
1
- <template>
2
- <div class="queue-lag-chart">
3
- <div class="chart-header">
4
- <h3 class="chart-title">Queue Lag Analysis</h3>
5
- <div class="chart-controls">
6
- <button @click="refreshData" class="refresh-btn" :disabled="loading">
7
- <i class="pi pi-refresh" :class="{ 'pi-spin': loading }"></i>
8
- </button>
9
- </div>
10
- </div>
11
-
12
- <div v-if="loading" class="loading-state">
13
- <i class="pi pi-spinner pi-spin"></i>
14
- <span>Loading lag data...</span>
15
- </div>
16
-
17
- <div v-else-if="error" class="error-state">
18
- <i class="pi pi-exclamation-triangle"></i>
19
- <span>{{ error }}</span>
20
- </div>
21
-
22
- <div v-else-if="!lagData || lagData.length === 0" class="empty-state">
23
- <i class="pi pi-info-circle"></i>
24
- <span>No lag data available. Queues need completed messages to calculate lag.</span>
25
- </div>
26
-
27
- <div v-else class="lag-content">
28
- <!-- Lag Bar Chart -->
29
- <div class="lag-chart-container">
30
- <div class="chart-section">
31
- <h4 class="section-title">{{ getMetricLabel() }} by Queue</h4>
32
- <div class="bar-chart">
33
- <div v-for="queue in lagData" :key="queue.queue" class="bar-item">
34
- <div class="bar-label">{{ queue.queue }}</div>
35
- <div class="bar-container">
36
- <div
37
- class="bar-fill"
38
- :class="getLagSeverity(queue)"
39
- :style="{ width: getBarWidth(queue) + '%' }"
40
- ></div>
41
- <span class="bar-value">{{ getMetricValue(queue) }}</span>
42
- </div>
43
- <div class="bar-details">
44
- <span class="backlog-count">{{ queue.totals.totalBacklog }} backlog</span>
45
- <span class="processing-time">{{ queue.totals.avgProcessingTime }} avg</span>
46
- </div>
47
- </div>
48
- </div>
49
- </div>
50
-
51
- <!-- Processing Time Chart -->
52
- <div class="chart-section">
53
- <h4 class="section-title">Average Processing Time</h4>
54
- <div class="bar-chart">
55
- <div v-for="queue in lagData" :key="`processing-${queue.queue}`" class="bar-item">
56
- <div class="bar-label">{{ queue.queue }}</div>
57
- <div class="bar-container">
58
- <div
59
- class="bar-fill processing-time-bar"
60
- :style="{ width: getProcessingTimeBarWidth(queue) + '%' }"
61
- ></div>
62
- <span class="bar-value">{{ queue.totals.avgProcessingTime }}</span>
63
- </div>
64
- <div class="bar-details">
65
- <span class="completed-count">{{ queue.totals.completedMessages }} completed (24h)</span>
66
- </div>
67
- </div>
68
- </div>
69
- </div>
70
- </div>
71
-
72
- <!-- Detailed Table -->
73
- <div class="lag-table-container">
74
- <table class="lag-table dark-table">
75
- <thead>
76
- <tr>
77
- <th>Queue</th>
78
- <th>Partition</th>
79
- <th>Pending</th>
80
- <th>Processing</th>
81
- <th>Total Backlog</th>
82
- <th>Avg Processing Time</th>
83
- <th>{{ getMetricLabel() }}</th>
84
- <th>Completed (24h)</th>
85
- </tr>
86
- </thead>
87
- <tbody>
88
- <template v-for="queue in lagData" :key="queue.queue">
89
- <tr v-for="partition in queue.partitions" :key="`${queue.queue}-${partition.name}`">
90
- <td>{{ queue.queue }}</td>
91
- <td>{{ partition.name }}</td>
92
- <td>{{ partition.stats.pendingCount }}</td>
93
- <td>{{ partition.stats.processingCount }}</td>
94
- <td>{{ partition.stats.totalBacklog }}</td>
95
- <td>{{ partition.stats.avgProcessingTime }}</td>
96
- <td :class="getPartitionLagSeverity(partition)">
97
- {{ getPartitionMetricValue(partition) }}
98
- </td>
99
- <td>{{ partition.stats.completedMessages }}</td>
100
- </tr>
101
- </template>
102
- </tbody>
103
- </table>
104
- </div>
105
- </div>
106
- </div>
107
- </template>
108
-
109
- <script setup>
110
- import { ref, onMounted, computed } from 'vue'
111
- import api from '../../services/api.js'
112
-
113
- // Reactive data
114
- const lagData = ref([])
115
- const loading = ref(false)
116
- const error = ref(null)
117
-
118
- // Methods
119
- const refreshData = async () => {
120
- loading.value = true
121
- error.value = null
122
-
123
- try {
124
- const response = await api.getQueueLag()
125
- lagData.value = response.queues || []
126
- } catch (err) {
127
- console.error('Failed to fetch queue lag data:', err)
128
- error.value = err.message || 'Failed to load lag data'
129
- } finally {
130
- loading.value = false
131
- }
132
- }
133
-
134
- const getMetricLabel = () => {
135
- return 'Estimated Lag'
136
- }
137
-
138
- const getMetricValue = (queue) => {
139
- return queue.totals.estimatedLag
140
- }
141
-
142
- const getPartitionMetricValue = (partition) => {
143
- return partition.stats.estimatedLag
144
- }
145
-
146
- const getLagSeverity = (queue) => {
147
- const seconds = queue.totals.estimatedLagSeconds
148
-
149
- if (seconds === 0) return 'lag-none'
150
- if (seconds < 60) return 'lag-low'
151
- if (seconds < 300) return 'lag-medium'
152
- if (seconds < 1800) return 'lag-high'
153
- return 'lag-critical'
154
- }
155
-
156
- const getPartitionLagSeverity = (partition) => {
157
- const seconds = partition.stats.estimatedLagSeconds
158
-
159
- if (seconds === 0) return 'lag-none'
160
- if (seconds < 60) return 'lag-low'
161
- if (seconds < 300) return 'lag-medium'
162
- if (seconds < 1800) return 'lag-high'
163
- return 'lag-critical'
164
- }
165
-
166
- const getBarWidth = (queue) => {
167
- if (!lagData.value || lagData.value.length === 0) return 0
168
-
169
- const maxLagSeconds = Math.max(...lagData.value.map(q => q.totals.estimatedLagSeconds))
170
-
171
- if (maxLagSeconds === 0) return 0
172
-
173
- const currentLagSeconds = queue.totals.estimatedLagSeconds
174
-
175
- return Math.max((currentLagSeconds / maxLagSeconds) * 100, 2) // Minimum 2% for visibility
176
- }
177
-
178
- const getProcessingTimeBarWidth = (queue) => {
179
- if (!lagData.value || lagData.value.length === 0) return 0
180
-
181
- const maxProcessingTime = Math.max(...lagData.value.map(q => q.totals.avgProcessingTimeSeconds))
182
-
183
- if (maxProcessingTime === 0) return 0
184
-
185
- return Math.max((queue.totals.avgProcessingTimeSeconds / maxProcessingTime) * 100, 2)
186
- }
187
-
188
- // Lifecycle
189
- onMounted(() => {
190
- refreshData()
191
- })
192
- </script>
193
-
194
- <style scoped>
195
- .queue-lag-chart {
196
- background: transparent;
197
- border-radius: 8px;
198
- padding: 1.5rem;
199
- position: relative;
200
- z-index: 2;
201
- }
202
-
203
- .chart-header {
204
- display: flex;
205
- justify-content: space-between;
206
- align-items: center;
207
- margin-bottom: 1.5rem;
208
- }
209
-
210
- .chart-title {
211
- margin: 0;
212
- color: #ffffff;
213
- font-size: 1.25rem;
214
- font-weight: 600;
215
- }
216
-
217
- .chart-controls {
218
- display: flex;
219
- gap: 0.75rem;
220
- align-items: center;
221
- }
222
-
223
-
224
- .refresh-btn {
225
- padding: 0.5rem;
226
- border: 1px solid rgba(255, 255, 255, 0.3);
227
- border-radius: 4px;
228
- background: rgba(255, 255, 255, 0.1);
229
- color: #ffffff;
230
- cursor: pointer;
231
- transition: all 0.2s;
232
- }
233
-
234
- .refresh-btn:hover:not(:disabled) {
235
- background: rgba(236, 72, 153, 0.1);
236
- border-color: rgba(236, 72, 153, 0.3);
237
- }
238
-
239
- .refresh-btn:disabled {
240
- opacity: 0.6;
241
- cursor: not-allowed;
242
- }
243
-
244
- .loading-state,
245
- .error-state,
246
- .empty-state {
247
- display: flex;
248
- align-items: center;
249
- justify-content: center;
250
- gap: 0.5rem;
251
- padding: 2rem;
252
- color: #a1a1aa;
253
- font-style: italic;
254
- }
255
-
256
- .error-state {
257
- color: #ef4444;
258
- }
259
-
260
- .lag-content {
261
- padding: 0;
262
- }
263
-
264
- .lag-chart-container {
265
- display: grid;
266
- grid-template-columns: 1fr 1fr;
267
- gap: 2rem;
268
- margin-bottom: 2rem;
269
- }
270
-
271
- .chart-section {
272
- background: #0a0a0a;
273
- border: 1px solid rgba(255, 255, 255, 0.1);
274
- border-radius: 8px;
275
- padding: 1.5rem;
276
- }
277
-
278
- .section-title {
279
- margin: 0 0 1rem 0;
280
- color: #e4e4e7;
281
- font-size: 1rem;
282
- font-weight: 500;
283
- }
284
-
285
- .bar-chart {
286
- display: flex;
287
- flex-direction: column;
288
- gap: 1rem;
289
- }
290
-
291
- .bar-item {
292
- display: flex;
293
- flex-direction: column;
294
- gap: 0.5rem;
295
- }
296
-
297
- .bar-label {
298
- font-size: 0.875rem;
299
- color: #d4d4d8;
300
- font-weight: 500;
301
- }
302
-
303
- .bar-container {
304
- position: relative;
305
- height: 24px;
306
- background: #2a2a2a;
307
- border-radius: 4px;
308
- display: flex;
309
- align-items: center;
310
- overflow: hidden;
311
- }
312
-
313
- .bar-fill {
314
- height: 100%;
315
- border-radius: 4px;
316
- transition: width 0.3s ease;
317
- position: relative;
318
- }
319
-
320
- .processing-time-bar {
321
- background: linear-gradient(90deg, rgba(59, 130, 246, 0.6), rgba(59, 130, 246, 0.8));
322
- }
323
-
324
- .bar-value {
325
- position: absolute;
326
- right: 8px;
327
- font-size: 0.75rem;
328
- color: #ffffff;
329
- font-weight: 600;
330
- z-index: 2;
331
- text-shadow: 0 1px 2px rgba(0, 0, 0, 0.8);
332
- }
333
-
334
- .bar-details {
335
- display: flex;
336
- gap: 1rem;
337
- font-size: 0.75rem;
338
- color: #a1a1aa;
339
- }
340
-
341
- .lag-table-container {
342
- overflow-x: auto;
343
- background: #0a0a0a;
344
- border: 1px solid rgba(255, 255, 255, 0.1);
345
- border-radius: 8px;
346
- }
347
-
348
- .dark-table {
349
- width: 100%;
350
- border-collapse: collapse;
351
- font-size: 0.875rem;
352
- }
353
-
354
- .dark-table th,
355
- .dark-table td {
356
- padding: 0.75rem;
357
- text-align: left;
358
- border-bottom: 1px solid rgba(255, 255, 255, 0.1);
359
- }
360
-
361
- .dark-table th {
362
- background: #0a0a0a;
363
- font-weight: 600;
364
- color: #d4d4d8;
365
- font-size: 0.8rem;
366
- text-transform: uppercase;
367
- letter-spacing: 0.5px;
368
- }
369
-
370
- .dark-table td {
371
- color: #e4e4e7;
372
- }
373
-
374
- .dark-table tbody tr:hover {
375
- background: rgba(236, 72, 153, 0.05);
376
- }
377
-
378
- /* Lag severity colors */
379
- .lag-none {
380
- color: #10b981;
381
- background: linear-gradient(90deg, rgba(16, 185, 129, 0.2), rgba(16, 185, 129, 0.4));
382
- }
383
-
384
- .lag-low {
385
- color: #06b6d4;
386
- background: linear-gradient(90deg, rgba(6, 182, 212, 0.2), rgba(6, 182, 212, 0.4));
387
- }
388
-
389
- .lag-medium {
390
- color: #f59e0b;
391
- background: linear-gradient(90deg, rgba(245, 158, 11, 0.2), rgba(245, 158, 11, 0.4));
392
- }
393
-
394
- .lag-high {
395
- color: #f97316;
396
- background: linear-gradient(90deg, rgba(249, 115, 22, 0.2), rgba(249, 115, 22, 0.4));
397
- }
398
-
399
- .lag-critical {
400
- color: #ef4444;
401
- background: linear-gradient(90deg, rgba(239, 68, 68, 0.2), rgba(239, 68, 68, 0.4));
402
- font-weight: 600;
403
- }
404
-
405
- @media (max-width: 1024px) {
406
- .lag-chart-container {
407
- grid-template-columns: 1fr;
408
- gap: 1.5rem;
409
- }
410
- }
411
-
412
- @media (max-width: 768px) {
413
- .chart-header {
414
- flex-direction: column;
415
- gap: 1rem;
416
- align-items: stretch;
417
- }
418
-
419
- .chart-controls {
420
- justify-content: center;
421
- }
422
-
423
- .chart-section {
424
- padding: 1rem;
425
- }
426
-
427
- .lag-table-container {
428
- font-size: 0.8rem;
429
- }
430
-
431
- .dark-table th,
432
- .dark-table td {
433
- padding: 0.5rem;
434
- }
435
- }
436
- </style>