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:
+24
-7
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/fs"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
@@ -10,11 +11,13 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
dockerwatcher "github.com/alexei/docker-watcher"
|
||||
"github.com/alexei/docker-watcher/internal/api"
|
||||
"github.com/alexei/docker-watcher/internal/config"
|
||||
"github.com/alexei/docker-watcher/internal/crypto"
|
||||
"github.com/alexei/docker-watcher/internal/deployer"
|
||||
"github.com/alexei/docker-watcher/internal/docker"
|
||||
"github.com/alexei/docker-watcher/internal/events"
|
||||
"github.com/alexei/docker-watcher/internal/health"
|
||||
"github.com/alexei/docker-watcher/internal/notify"
|
||||
"github.com/alexei/docker-watcher/internal/npm"
|
||||
@@ -71,14 +74,15 @@ func main() {
|
||||
// Initialize services.
|
||||
healthChecker := health.New()
|
||||
notifier := notify.New()
|
||||
eventBus := events.New()
|
||||
|
||||
dep := deployer.New(dockerClient, npmClient, db, healthChecker, notifier, encKey)
|
||||
dep := deployer.New(dockerClient, npmClient, db, healthChecker, notifier, eventBus, encKey)
|
||||
|
||||
// Initialize webhook handler.
|
||||
webhookHandler := webhook.NewHandler(db, dep, dockerClient)
|
||||
|
||||
// Ensure webhook secret exists.
|
||||
secret, err := webhook.EnsureWebhookSecret(db)
|
||||
_, err = webhook.EnsureWebhookSecret(db)
|
||||
if err != nil {
|
||||
log.Fatalf("ensure webhook secret: %v", err)
|
||||
}
|
||||
@@ -94,16 +98,29 @@ func main() {
|
||||
}
|
||||
|
||||
// Build API server.
|
||||
apiServer := api.NewServer(db, dockerClient, dep, webhookHandler, encKey)
|
||||
apiServer := api.NewServer(db, dockerClient, dep, webhookHandler, eventBus, encKey)
|
||||
router := apiServer.Router()
|
||||
|
||||
// Serve embedded static files for the SPA frontend.
|
||||
// The embed.FS has "web/build" as a prefix, so we sub it to get the root.
|
||||
webBuildFS, err := fs.Sub(dockerwatcher.WebBuildFS, "web/build")
|
||||
if err != nil {
|
||||
log.Printf("WARNING: embedded frontend not available: %v", err)
|
||||
} else {
|
||||
staticHandler := api.StaticHandler(webBuildFS)
|
||||
// Handle all non-API routes with the static file server.
|
||||
router.NotFound(staticHandler.ServeHTTP)
|
||||
}
|
||||
|
||||
// Start HTTP server.
|
||||
addr := envOrDefault("LISTEN_ADDR", ":8080")
|
||||
httpServer := &http.Server{
|
||||
Addr: addr,
|
||||
Handler: router,
|
||||
ReadTimeout: 30 * time.Second,
|
||||
WriteTimeout: 60 * time.Second,
|
||||
Addr: addr,
|
||||
Handler: router,
|
||||
ReadTimeout: 30 * time.Second,
|
||||
// WriteTimeout is disabled (0) to support SSE long-lived connections.
|
||||
// Individual non-SSE handlers should use context timeouts as needed.
|
||||
WriteTimeout: 0,
|
||||
IdleTimeout: 120 * time.Second,
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user