@gravito/zenith 0.1.0-beta.1

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 (63) hide show
  1. package/ARCHITECTURE.md +88 -0
  2. package/BATCH_OPERATIONS_IMPLEMENTATION.md +159 -0
  3. package/DEMO.md +156 -0
  4. package/DEPLOYMENT.md +157 -0
  5. package/DOCS_INTERNAL.md +73 -0
  6. package/Dockerfile +46 -0
  7. package/Dockerfile.demo-worker +29 -0
  8. package/EVOLUTION_BLUEPRINT.md +112 -0
  9. package/JOBINSPECTOR_SCROLL_FIX.md +152 -0
  10. package/PULSE_IMPLEMENTATION_PLAN.md +111 -0
  11. package/QUICK_TEST_GUIDE.md +72 -0
  12. package/README.md +33 -0
  13. package/ROADMAP.md +85 -0
  14. package/TESTING_BATCH_OPERATIONS.md +252 -0
  15. package/bin/flux-console.ts +2 -0
  16. package/dist/bin.js +108196 -0
  17. package/dist/client/assets/index-DGYEwTDL.css +1 -0
  18. package/dist/client/assets/index-oyTdySX0.js +421 -0
  19. package/dist/client/index.html +13 -0
  20. package/dist/server/index.js +108191 -0
  21. package/docker-compose.yml +40 -0
  22. package/docs/integrations/LARAVEL.md +207 -0
  23. package/package.json +50 -0
  24. package/postcss.config.js +6 -0
  25. package/scripts/flood-logs.ts +21 -0
  26. package/scripts/seed.ts +213 -0
  27. package/scripts/verify-throttle.ts +45 -0
  28. package/scripts/worker.ts +123 -0
  29. package/src/bin.ts +6 -0
  30. package/src/client/App.tsx +70 -0
  31. package/src/client/Layout.tsx +644 -0
  32. package/src/client/Sidebar.tsx +102 -0
  33. package/src/client/ThroughputChart.tsx +135 -0
  34. package/src/client/WorkerStatus.tsx +170 -0
  35. package/src/client/components/ConfirmDialog.tsx +103 -0
  36. package/src/client/components/JobInspector.tsx +524 -0
  37. package/src/client/components/LogArchiveModal.tsx +383 -0
  38. package/src/client/components/NotificationBell.tsx +203 -0
  39. package/src/client/components/Toaster.tsx +80 -0
  40. package/src/client/components/UserProfileDropdown.tsx +177 -0
  41. package/src/client/contexts/AuthContext.tsx +93 -0
  42. package/src/client/contexts/NotificationContext.tsx +103 -0
  43. package/src/client/index.css +174 -0
  44. package/src/client/index.html +12 -0
  45. package/src/client/main.tsx +15 -0
  46. package/src/client/pages/LoginPage.tsx +153 -0
  47. package/src/client/pages/MetricsPage.tsx +408 -0
  48. package/src/client/pages/OverviewPage.tsx +511 -0
  49. package/src/client/pages/QueuesPage.tsx +372 -0
  50. package/src/client/pages/SchedulesPage.tsx +531 -0
  51. package/src/client/pages/SettingsPage.tsx +449 -0
  52. package/src/client/pages/WorkersPage.tsx +316 -0
  53. package/src/client/pages/index.ts +7 -0
  54. package/src/client/utils.ts +6 -0
  55. package/src/server/index.ts +556 -0
  56. package/src/server/middleware/auth.ts +127 -0
  57. package/src/server/services/AlertService.ts +160 -0
  58. package/src/server/services/QueueService.ts +828 -0
  59. package/tailwind.config.js +73 -0
  60. package/tests/placeholder.test.ts +7 -0
  61. package/tsconfig.json +38 -0
  62. package/tsconfig.node.json +12 -0
  63. package/vite.config.ts +27 -0
@@ -0,0 +1,123 @@
1
+ #!/usr/bin/env bun
2
+ import { Consumer, Job, QueueManager } from '@gravito/stream'
3
+ import Redis from 'ioredis'
4
+
5
+ /**
6
+ * Flux Console Unified Worker Script
7
+ *
8
+ * Usage:
9
+ * bun scripts/worker.ts [queues] [--fail=rate] [--delay=ms]
10
+ *
11
+ * Example:
12
+ * bun scripts/worker.ts orders,reports --fail=0.1 --delay=200
13
+ * bun scripts/worker.ts all
14
+ */
15
+
16
+ const redis = new Redis('redis://localhost:6379')
17
+ const prefix = 'queue:'
18
+
19
+ const queuesRaw = process.argv[2] || 'orders,notifications,test-batch,billing,analytics'
20
+ let queues: string[] = []
21
+
22
+ if (queuesRaw === 'all') {
23
+ console.log('šŸ” Discovering all queues...')
24
+ const keys = await redis.keys(`${prefix}*`)
25
+ const set = new Set<string>()
26
+ for (const k of keys) {
27
+ const name = k.slice(prefix.length).split(':')[0]
28
+ // Exclude internal management keys
29
+ if (
30
+ name &&
31
+ ![
32
+ 'active',
33
+ 'schedules',
34
+ 'schedule',
35
+ 'worker',
36
+ 'lock',
37
+ 'logs',
38
+ 'metrics',
39
+ 'throughput',
40
+ ].includes(name)
41
+ ) {
42
+ set.add(name)
43
+ }
44
+ }
45
+ queues = Array.from(set)
46
+ if (queues.length === 0) {
47
+ console.log('āš ļø No active queues found. Defaulting to standard set...')
48
+ queues = ['orders', 'notifications', 'test-batch', 'billing', 'analytics']
49
+ }
50
+ } else {
51
+ queues = queuesRaw.split(',')
52
+ }
53
+
54
+ const failRate = parseFloat(process.argv.find((a) => a.startsWith('--fail='))?.split('=')[1] || '0')
55
+ const processDelay = parseInt(
56
+ process.argv.find((a) => a.startsWith('--delay='))?.split('=')[1] || '100'
57
+ )
58
+
59
+ // Simple Job class for testing
60
+ class GenericJob extends Job {
61
+ constructor(
62
+ id: any = null,
63
+ public data: any = {}
64
+ ) {
65
+ super()
66
+ this.id = id
67
+ }
68
+ async handle() {
69
+ // Simulated work
70
+ if (processDelay > 0) {
71
+ await new Promise((r) => setTimeout(r, processDelay))
72
+ }
73
+
74
+ // Simulated failure
75
+ if (Math.random() < failRate) {
76
+ throw new Error('Simulated random failure')
77
+ }
78
+ }
79
+ }
80
+
81
+ const manager = new QueueManager({
82
+ default: 'redis',
83
+ connections: {
84
+ redis: {
85
+ driver: 'redis',
86
+ client: redis,
87
+ prefix,
88
+ },
89
+ },
90
+ })
91
+
92
+ manager.registerJobClasses([GenericJob])
93
+
94
+ console.log('šŸš€ Starting Flux Unified Worker...')
95
+ console.log(`šŸ“” Queues: ${queues.join(', ')}`)
96
+ console.log(`āš ļø Fail Rate: ${(failRate * 100).toFixed(0)}%`)
97
+ console.log(`ā±ļø Sim Delay: ${processDelay}ms\n`)
98
+
99
+ const consumer = new Consumer(manager, {
100
+ queues,
101
+ connection: 'redis',
102
+ pollInterval: 100,
103
+ monitor: {
104
+ prefix: 'flux_console:', // Critical: match the prefix the Console looks for
105
+ },
106
+ workerOptions: {
107
+ maxAttempts: 3,
108
+ },
109
+ })
110
+
111
+ console.log('āœ… Worker started. Monitoring enabled (check the Workers page in Console).')
112
+
113
+ consumer.start().catch((err) => {
114
+ console.error('šŸ’„ Consumer Error:', err)
115
+ process.exit(1)
116
+ })
117
+
118
+ process.on('SIGINT', async () => {
119
+ console.log('\nšŸ›‘ Shutting down worker...')
120
+ await consumer.stop()
121
+ redis.disconnect()
122
+ process.exit(0)
123
+ })
package/src/bin.ts ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env bun
2
+ import server from './server/index'
3
+
4
+ console.log(`[Flux Console] CLI wrapper initialized.`)
5
+
6
+ export default server
@@ -0,0 +1,70 @@
1
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
2
+ import { RefreshCcw } from 'lucide-react'
3
+ import { BrowserRouter, Route, Routes } from 'react-router-dom'
4
+ import { AuthProvider, useAuth } from './contexts/AuthContext'
5
+ import { NotificationProvider } from './contexts/NotificationContext'
6
+ import { Layout } from './Layout'
7
+ import {
8
+ LoginPage,
9
+ MetricsPage,
10
+ OverviewPage,
11
+ QueuesPage,
12
+ SchedulesPage,
13
+ SettingsPage,
14
+ WorkersPage,
15
+ } from './pages'
16
+
17
+ const queryClient = new QueryClient()
18
+
19
+ function AuthenticatedRoutes() {
20
+ const { isAuthenticated, isAuthEnabled, isLoading } = useAuth()
21
+
22
+ // Show loading spinner while checking auth
23
+ if (isLoading) {
24
+ return (
25
+ <div className="min-h-screen flex items-center justify-center bg-background">
26
+ <div className="flex flex-col items-center gap-4">
27
+ <RefreshCcw className="animate-spin text-primary" size={48} />
28
+ <p className="text-muted-foreground font-bold uppercase tracking-[0.3em] text-xs">
29
+ Initializing...
30
+ </p>
31
+ </div>
32
+ </div>
33
+ )
34
+ }
35
+
36
+ // If auth is enabled and user is not authenticated, show login
37
+ if (isAuthEnabled && !isAuthenticated) {
38
+ return <LoginPage />
39
+ }
40
+
41
+ // Otherwise, show the main app
42
+ return (
43
+ <NotificationProvider>
44
+ <Layout>
45
+ <Routes>
46
+ <Route path="/" element={<OverviewPage />} />
47
+ <Route path="/queues" element={<QueuesPage />} />
48
+ <Route path="/schedules" element={<SchedulesPage />} />
49
+ <Route path="/workers" element={<WorkersPage />} />
50
+ <Route path="/metrics" element={<MetricsPage />} />
51
+ <Route path="/settings" element={<SettingsPage />} />
52
+ </Routes>
53
+ </Layout>
54
+ </NotificationProvider>
55
+ )
56
+ }
57
+
58
+ function App() {
59
+ return (
60
+ <QueryClientProvider client={queryClient}>
61
+ <BrowserRouter>
62
+ <AuthProvider>
63
+ <AuthenticatedRoutes />
64
+ </AuthProvider>
65
+ </BrowserRouter>
66
+ </QueryClientProvider>
67
+ )
68
+ }
69
+
70
+ export default App