feat(docker-watcher): phase 11 - frontend embed & SSE
Embed SvelteKit static build in Go binary via go:embed. Event bus for pub/sub with deploy log, instance status, and deploy status events. SSE endpoints for real-time streaming. Frontend SSE client with exponential backoff reconnection. Makefile for build pipeline. Update Phase 12 auth plan with OAuth2/OIDC support.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# Phase 11: Frontend Embed & Real-Time Updates
|
||||
|
||||
**Status:** ⬜ Not Started
|
||||
**Status:** Done
|
||||
**Parent plan:** [PLAN.md](./PLAN.md)
|
||||
**Domain:** fullstack
|
||||
|
||||
@@ -9,26 +9,31 @@ Build SvelteKit to static files, embed into the Go binary with `go:embed`, serve
|
||||
|
||||
## Tasks
|
||||
|
||||
- [ ] Task 1: Configure SvelteKit static adapter to output to `web/build/`
|
||||
- [ ] Task 2: Add `//go:embed web/build` directive in Go — serve static files
|
||||
- [ ] Task 3: Create Go handler for serving embedded SPA — serve index.html for all non-API routes (SPA fallback)
|
||||
- [ ] Task 4: Implement SSE endpoint for deploy logs — `GET /api/deploys/:id/logs` streams deploy progress in real-time
|
||||
- [ ] Task 5: Implement SSE endpoint for instance status — `GET /api/events` streams instance status changes
|
||||
- [ ] Task 6: Create event bus/broadcaster in Go — publish events from deployer, subscribe from SSE handlers
|
||||
- [ ] Task 7: Frontend: connect to SSE for deploy progress — update deploy log view in real-time
|
||||
- [ ] Task 8: Frontend: connect to SSE for instance status — update dashboard/project views without refresh
|
||||
- [ ] Task 9: Handle SSE reconnection in frontend — auto-reconnect with backoff on disconnect
|
||||
- [ ] Task 10: Build script/Makefile — `make build` builds frontend then Go binary
|
||||
- [x] Task 1: Configure SvelteKit static adapter to output to `web/build/` (already configured)
|
||||
- [x] Task 2: Add `//go:embed web/build` directive in Go — `web.go` at project root
|
||||
- [x] Task 3: Create Go handler for serving embedded SPA — `internal/api/static.go` with SPA fallback
|
||||
- [x] Task 4: Implement SSE endpoint for deploy logs — `GET /api/deploys/:id/logs` (SSE + JSON fallback)
|
||||
- [x] Task 5: Implement SSE endpoint for instance status — `GET /api/events` streams instance status changes
|
||||
- [x] Task 6: Create event bus/broadcaster in Go — `internal/events/bus.go` with pub/sub channels
|
||||
- [x] Task 7: Frontend: connect to SSE for deploy progress — `connectDeployLogs()` in `web/src/lib/sse.ts`
|
||||
- [x] Task 8: Frontend: connect to SSE for instance status — global SSE in `+layout.svelte` via store
|
||||
- [x] Task 9: Handle SSE reconnection in frontend — exponential backoff with jitter in `connectSSE()`
|
||||
- [x] Task 10: Build script/Makefile — `make build` builds frontend then Go binary
|
||||
|
||||
## Files to Modify/Create
|
||||
- `web/svelte.config.js` — ensure static adapter outputs to `web/build/`
|
||||
- `web/svelte.config.js` — already configured with static adapter outputting to `web/build/`
|
||||
- `web.go` — root-level embed directive (`//go:embed web/build`)
|
||||
- `internal/api/static.go` — embedded static file server with SPA fallback
|
||||
- `internal/api/sse.go` — SSE endpoints for deploy logs and instance events
|
||||
- `internal/events/bus.go` — event bus for publishing/subscribing to events
|
||||
- `web/src/lib/sse.ts` — SSE client helper with auto-reconnect
|
||||
- `web/src/routes/+layout.svelte` — wire up global SSE connection for instance status
|
||||
- `web/src/lib/stores/instance-status.ts` — Svelte store for real-time instance status
|
||||
- `web/src/routes/+layout.svelte` — wired up global SSE connection for instance status
|
||||
- `Makefile` — build frontend + backend
|
||||
- `cmd/server/main.go` — wire embedded static serving and event bus
|
||||
- `cmd/server/main.go` — wired embedded static serving and event bus
|
||||
- `internal/api/router.go` — added eventBus to Server, SSE routes
|
||||
- `internal/api/deploys.go` — removed old JSON stub, replaced by SSE handler
|
||||
- `internal/deployer/deployer.go` — added event publishing for deploy logs, status, instance status
|
||||
|
||||
## Acceptance Criteria
|
||||
- `make build` produces a single Go binary with embedded frontend
|
||||
@@ -43,13 +48,29 @@ Build SvelteKit to static files, embed into the Go binary with `go:embed`, serve
|
||||
- Event bus: simple pub/sub with channels — no external dependency needed
|
||||
- SSE format: `data: {"type": "deploy_log", "payload": {...}}\n\n`
|
||||
- Keep SSE connections lightweight — use context cancellation for cleanup
|
||||
- WriteTimeout on HTTP server set to 0 to support long-lived SSE connections
|
||||
- Deploy logs endpoint serves both SSE (Accept: text/event-stream) and JSON (default)
|
||||
|
||||
## Review Checklist
|
||||
- [ ] All tasks completed
|
||||
- [ ] Single binary serves both API and frontend
|
||||
- [ ] SSE handles multiple concurrent clients
|
||||
- [ ] No goroutine leaks on SSE disconnect
|
||||
- [ ] Build process is reproducible (Makefile)
|
||||
- [x] All tasks completed
|
||||
- [x] Single binary serves both API and frontend
|
||||
- [x] SSE handles multiple concurrent clients (buffered channels, non-blocking publish)
|
||||
- [x] No goroutine leaks on SSE disconnect (context cancellation + Unsubscribe)
|
||||
- [x] Build process is reproducible (Makefile)
|
||||
|
||||
## Handoff to Next Phase
|
||||
<!-- Filled in by the implementation agent after completing this phase. -->
|
||||
|
||||
### What was implemented
|
||||
- **Event bus** (`internal/events/bus.go`): In-process pub/sub with topic filtering, buffered subscriber channels (64 events), non-blocking publish. Supports `EventDeployLog`, `EventInstanceStatus`, and `EventDeployStatus` event types.
|
||||
- **SSE endpoints**: `GET /api/deploys/{id}/logs` streams deploy logs with JSON fallback; `GET /api/events` streams global instance/deploy status changes.
|
||||
- **Static file serving**: `web.go` at project root embeds `web/build/`, `internal/api/static.go` serves SPA with fallback. Mounted via chi's `NotFound` handler.
|
||||
- **Frontend SSE client** (`web/src/lib/sse.ts`): `connectSSE()` with exponential backoff + jitter, `connectDeployLogs()` and `connectGlobalEvents()` convenience functions.
|
||||
- **Instance status store** (`web/src/lib/stores/instance-status.ts`): Svelte writable store updated by global SSE connection in `+layout.svelte`.
|
||||
- **Deployer integration**: `deployer.go` now publishes deploy log, deploy status, and instance status events via `EventPublisher` interface.
|
||||
|
||||
### Key integration points for next phase
|
||||
- `events.Bus` is passed to both `api.NewServer` and `deployer.New`
|
||||
- `api.NewServer` now requires an `*events.Bus` parameter (6th arg before encKey)
|
||||
- `deployer.New` now requires an `EventPublisher` parameter (6th arg before encKey)
|
||||
- HTTP server `WriteTimeout` is 0 to support SSE
|
||||
- The `web.go` file at project root uses package name `dockerwatcher` (imported as `github.com/alexei/docker-watcher`)
|
||||
|
||||
Reference in New Issue
Block a user