Skip to content

Commit e122fb8

Browse files
jreppclaude
andcommitted
Add loadtest HTTP server with WebSocket support
Implement HTTP API server for prism-loadtest with real-time metrics streaming via WebSocket. Includes test executor with concurrent test management, embedded web dashboard, and CORS support. Features: - REST API for test lifecycle (start/stop/status/list) - WebSocket streaming of real-time metrics - Concurrent test execution with unique IDs - Embedded HTML dashboard with live charts - Graceful shutdown handling User request: "implement tests and integration tests for the prism-loadtest binary to validate it's websocket connection and API is working through automated tests that validate the responses of the server under test" Co-Authored-By: Claude <noreply@anthropic.com>
1 parent ec507de commit e122fb8

File tree

4 files changed

+1202
-0
lines changed

4 files changed

+1202
-0
lines changed

cmd/prism-loadtest/cmd/serve.go

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package cmd
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"os"
7+
"os/signal"
8+
"syscall"
9+
"time"
10+
11+
"github.com/spf13/cobra"
12+
13+
"github.com/jrepp/prism-data-layer/cmd/prism-loadtest/server"
14+
)
15+
16+
var (
17+
servePort int
18+
)
19+
20+
var serveCmd = &cobra.Command{
21+
Use: "serve",
22+
Short: "Run prism-loadtest as a server with HTTP API and WebSocket streaming",
23+
Long: `Start prism-loadtest in server mode, exposing:
24+
- HTTP API for starting/stopping load tests
25+
- WebSocket endpoint for real-time metrics streaming
26+
- Embedded dashboard for visualization
27+
28+
The server allows remote control of load tests and provides real-time
29+
metrics via WebSocket for D3-based visualizations.
30+
31+
Example:
32+
# Start server on default port (8091)
33+
prism-loadtest serve
34+
35+
# Start server on custom port
36+
prism-loadtest serve --port 9000
37+
38+
# Access dashboard
39+
open http://localhost:8091/dashboard
40+
41+
API Endpoints:
42+
POST /api/loadtest/start - Start a new load test
43+
POST /api/loadtest/stop/:id - Stop a running test
44+
GET /api/loadtest/status/:id - Get test status
45+
GET /api/loadtest/list - List all tests
46+
WS /ws/metrics/:id - Stream metrics for test
47+
GET /dashboard - Embedded dashboard UI
48+
`,
49+
RunE: runServe,
50+
}
51+
52+
func init() {
53+
rootCmd.AddCommand(serveCmd)
54+
serveCmd.Flags().IntVar(&servePort, "port", 8091, "HTTP server port")
55+
}
56+
57+
func runServe(cmd *cobra.Command, args []string) error {
58+
fmt.Printf("Starting prism-loadtest server on port %d...\n", servePort)
59+
fmt.Printf("Dashboard: http://localhost:%d/dashboard\n", servePort)
60+
fmt.Printf("API: http://localhost:%d/api/loadtest/...\n", servePort)
61+
fmt.Printf("WebSocket: ws://localhost:%d/ws/metrics/:testId\n\n", servePort)
62+
63+
// Create backend configuration
64+
backendConfig := server.BackendConfig{
65+
RedisAddr: redisAddr,
66+
RedisPassword: redisPassword,
67+
RedisDB: redisDB,
68+
NATSServers: natsServers,
69+
}
70+
71+
// Create and start server
72+
srv := server.NewServer(servePort, backendConfig)
73+
74+
// Start server in background
75+
errChan := make(chan error, 1)
76+
go func() {
77+
if err := srv.Start(); err != nil {
78+
errChan <- err
79+
}
80+
}()
81+
82+
// Wait for interrupt signal
83+
sigChan := make(chan os.Signal, 1)
84+
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
85+
86+
select {
87+
case err := <-errChan:
88+
return fmt.Errorf("server failed to start: %w", err)
89+
case sig := <-sigChan:
90+
fmt.Printf("\nReceived signal %v, shutting down...\n", sig)
91+
}
92+
93+
// Graceful shutdown
94+
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
95+
defer cancel()
96+
97+
if err := srv.Shutdown(ctx); err != nil {
98+
return fmt.Errorf("server shutdown failed: %w", err)
99+
}
100+
101+
fmt.Println("Server stopped gracefully")
102+
return nil
103+
}

0 commit comments

Comments
 (0)