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

3.7 KiB

Workflows

Application Startup

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

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

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

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

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

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

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.