savinmax 905c241daa
Some checks failed
CI / test (push) Successful in 54s
CI / lint (push) Failing after 3m16s
Improve reliability, testing, and documentation
- 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
2026-06-11 19:14:19 +02:00

143 lines
3.4 KiB
Markdown

# Data Models
## Configuration Model
```mermaid
classDiagram
class Config {
+Server ServerConfig
+Metrics MetricsConfig
}
class ServerConfig {
+int Port
+TLSConfig TLS
}
class TLSConfig {
+bool Enabled
+string CertFile
+string KeyFile
}
class MetricsConfig {
+bool Enabled
+int Port
}
Config --> ServerConfig
Config --> MetricsConfig
ServerConfig --> TLSConfig
```
### Config Struct Definition
```go
type Config struct {
Server struct {
Port int `yaml:"port"`
TLS struct {
Enabled bool `yaml:"enabled"`
CertFile string `yaml:"cert_file"`
KeyFile string `yaml:"key_file"`
} `yaml:"tls"`
} `yaml:"server"`
Metrics struct {
Enabled bool `yaml:"enabled"`
Port int `yaml:"port"`
} `yaml:"metrics"`
}
```
### Default Configuration Values
| Field | Default | Notes |
|-------|---------|-------|
| `server.port` | 8443 | Standard alternate HTTPS port |
| `server.tls.enabled` | false (config.yaml) / true (example) | Toggle TLS |
| `server.tls.cert_file` | `cert.pem` | Relative to working directory |
| `server.tls.key_file` | `key.pem` | Relative to working directory |
| `metrics.enabled` | true | Prometheus metrics |
| `metrics.port` | 9090 | Standard Prometheus port |
---
## Hub State Model
```mermaid
classDiagram
class Hub {
-map~*websocket.Conn, bool~ clients
-chan []byte broadcast
-chan *websocket.Conn register
-chan *websocket.Conn unregister
-sync.RWMutex mu
+New() Hub
+Run()
+HandleWebSocket(w, r)
+ClientCount() int
}
```
### Channel Types
| Channel | Direction | Payload | Buffer |
|---------|-----------|---------|--------|
| `register` | Handler → Hub | `*websocket.Conn` | Unbuffered |
| `unregister` | Reader → Hub | `*websocket.Conn` | Unbuffered |
| `broadcast` | Reader → Hub | `[]byte` | Unbuffered |
---
## Message Model
The relay server does **not** impose any message structure. Messages are raw `[]byte` payloads passed through as WebSocket text frames.
```mermaid
graph LR
A[Client A sends bytes] --> B[Hub broadcast channel]
B --> C[Written as TextMessage to all clients]
```
The example HTML client uses an informal format:
```
{name}<br>{message_text}
```
But this is purely client-side convention — the server is format-agnostic.
---
## Metrics Model
```mermaid
classDiagram
class PrometheusMetrics {
+Gauge ConnectedClients
+Gauge MessagesTotal
+Gauge ConnectionsTotal
+Gauge DisconnectionsTotal
}
```
| Metric | Update Trigger |
|--------|---------------|
| `ConnectedClients` | Set on register/unregister (absolute count) |
| `MessagesTotal` | Incremented on each broadcast |
| `ConnectionsTotal` | Incremented on register |
| `DisconnectionsTotal` | Incremented on unregister |
---
## Connection State Machine
```mermaid
stateDiagram-v2
[*] --> Connecting: HTTP request to /
Connecting --> Connected: WebSocket upgrade success
Connecting --> Failed: Upgrade error
Connected --> Active: Registered in Hub
Active --> Active: Sending/Receiving messages
Active --> Disconnecting: Read error or client close
Disconnecting --> Closed: Unregistered from Hub
Failed --> [*]
Closed --> [*]
```