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.9 KiB

Components

Component Overview

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

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

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