All checks were successful
CI / ci (push) Successful in 7m16s
Restructure the monolithic 252-line main.rs into a 10-crate workspace with clean hexagonal architecture, swappable adapters, and a production- ready deployment pipeline. Backend architecture: - domain: Canvas, Color/Position/PixelUpdate value objects, port traits (CanvasStore, CanvasPersistence, EventBroadcaster), BroadcastEvent - application: use cases (place_pixel, get_state, save/restore snapshot, connect/disconnect), AppState with Arc snapshot cache - config: AppConfig structs + ConfigSource trait - api-types: shared DTOs, event name constants - adapters: config-env, canvas-file, http-axum (rust-embed), socketio, websocket — all behind port traits, swappable via feature flags - server: composition root with graceful shutdown (SIGTERM/SIGINT) Frontend: - Transport abstraction: Socket.IO and native WebSocket via VITE_TRANSPORT - Canvas zoom/pan with mouse wheel, pinch-to-zoom, and +/- buttons - ImageData rendering (~50x faster than fillRect loop) - Touch support, responsive CSS scaling, mobile-friendly layout - OG/Twitter Card meta tags for rich link previews Production: - Docker: musl static build on scratch — 2.73MB image - CI workflows for Gitea and GitHub Actions (fmt, clippy, test, Docker push) - deploy.sh for private registry - 39 unit tests across domain and application - Zero unwraps, zero unsafe, graceful error handling with tracing - Periodic canvas snapshots with rotation, restored on startup - All config via environment variables with typed defaults
84 lines
2.9 KiB
Plaintext
84 lines
2.9 KiB
Plaintext
graph TB
|
|
subgraph Binary ["Server (Composition Root)"]
|
|
server["server<br/><i>wires adapters, starts Axum</i>"]
|
|
end
|
|
|
|
subgraph Application ["Application Layer"]
|
|
AppState["AppState"]
|
|
PlacePixel["canvas::place_pixel"]
|
|
GetState["canvas::get_state"]
|
|
SaveSnapshot["canvas::save_snapshot"]
|
|
RestoreSnapshot["canvas::restore_snapshot"]
|
|
Connect["soldiers::connect"]
|
|
Disconnect["soldiers::disconnect"]
|
|
InMemoryCanvas["InMemoryCanvasStore"]
|
|
InProcessBroadcast["InProcessBroadcaster"]
|
|
end
|
|
|
|
subgraph Domain ["Domain Layer (0 infra deps)"]
|
|
Canvas["Canvas"]
|
|
ValueObjects["Color | Position | PixelUpdate"]
|
|
BroadcastEvent["BroadcastEvent"]
|
|
DomainError["DomainError"]
|
|
|
|
subgraph Ports ["Port Traits"]
|
|
CanvasStore["CanvasStore"]
|
|
CanvasPersistence["CanvasPersistence"]
|
|
EventBroadcaster["EventBroadcaster"]
|
|
end
|
|
end
|
|
|
|
subgraph Shared ["Shared Types"]
|
|
Config["config<br/><i>AppConfig, ConfigSource trait</i>"]
|
|
ApiTypes["api-types<br/><i>PixelUpdatePayload, event constants</i>"]
|
|
end
|
|
|
|
subgraph Adapters ["Adapters"]
|
|
subgraph Transport ["Transport (driving)"]
|
|
SocketIO["socketio<br/><i>Socket.IO protocol</i>"]
|
|
WebSocket["websocket<br/><i>native WebSocket + JSON</i>"]
|
|
end
|
|
|
|
subgraph Infrastructure ["Infrastructure (driven)"]
|
|
ConfigEnv["config-env<br/><i>env var loader</i>"]
|
|
CanvasFile["canvas-file<br/><i>file snapshots</i>"]
|
|
HttpAxum["http-axum<br/><i>HTTP routes, rate limit,<br/>embedded static files</i>"]
|
|
end
|
|
end
|
|
|
|
server --> Application
|
|
server --> Transport
|
|
server --> Infrastructure
|
|
server --> Config
|
|
|
|
PlacePixel --> CanvasStore
|
|
PlacePixel --> EventBroadcaster
|
|
SaveSnapshot --> CanvasStore
|
|
SaveSnapshot --> CanvasPersistence
|
|
RestoreSnapshot --> CanvasStore
|
|
RestoreSnapshot --> CanvasPersistence
|
|
Connect --> EventBroadcaster
|
|
Disconnect --> EventBroadcaster
|
|
|
|
InMemoryCanvas -.->|implements| CanvasStore
|
|
InProcessBroadcast -.->|implements| EventBroadcaster
|
|
CanvasFile -.->|implements| CanvasPersistence
|
|
ConfigEnv -.->|implements| Config
|
|
|
|
SocketIO --> Application
|
|
WebSocket --> Application
|
|
SocketIO --> ApiTypes
|
|
HttpAxum --> Config
|
|
|
|
classDef domain fill:#e8f5e9,stroke:#2e7d32
|
|
classDef app fill:#e3f2fd,stroke:#1565c0
|
|
classDef adapter fill:#fff3e0,stroke:#e65100
|
|
classDef shared fill:#f3e5f5,stroke:#6a1b9a
|
|
classDef binary fill:#fce4ec,stroke:#c62828
|
|
|
|
class Canvas,ValueObjects,BroadcastEvent,DomainError,CanvasStore,CanvasPersistence,EventBroadcaster domain
|
|
class AppState,PlacePixel,GetState,SaveSnapshot,RestoreSnapshot,Connect,Disconnect,InMemoryCanvas,InProcessBroadcast app
|
|
class SocketIO,WebSocket,ConfigEnv,CanvasFile,HttpAxum adapter
|
|
class Config,ApiTypes shared
|
|
class server binary
|