queen-mq 0.1.1 → 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 (139) hide show
  1. package/API.md +1226 -0
  2. package/AUTH.md +2044 -0
  3. package/LICENSE.md +202 -0
  4. package/README.md +276 -53
  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-dashboard-api.js +200 -0
  17. package/package.json +4 -2
  18. package/server.log +1 -0
  19. package/src/benchmark/consumer.js +207 -0
  20. package/src/benchmark/consumer_multi.js +216 -0
  21. package/src/benchmark/producer.js +75 -0
  22. package/src/benchmark/producer_multi.js +115 -0
  23. package/src/client/client.js +192 -16
  24. package/src/client/queenClient.js +5 -0
  25. package/src/cluster-server.js +242 -0
  26. package/src/config.js +19 -5
  27. package/src/database/connection.js +42 -16
  28. package/src/database/poolManager.js +7 -0
  29. package/src/database/schema-v2.sql +194 -130
  30. package/src/managers/queueManagerOptimized.js +823 -933
  31. package/src/managers/systemEventManager.js +8 -3
  32. package/src/routes/messages.js +127 -57
  33. package/src/routes/pop.js +27 -43
  34. package/src/routes/resources.js +61 -27
  35. package/src/routes/status.js +1037 -0
  36. package/src/server.js +308 -272
  37. package/src/services/evictionService.js +57 -28
  38. package/src/services/retentionService.js +44 -11
  39. package/src/test/advanced-pattern-tests.js +5 -5
  40. package/src/test/bus-mode-tests.js +24 -11
  41. package/src/test/edge-case-tests.js +12 -5
  42. package/src/test/enterprise-tests.js +48 -15
  43. package/src/test/utils.js +1 -1
  44. package/src/utils/streaming.js +231 -0
  45. package/src/utils/uuid.js +2 -2
  46. package/src/websocket/wsServer.js +10 -3
  47. package/test-keepalive-v2.sh +22 -0
  48. package/webapp/COLOR_GUIDE.md +118 -0
  49. package/webapp/README.md +143 -0
  50. package/webapp/index.html +14 -0
  51. package/webapp/package-lock.json +3184 -0
  52. package/webapp/package.json +25 -0
  53. package/webapp/postcss.config.js +7 -0
  54. package/webapp/public/assets/queen-logo-blue.svg +210 -0
  55. package/webapp/public/assets/queen-logo-cyan.svg +210 -0
  56. package/webapp/public/assets/queen-logo-indigo.svg +210 -0
  57. package/webapp/public/assets/queen-logo-orange.svg +210 -0
  58. package/webapp/public/assets/queen-logo-pink.svg +210 -0
  59. package/webapp/public/assets/queen-logo-purple.svg +210 -0
  60. package/webapp/public/assets/queen-logo-rose.svg +239 -0
  61. package/webapp/public/assets/queen-logo.svg +263 -0
  62. package/webapp/src/App.vue +19 -0
  63. package/webapp/src/api/analytics.js +10 -0
  64. package/webapp/src/api/client.js +29 -0
  65. package/webapp/src/api/consumers.js +52 -0
  66. package/webapp/src/api/health.js +7 -0
  67. package/webapp/src/api/messages.js +26 -0
  68. package/webapp/src/api/queues.js +14 -0
  69. package/webapp/src/api/resources.js +8 -0
  70. package/webapp/src/assets/styles/main.css +357 -0
  71. package/webapp/src/components/analytics/AnalyticsFilters.vue +87 -0
  72. package/webapp/src/components/analytics/AnalyticsMetrics.vue +57 -0
  73. package/webapp/src/components/analytics/MessageDistributionChart.vue +111 -0
  74. package/webapp/src/components/analytics/MessageFlowChart.vue +173 -0
  75. package/webapp/src/components/analytics/TimeRangeSelector.vue +27 -0
  76. package/webapp/src/components/analytics/TopQueuesChart.vue +132 -0
  77. package/webapp/src/components/common/ConfirmDialog.vue +56 -0
  78. package/webapp/src/components/common/LoadingSpinner.vue +6 -0
  79. package/webapp/src/components/common/MetricCard.vue +43 -0
  80. package/webapp/src/components/common/StatusBadge.vue +45 -0
  81. package/webapp/src/components/dashboard/MessageStatusCard.vue +50 -0
  82. package/webapp/src/components/dashboard/PerformanceCard.vue +38 -0
  83. package/webapp/src/components/dashboard/ThroughputChart.vue +182 -0
  84. package/webapp/src/components/dashboard/TopQueuesTable.vue +53 -0
  85. package/webapp/src/components/layout/AppLayout.vue +110 -0
  86. package/webapp/src/components/layout/AppSidebar.vue +304 -0
  87. package/webapp/src/components/messages/MessageDetailPanel.vue +242 -0
  88. package/webapp/src/components/messages/MessageFilters.vue +114 -0
  89. package/webapp/src/components/queue-detail/PartitionList.vue +79 -0
  90. package/webapp/src/components/queue-detail/PushMessageModal.vue +175 -0
  91. package/webapp/src/components/queue-detail/QueueConfig.vue +63 -0
  92. package/webapp/src/components/queue-detail/QueueDetailHeader.vue +53 -0
  93. package/webapp/src/components/queue-detail/RecentMessages.vue +76 -0
  94. package/webapp/src/components/queues/CreateQueueModal.vue +193 -0
  95. package/webapp/src/components/queues/QueueFilters.vue +90 -0
  96. package/webapp/src/composables/useApi.js +34 -0
  97. package/webapp/src/composables/useTheme.js +36 -0
  98. package/webapp/src/main.js +11 -0
  99. package/webapp/src/router/index.js +42 -0
  100. package/webapp/src/utils/colors.js +96 -0
  101. package/webapp/src/utils/formatters.js +49 -0
  102. package/webapp/src/views/Analytics.vue +377 -0
  103. package/webapp/src/views/ConsumerGroups.vue +433 -0
  104. package/webapp/src/views/Dashboard.vue +418 -0
  105. package/webapp/src/views/Messages.vue +361 -0
  106. package/webapp/src/views/QueueDetail.vue +582 -0
  107. package/webapp/src/views/Queues.vue +496 -0
  108. package/webapp/tailwind.config.js +25 -0
  109. package/webapp/vite.config.js +10 -0
  110. package/dashboard/.vscode/extensions.json +0 -3
  111. package/dashboard/README.md +0 -5
  112. package/dashboard/index.html +0 -14
  113. package/dashboard/package-lock.json +0 -1458
  114. package/dashboard/package.json +0 -25
  115. package/dashboard/public/vite.svg +0 -1
  116. package/dashboard/src/App.vue +0 -29
  117. package/dashboard/src/assets/styles/main.css +0 -908
  118. package/dashboard/src/assets/vue.svg +0 -1
  119. package/dashboard/src/components/cards/MetricCard.vue +0 -298
  120. package/dashboard/src/components/charts/QueueDepthChart.vue +0 -276
  121. package/dashboard/src/components/charts/QueueLagChart.vue +0 -436
  122. package/dashboard/src/components/charts/ThroughputChart.vue +0 -302
  123. package/dashboard/src/components/common/ActivityFeed.vue +0 -251
  124. package/dashboard/src/components/layout/AppHeader.vue +0 -208
  125. package/dashboard/src/components/layout/AppLayout.vue +0 -88
  126. package/dashboard/src/components/layout/AppSidebar.vue +0 -261
  127. package/dashboard/src/main.js +0 -44
  128. package/dashboard/src/router.js +0 -54
  129. package/dashboard/src/services/api.js +0 -187
  130. package/dashboard/src/services/websocket.js +0 -167
  131. package/dashboard/src/utils/constants.js +0 -56
  132. package/dashboard/src/utils/helpers.js +0 -118
  133. package/dashboard/src/views/Analytics.vue +0 -912
  134. package/dashboard/src/views/Dashboard.vue +0 -906
  135. package/dashboard/src/views/Messages.vue +0 -437
  136. package/dashboard/src/views/QueueDetail.vue +0 -501
  137. package/dashboard/src/views/Queues.vue +0 -333
  138. package/dashboard/vite.config.js +0 -30
  139. package/src/routes/analytics.js +0 -812
@@ -1,437 +0,0 @@
1
- <template>
2
- <div class="messages-view">
3
- <Card class="messages-card">
4
- <template #content>
5
- <DataTable
6
- :value="messages"
7
- :loading="loading"
8
- :paginator="true"
9
- :rows="20"
10
- :rowsPerPageOptions="[20, 50, 100]"
11
- responsiveLayout="scroll"
12
- class="dark-table-v3"
13
- >
14
- <template #header>
15
- <div class="table-header">
16
- <h2>Message Browser</h2>
17
- <div class="table-actions">
18
- <Select
19
- v-model="selectedQueue"
20
- :options="queues || []"
21
- optionLabel="name"
22
- optionValue="name"
23
- placeholder="Select Queue"
24
- class="queue-dropdown"
25
- @change="fetchMessages"
26
- />
27
- <Select
28
- v-model="selectedStatus"
29
- :options="statusOptions"
30
- optionLabel="label"
31
- optionValue="value"
32
- placeholder="Status"
33
- class="status-dropdown"
34
- @change="fetchMessages"
35
- />
36
- <Button
37
- icon="pi pi-refresh"
38
- @click="fetchMessages"
39
- :loading="loading"
40
- class="p-button-text"
41
- v-tooltip="'Refresh'"
42
- />
43
- </div>
44
- </div>
45
- </template>
46
-
47
- <Column field="transactionId" header="Transaction ID">
48
- <template #body="{ data }">
49
- <span class="transaction-id">{{ data.transactionId.substring(0, 8) }}...</span>
50
- </template>
51
- </Column>
52
-
53
- <Column field="queue" header="Queue">
54
- <template #body="{ data }">
55
- <div class="queue-name-cell">
56
- <div class="queue-icon-small">Q</div>
57
- <span>{{ data.queue }}</span>
58
- </div>
59
- </template>
60
- </Column>
61
-
62
- <Column field="status" header="Status">
63
- <template #body="{ data }">
64
- <span :class="`status-${data.status}`">{{ data.status }}</span>
65
- </template>
66
- </Column>
67
-
68
- <Column field="created" header="Created">
69
- <template #body="{ data }">
70
- <span class="timestamp">{{ formatDate(data.created) }}</span>
71
- </template>
72
- </Column>
73
-
74
- <Column field="attempts" header="Attempts">
75
- <template #body="{ data }">
76
- <Tag :value="data.attempts || 0" :severity="getAttemptSeverity(data.attempts)" />
77
- </template>
78
- </Column>
79
-
80
- <Column header="Actions" :exportable="false">
81
- <template #body="{ data }">
82
- <Button
83
- icon="pi pi-eye"
84
- class="p-button-text p-button-sm action-btn"
85
- @click="viewMessage(data)"
86
- v-tooltip="'View Details'"
87
- />
88
- <Button
89
- icon="pi pi-replay"
90
- class="p-button-text p-button-sm action-btn"
91
- @click="retryMessage(data)"
92
- v-tooltip="'Retry'"
93
- :disabled="data.status !== 'failed'"
94
- />
95
- </template>
96
- </Column>
97
- </DataTable>
98
- </template>
99
- </Card>
100
-
101
- <!-- Message Detail Dialog -->
102
- <Dialog
103
- v-model:visible="showDetail"
104
- :header="`Message: ${selectedMessage?.transactionId}`"
105
- :style="{ width: '50vw' }"
106
- :modal="true"
107
- class="message-dialog"
108
- >
109
- <div v-if="selectedMessage" class="message-detail">
110
- <div class="detail-row">
111
- <span class="detail-label">Transaction ID:</span>
112
- <span class="detail-value">{{ selectedMessage.transactionId }}</span>
113
- </div>
114
- <div class="detail-row">
115
- <span class="detail-label">Queue:</span>
116
- <span class="detail-value">{{ selectedMessage.queue }}</span>
117
- </div>
118
- <div class="detail-row">
119
- <span class="detail-label">Status:</span>
120
- <span :class="`status-${selectedMessage.status}`">{{ selectedMessage.status }}</span>
121
- </div>
122
- <div class="detail-row">
123
- <span class="detail-label">Created:</span>
124
- <span class="detail-value">{{ formatDate(selectedMessage.created) }}</span>
125
- </div>
126
- <div class="detail-row">
127
- <span class="detail-label">Payload:</span>
128
- </div>
129
- <pre class="payload-viewer">{{ JSON.stringify(selectedMessage.payload, null, 2) }}</pre>
130
- </div>
131
- </Dialog>
132
- </div>
133
- </template>
134
-
135
- <script setup>
136
- import { ref, onMounted } from 'vue'
137
- import { useToast } from 'primevue/usetoast'
138
- import DataTable from 'primevue/datatable'
139
- import Column from 'primevue/column'
140
- import Button from 'primevue/button'
141
- import Select from 'primevue/select'
142
- import Tag from 'primevue/tag'
143
- import Card from 'primevue/card'
144
- import Dialog from 'primevue/dialog'
145
- import api from '../services/api.js'
146
-
147
- const toast = useToast()
148
- const loading = ref(false)
149
- const messages = ref([])
150
- const queues = ref([])
151
- const selectedQueue = ref(null)
152
- const selectedStatus = ref(null)
153
- const selectedMessage = ref(null)
154
- const showDetail = ref(false)
155
-
156
- const statusOptions = [
157
- { label: 'All', value: null },
158
- { label: 'Pending', value: 'pending' },
159
- { label: 'Processing', value: 'processing' },
160
- { label: 'Completed', value: 'completed' },
161
- { label: 'Failed', value: 'failed' },
162
- { label: 'Dead Letter', value: 'dead_letter' }
163
- ]
164
-
165
- const fetchQueues = async () => {
166
- try {
167
- const data = await api.getQueues()
168
- queues.value = data.queues || []
169
- } catch (error) {
170
- console.error('Failed to fetch queues:', error)
171
- }
172
- }
173
-
174
- const fetchMessages = async () => {
175
- try {
176
- loading.value = true
177
-
178
- // Build API parameters
179
- const params = {}
180
- if (selectedQueue.value) {
181
- params.queue = selectedQueue.value
182
- }
183
- if (selectedStatus.value) {
184
- params.status = selectedStatus.value
185
- }
186
-
187
- // Fetch real messages from API
188
- const data = await api.getMessages(params)
189
-
190
- if (data && Array.isArray(data.messages)) {
191
- // Process real API data
192
- messages.value = data.messages.map(message => ({
193
- transactionId: message.transactionId || message.id,
194
- queue: message.queue,
195
- status: message.status,
196
- created: message.createdAt || message.created,
197
- attempts: message.attempts || message.retryCount || 0,
198
- payload: message.payload || message.data || {}
199
- }))
200
- } else if (data && Array.isArray(data)) {
201
- // Handle if API returns array directly
202
- messages.value = data.map(message => ({
203
- transactionId: message.transactionId || message.id,
204
- queue: message.queue,
205
- status: message.status,
206
- created: message.createdAt || message.created,
207
- attempts: message.attempts || message.retryCount || 0,
208
- payload: message.payload || message.data || {}
209
- }))
210
- } else {
211
- // No data available
212
- messages.value = []
213
- }
214
-
215
- } catch (error) {
216
- console.error('Failed to fetch messages:', error)
217
- toast.add({
218
- severity: 'error',
219
- summary: 'Error',
220
- detail: 'Failed to load messages',
221
- life: 3000
222
- })
223
-
224
- // Show empty state on error
225
- messages.value = []
226
- } finally {
227
- loading.value = false
228
- }
229
- }
230
-
231
- const viewMessage = (message) => {
232
- selectedMessage.value = message
233
- showDetail.value = true
234
- }
235
-
236
- const retryMessage = async (message) => {
237
- try {
238
- // API call to retry message
239
- toast.add({
240
- severity: 'success',
241
- summary: 'Success',
242
- detail: 'Message queued for retry',
243
- life: 3000
244
- })
245
- } catch (error) {
246
- toast.add({
247
- severity: 'error',
248
- summary: 'Error',
249
- detail: 'Failed to retry message',
250
- life: 3000
251
- })
252
- }
253
- }
254
-
255
- const formatDate = (dateString) => {
256
- if (!dateString) return '-'
257
- const date = new Date(dateString)
258
- return date.toLocaleString()
259
- }
260
-
261
- const getAttemptSeverity = (attempts) => {
262
- if (!attempts || attempts === 0) return 'success'
263
- if (attempts <= 2) return 'warning'
264
- return 'danger'
265
- }
266
-
267
- onMounted(() => {
268
- fetchQueues()
269
- fetchMessages()
270
- })
271
- </script>
272
-
273
- <style scoped>
274
- .messages-view {
275
- padding: 0;
276
- }
277
-
278
- .messages-card {
279
- background: transparent !important;
280
- border: 1px solid rgba(255, 255, 255, 0.1);
281
- border-radius: 16px;
282
- box-shadow: none !important;
283
- }
284
-
285
- :deep(.p-card-content) {
286
- padding: 0;
287
- }
288
-
289
- .table-header {
290
- display: flex;
291
- justify-content: space-between;
292
- align-items: center;
293
- padding: 1.5rem;
294
- border-bottom: 1px solid rgba(255, 255, 255, 0.1);
295
- }
296
-
297
- .table-header h2 {
298
- font-size: 1.25rem;
299
- font-weight: 600;
300
- color: var(--surface-700);
301
- margin: 0;
302
- }
303
-
304
- .table-actions {
305
- display: flex;
306
- gap: 1rem;
307
- align-items: center;
308
- }
309
-
310
- .queue-dropdown,
311
- .status-dropdown {
312
- min-width: 150px;
313
- }
314
-
315
- :deep(.queue-dropdown .p-dropdown),
316
- :deep(.status-dropdown .p-dropdown) {
317
- background: rgba(255, 255, 255, 0.05);
318
- border: 1px solid rgba(255, 255, 255, 0.1);
319
- }
320
-
321
- .transaction-id {
322
- font-family: 'Courier New', monospace;
323
- font-size: 0.875rem;
324
- color: var(--primary-500);
325
- }
326
-
327
- .queue-name-cell {
328
- display: flex;
329
- align-items: center;
330
- gap: 0.5rem;
331
- }
332
-
333
- .queue-icon-small {
334
- width: 24px;
335
- height: 24px;
336
- border-radius: 6px;
337
- background: linear-gradient(135deg, #ec4899 0%, #db2777 100%);
338
- display: flex;
339
- align-items: center;
340
- justify-content: center;
341
- color: white;
342
- font-weight: 600;
343
- font-size: 0.75rem;
344
- }
345
-
346
- .timestamp {
347
- color: var(--surface-500);
348
- font-size: 0.875rem;
349
- }
350
-
351
- .action-btn {
352
- color: var(--surface-500) !important;
353
- }
354
-
355
- .action-btn:hover {
356
- background: rgba(236, 72, 153, 0.1) !important;
357
- color: var(--primary-500) !important;
358
- }
359
-
360
- /* Message Detail Dialog */
361
- .message-dialog :deep(.p-dialog) {
362
- background: var(--surface-50);
363
- border: 1px solid rgba(255, 255, 255, 0.1);
364
- }
365
-
366
- .message-dialog :deep(.p-dialog-header) {
367
- background: var(--surface-0);
368
- border-bottom: 1px solid rgba(255, 255, 255, 0.1);
369
- }
370
-
371
- .message-detail {
372
- padding: 1rem;
373
- }
374
-
375
- .detail-row {
376
- display: flex;
377
- align-items: center;
378
- gap: 1rem;
379
- margin-bottom: 1rem;
380
- }
381
-
382
- .detail-label {
383
- font-weight: 600;
384
- color: var(--surface-400);
385
- min-width: 120px;
386
- }
387
-
388
- .detail-value {
389
- color: var(--surface-600);
390
- }
391
-
392
- .payload-viewer {
393
- background: var(--surface-0);
394
- border: 1px solid rgba(255, 255, 255, 0.1);
395
- border-radius: 8px;
396
- padding: 1rem;
397
- color: var(--surface-600);
398
- font-family: 'Courier New', monospace;
399
- font-size: 0.875rem;
400
- overflow-x: auto;
401
- }
402
-
403
- /* DataTable dark theme overrides */
404
- :deep(.dark-table-v3) {
405
- background: transparent !important;
406
- border: none !important;
407
- }
408
-
409
- :deep(.dark-table-v3 .p-datatable-header) {
410
- background: transparent !important;
411
- border: none !important;
412
- }
413
-
414
- :deep(.dark-table-v3 .p-datatable-thead > tr > th) {
415
- background: transparent !important;
416
- color: var(--surface-400) !important;
417
- border-color: rgba(255, 255, 255, 0.1) !important;
418
- }
419
-
420
- :deep(.dark-table-v3 .p-datatable-tbody > tr) {
421
- background: transparent !important;
422
- }
423
-
424
- :deep(.dark-table-v3 .p-datatable-tbody > tr:hover) {
425
- background: rgba(236, 72, 153, 0.05) !important;
426
- }
427
-
428
- :deep(.dark-table-v3 .p-datatable-tbody > tr > td) {
429
- color: var(--surface-600) !important;
430
- border-color: rgba(255, 255, 255, 0.05) !important;
431
- }
432
-
433
- :deep(.p-paginator) {
434
- background: transparent !important;
435
- border-top: 1px solid rgba(255, 255, 255, 0.1) !important;
436
- }
437
- </style>