- Fix metrics: change MessagesTotal, ConnectionsTotal, DisconnectionsTotal from Gauge to Counter with proper _total naming convention - Fix broadcast write-error handling: failed clients now get properly removed with accurate metrics updates - Add graceful shutdown: SIGINT/SIGTERM handling with 10s timeout, CloseGoingAway frame sent to clients before disconnect - Add integration tests: 11 tests using real WebSocket connections covering connect, broadcast, disconnect, concurrency, and shutdown - Fix example client port: changed from 8000 to 8443 to match config - Rewrite README.md to reflect current features and usage - Add AGENTS.md and .agents/summary/ documentation for AI assistants
148 lines
3.9 KiB
Markdown
148 lines
3.9 KiB
Markdown
# Components
|
|
|
|
## Component Overview
|
|
|
|
```mermaid
|
|
graph TB
|
|
subgraph "main (Entry Point)"
|
|
MAIN[main.go]
|
|
end
|
|
|
|
subgraph "internal/config"
|
|
CFG[Config Loader]
|
|
end
|
|
|
|
subgraph "internal/hub"
|
|
HUB[Hub Manager]
|
|
WS[WebSocket Handler]
|
|
end
|
|
|
|
subgraph "internal/metrics"
|
|
MET[Prometheus Metrics]
|
|
end
|
|
|
|
MAIN --> CFG
|
|
MAIN --> HUB
|
|
MAIN --> MET
|
|
HUB --> WS
|
|
HUB --> MET
|
|
```
|
|
|
|
## Package: `main`
|
|
|
|
**File:** `main.go`
|
|
|
|
**Responsibility:** Application entry point and server initialization.
|
|
|
|
**Behavior:**
|
|
1. Parses CLI flags (`--config-file`)
|
|
2. Loads YAML configuration
|
|
3. Creates and starts the Hub
|
|
4. Optionally starts the metrics HTTP server on a separate port
|
|
5. Starts the WebSocket HTTP/TLS server
|
|
|
|
**Dependencies:** `internal/config`, `internal/hub`, `prometheus/client_golang`
|
|
|
|
---
|
|
|
|
## Package: `internal/hub`
|
|
|
|
**File:** `internal/hub/hub.go`
|
|
|
|
**Responsibility:** WebSocket connection lifecycle management and message broadcasting.
|
|
|
|
### Struct: `Hub`
|
|
|
|
| Field | Type | Purpose |
|
|
|-------|------|---------|
|
|
| `clients` | `map[*websocket.Conn]bool` | Set of active connections |
|
|
| `broadcast` | `chan []byte` | Channel for messages to relay |
|
|
| `register` | `chan *websocket.Conn` | Channel for new connections |
|
|
| `unregister` | `chan *websocket.Conn` | Channel for disconnections |
|
|
| `mu` | `sync.RWMutex` | Protects the clients map |
|
|
|
|
### Methods
|
|
|
|
| Method | Signature | Description |
|
|
|--------|-----------|-------------|
|
|
| `New` | `func New() *Hub` | Constructor, initializes all channels and map |
|
|
| `Run` | `func (h *Hub) Run()` | Main event loop processing channels (blocking) |
|
|
| `HandleWebSocket` | `func (h *Hub) HandleWebSocket(w, r)` | HTTP handler — upgrades connection and starts reader |
|
|
| `ClientCount` | `func (h *Hub) ClientCount() int` | Returns current connected client count (thread-safe) |
|
|
|
|
### Connection Flow
|
|
|
|
```mermaid
|
|
stateDiagram-v2
|
|
[*] --> HTTPRequest: Client connects
|
|
HTTPRequest --> Upgraded: WebSocket upgrade
|
|
Upgraded --> Registered: register channel
|
|
Registered --> Reading: goroutine loop
|
|
Reading --> Broadcasting: message received
|
|
Broadcasting --> Reading: continue
|
|
Reading --> Unregistered: error/close
|
|
Unregistered --> [*]: connection cleaned up
|
|
```
|
|
|
|
---
|
|
|
|
## Package: `internal/config`
|
|
|
|
**File:** `internal/config/config.go`
|
|
|
|
**Responsibility:** YAML configuration file loading and parsing.
|
|
|
|
### Struct: `Config`
|
|
|
|
```go
|
|
type Config struct {
|
|
Server struct {
|
|
Port int
|
|
TLS struct {
|
|
Enabled bool
|
|
CertFile string
|
|
KeyFile string
|
|
}
|
|
}
|
|
Metrics struct {
|
|
Enabled bool
|
|
Port int
|
|
}
|
|
}
|
|
```
|
|
|
|
### Functions
|
|
|
|
| Function | Signature | Description |
|
|
|----------|-----------|-------------|
|
|
| `Load` | `func Load(filename string) (*Config, error)` | Reads and parses YAML config file |
|
|
|
|
---
|
|
|
|
## Package: `internal/metrics`
|
|
|
|
**File:** `internal/metrics/metrics.go`
|
|
|
|
**Responsibility:** Prometheus metrics registration and exposure.
|
|
|
|
### Metrics Defined
|
|
|
|
| Variable | Prometheus Type | Metric Name | Description |
|
|
|----------|----------------|-------------|-------------|
|
|
| `ConnectedClients` | Gauge | `websocket_connected_clients` | Current number of connected clients |
|
|
| `MessagesTotal` | Gauge | `websocket_message` | Total messages processed |
|
|
| `ConnectionsTotal` | Gauge | `websocket_connection` | Total connections established |
|
|
| `DisconnectionsTotal` | Gauge | `websocket_disconnection` | Total disconnections |
|
|
|
|
> **Note:** All metrics use `promauto.NewGauge` for auto-registration. The "total" metrics use Gauge instead of Counter, which means they track cumulative counts but will reset on restart.
|
|
|
|
---
|
|
|
|
## Test Coverage
|
|
|
|
| Package | Test File | Tests |
|
|
|---------|-----------|-------|
|
|
| `internal/hub` | `hub_test.go` | `TestNew`, `TestClientCount`, `TestBroadcastChannel` |
|
|
| `internal/config` | `config_test.go` | `TestLoad`, `TestLoadFileNotFound` |
|
|
| `internal/metrics` | — | No dedicated tests |
|