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

141 lines
3.7 KiB
Markdown

# Workflows
## Application Startup
```mermaid
flowchart TD
START[Application Start] --> PARSE[Parse CLI flags]
PARSE --> LOAD[Load config.yaml]
LOAD -->|Error| FATAL[log.Fatal - exit]
LOAD -->|Success| CREATE[Create Hub]
CREATE --> RUN[Start Hub.Run goroutine]
RUN --> METRICS{Metrics enabled?}
METRICS -->|Yes| METSRV[Start metrics server goroutine on :9090]
METRICS -->|No| SKIP[Skip metrics]
METSRV --> TLS{TLS enabled?}
SKIP --> TLS
TLS -->|Yes| TLSSERVE[ListenAndServeTLS on :8443]
TLS -->|No| HTTPSERVE[ListenAndServe on :8443]
```
---
## Client Connection Workflow
```mermaid
sequenceDiagram
participant Client
participant HTTP as HTTP Server
participant Upgrader as WebSocket Upgrader
participant Hub as Hub.Run()
participant Metrics
Client->>HTTP: GET / (Upgrade: websocket)
HTTP->>Upgrader: CheckOrigin (always true)
Upgrader->>HTTP: Upgrade response
HTTP->>Hub: register <- conn
Hub->>Metrics: ConnectedClients.Set(n)
Hub->>Metrics: ConnectionsTotal.Inc()
Note over HTTP: Spawn reader goroutine
loop Message Loop
Client->>HTTP: WebSocket frame
HTTP->>Hub: broadcast <- message
Hub->>Metrics: MessagesTotal.Inc()
Hub->>Client: WriteMessage to all clients
end
Note over HTTP: Read error or client disconnect
HTTP->>Hub: unregister <- conn
Hub->>Metrics: ConnectedClients.Set(n-1)
Hub->>Metrics: DisconnectionsTotal.Inc()
Hub->>Hub: Close connection, remove from map
```
---
## Build and Release Workflow
```mermaid
flowchart LR
subgraph Development
CODE[Write Code] --> PUSH[Push to main/develop]
end
subgraph "CI Pipeline"
PUSH --> TEST[go test -v ./...]
PUSH --> LINT[golangci-lint]
TEST --> BUILD[make build]
end
subgraph "Release Pipeline"
TAG[Push v* tag] --> REL_BUILD[Cross-compile]
REL_BUILD --> LINUX[linux/amd64 binary]
REL_BUILD --> MACOS[darwin/arm64 binary]
LINUX --> RELEASE[Gitea Release]
MACOS --> RELEASE
end
```
---
## Development Workflow
```mermaid
flowchart TD
START[Clone repo] --> DEPS[make deps / go mod tidy]
DEPS --> CONFIG[Edit config.yaml]
CONFIG --> RUN[make run]
RUN --> TEST_LOCAL[Test with example/index.html]
TEST_LOCAL --> WRITE[Write code changes]
WRITE --> UNIT[make test]
UNIT -->|Pass| COMMIT[git commit]
UNIT -->|Fail| WRITE
COMMIT --> PUSH[git push]
PUSH --> CI[CI runs tests + lint]
```
---
## Message Broadcast Workflow
```mermaid
flowchart TD
MSG[Client sends message] --> CHAN[broadcast channel receives []byte]
CHAN --> INC[MessagesTotal.Inc]
INC --> LOCK[RLock clients map]
LOCK --> ITER{For each client}
ITER -->|Next client| WRITE[WriteMessage]
WRITE -->|Success| ITER
WRITE -->|Error| REMOVE[Remove client, close conn]
REMOVE --> ITER
ITER -->|Done| UNLOCK[RUnlock]
```
---
## Error Handling Workflows
### Connection Upgrade Failure
```mermaid
flowchart LR
REQ[HTTP Request] --> UPG{Upgrade succeeds?}
UPG -->|No| LOG[Log error]
LOG --> RETURN[Return - no cleanup needed]
UPG -->|Yes| REGISTER[Continue with registration]
```
### Write Error During Broadcast
```mermaid
flowchart LR
WRITE[WriteMessage] --> ERR{Error?}
ERR -->|No| NEXT[Continue to next client]
ERR -->|Yes| DEL[Delete from clients map]
DEL --> CLOSE[Close connection]
CLOSE --> NEXT
```
> **Note:** Write errors during broadcast silently remove the failing client without triggering the unregister channel. This is a potential inconsistency — the `DisconnectionsTotal` metric won't be incremented and `ConnectedClients` gauge won't be updated for these removals.