Skip to content

Commit 60c5ccf

Browse files
chore: wip
1 parent bcbe71e commit 60c5ccf

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+1517
-6713
lines changed

packages/dashboard/build.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import plugin from 'bun-plugin-dtsx'
2+
3+
await Bun.build({
4+
entrypoints: ['./src/index.ts'],
5+
outdir: './dist',
6+
target: 'bun',
7+
format: 'esm',
8+
splitting: true,
9+
sourcemap: 'external',
10+
minify: false,
11+
plugins: [plugin()],
12+
})
13+
14+
console.log('Build complete!')
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export default {
2+
content: [
3+
'./src/**/*.stx',
4+
],
5+
output: '',
6+
minify: false,
7+
preflight: true,
8+
cssVariables: true,
9+
}

packages/dashboard/package.json

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
{
2+
"name": "@stacksjs/bun-queue-dashboard",
3+
"type": "module",
4+
"version": "0.1.0",
5+
"description": "A real-time monitoring dashboard for bun-queue, built with stx.",
6+
"author": "Chris Breuer <chris@stacksjs.org>",
7+
"license": "MIT",
8+
"homepage": "https://github.com/stacksjs/bun-queue",
9+
"repository": {
10+
"type": "git",
11+
"url": "git+https://github.com/stacksjs/bun-queue.git"
12+
},
13+
"bugs": {
14+
"url": "https://github.com/stacksjs/bun-queue/issues"
15+
},
16+
"keywords": [
17+
"bun-queue",
18+
"dashboard",
19+
"monitoring",
20+
"stx",
21+
"redis",
22+
"job-queue"
23+
],
24+
"exports": {
25+
".": {
26+
"types": "./dist/index.d.ts",
27+
"import": "./dist/index.js"
28+
},
29+
"./*": {
30+
"import": "./dist/*"
31+
}
32+
},
33+
"module": "./dist/index.js",
34+
"types": "./dist/index.d.ts",
35+
"files": [
36+
"LICENSE.md",
37+
"README.md",
38+
"dist"
39+
],
40+
"scripts": {
41+
"build": "bun --bun build.ts",
42+
"dev": "bunx bun-plugin-stx serve src/pages/ --port 4400",
43+
"prepublishOnly": "bun run build",
44+
"test": "bun test",
45+
"test:watch": "bun test --watch",
46+
"test:coverage": "bun test --coverage",
47+
"typecheck": "bun tsc --noEmit"
48+
},
49+
"dependencies": {
50+
"@cwcss/crosswind": "^0.1.6",
51+
"@stacksjs/bun-queue": "^0.0.1"
52+
},
53+
"devDependencies": {
54+
"@stacksjs/stx": "^0.2.5",
55+
"bun-plugin-stx": "^0.2.5"
56+
}
57+
}

packages/dashboard/src/api.ts

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import type { DashboardConfig, DashboardStats, JobData, QueueMetrics } from './types'
2+
3+
const defaultConfig: Required<Pick<DashboardConfig, 'port' | 'host' | 'refreshInterval'>> = {
4+
port: 4400,
5+
host: 'localhost',
6+
refreshInterval: 5000,
7+
}
8+
9+
export function resolveConfig(config: DashboardConfig): DashboardConfig & typeof defaultConfig {
10+
return { ...defaultConfig, ...config }
11+
}
12+
13+
export async function fetchQueueMetrics(_config: DashboardConfig): Promise<QueueMetrics[]> {
14+
// TODO: Connect to Redis and read bun-queue metrics
15+
// This will use the bun-queue internal Redis keys to aggregate data
16+
return [
17+
{
18+
name: 'default',
19+
waiting: 0,
20+
active: 0,
21+
completed: 0,
22+
failed: 0,
23+
delayed: 0,
24+
paused: false,
25+
throughput: 0,
26+
errorRate: 0,
27+
avgProcessingTime: 0,
28+
},
29+
]
30+
}
31+
32+
export async function fetchJobs(_config: DashboardConfig, _queue?: string, _status?: string): Promise<JobData[]> {
33+
// TODO: Read job data from Redis
34+
return []
35+
}
36+
37+
export async function fetchDashboardStats(_config: DashboardConfig): Promise<DashboardStats> {
38+
// TODO: Aggregate stats from Redis
39+
return {
40+
totalQueues: 0,
41+
totalJobs: 0,
42+
activeJobs: 0,
43+
completedJobs: 0,
44+
failedJobs: 0,
45+
throughputPerMinute: 0,
46+
avgLatency: 0,
47+
uptime: 0,
48+
}
49+
}
50+
51+
export function createApiRoutes(config: DashboardConfig) {
52+
const resolvedConfig = resolveConfig(config)
53+
54+
return {
55+
'/api/stats': async () => {
56+
const stats = await fetchDashboardStats(resolvedConfig)
57+
return Response.json(stats)
58+
},
59+
'/api/queues': async () => {
60+
const queues = await fetchQueueMetrics(resolvedConfig)
61+
return Response.json(queues)
62+
},
63+
'/api/jobs': async (req: Request) => {
64+
const url = new URL(req.url)
65+
const queue = url.searchParams.get('queue') ?? undefined
66+
const status = url.searchParams.get('status') ?? undefined
67+
const jobs = await fetchJobs(resolvedConfig, queue, status)
68+
return Response.json(jobs)
69+
},
70+
}
71+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<script>
2+
const jobs = []
3+
</script>
4+
5+
<div>
6+
@if(jobs.length === 0)
7+
<div class="empty-state">No jobs to display.</div>
8+
@else
9+
<table>
10+
<thead>
11+
<tr>
12+
<th>ID</th>
13+
<th>Queue</th>
14+
<th>Name</th>
15+
<th>Status</th>
16+
<th class="text-right">Attempts</th>
17+
<th>Created</th>
18+
<th class="text-right">Duration</th>
19+
</tr>
20+
</thead>
21+
<tbody>
22+
@foreach(jobs as job)
23+
<tr>
24+
<td class="mono" style="font-size: 0.75rem;">{{ job.id }}</td>
25+
<td>{{ job.queue }}</td>
26+
<td style="color: var(--text); font-weight: 500;">{{ job.name }}</td>
27+
<td>
28+
<span class="badge {{ job.status === 'completed' ? 'badge-success' : job.status === 'failed' ? 'badge-error' : job.status === 'active' ? 'badge-info' : job.status === 'waiting' ? 'badge-warning' : 'badge-muted' }}">{{ job.status }}</span>
29+
</td>
30+
<td class="text-right tabular-nums">{{ job.attempts }}/{{ job.maxAttempts }}</td>
31+
<td style="font-size: 0.75rem;">{{ job.createdAt }}</td>
32+
<td class="text-right mono tabular-nums" style="font-size: 0.75rem;">{{ job.duration ? job.duration + 'ms' : '—' }}</td>
33+
</tr>
34+
@endforeach
35+
</tbody>
36+
</table>
37+
@endif
38+
</div>

0 commit comments

Comments
 (0)