Services Domain
Manages external infrastructure nodes that CoreAPI integrates with — Castis Streamer nodes, Cache (cproxy), and SLB (ELB). Each node type follows the same pattern: a DB registry for storing connection info, a dedicated HTTP client in pkg/ for runtime communication, and a proxy endpoint for direct API access during development.
Architecture
graph LR
CoreAPI --> StreamerClient["pkg/StreamerClient"]
CoreAPI --> CproxyClient["pkg/CproxyClient (planned)"]
CoreAPI --> ELBClient["pkg/ELBClient (planned)"]
StreamerClient --> Streamer["Castis Streamer Nodes"]
CproxyClient --> Cproxy["Cache / cproxy Nodes"]
ELBClient --> ELB["SLB / ELB Nodes"]
CoreAPI --> PostgreSQL["PostgreSQL (node registry)"]
Node records are stored in Postgres. At runtime, CoreAPI queries the record to get host and ports, maps it to a lightweight client struct (StreamerNode, etc.), and makes the HTTP call. The DB record and the client are kept separate — updating a node's host in the DB automatically takes effect on the next request.
Implementation Status
Streamer (Castis Streamer)
- Streamer CRUD (
/streamers) - Ping endpoint — hits
/api/ping, updatesstatusandlastPingedAt -
pkg/StreamerClient—CreateStream,DeleteStream,GetStreams,GetTraffic,ProxyRequest - Proxy endpoint — forward any Streamer API path verbatim (
/streamers/:id/proxy/*) -
StreamerNodedecoupled from DB model — no import cycle
Cache / cproxy
- Cache node CRUD
-
pkg/CproxyClient - Proxy endpoint
SLB / ELB
- SLB node CRUD
-
pkg/ELBClient - Proxy endpoint
Proxy Endpoint
Before dedicated typed functions are built for each node API, the proxy endpoint provides direct passthrough access to any path on the node: GET /streamers/1/proxy/api/version GET /streamers/1/proxy/api/traffic GET /streamers/1/proxy/api/config GET /streamers/1/proxy/api/v2/files PUT /streamers/1/proxy/api/config
The method, path, query string, and body are all forwarded verbatim. The raw response status and body are passed straight back — no envelope wrapping. When a dedicated handler is built for a path, add it as a named route above the wildcard and the proxy continues to cover everything else.
Node Registration Flow
sequenceDiagram
participant Dev
participant CoreAPI
participant PostgreSQL
Dev->>CoreAPI: POST /streamers { name, host, httpPort, apiPort }
CoreAPI->>PostgreSQL: INSERT streamer record
CoreAPI-->>Dev: 201 { id, status: unknown }
Dev->>CoreAPI: POST /streamers/:id/ping
CoreAPI->>Streamer: GET http://host:apiPort/api/ping
Streamer-->>CoreAPI: 200
CoreAPI->>PostgreSQL: UPDATE status=online, lastPingedAt=now
CoreAPI-->>Dev: 200 { status: online, pingedAt }
Changelog
| Date | Author | Change |
|---|---|---|
| 2026-06-01 | Shida | Decoupled StreamerNode from service.Streamer — resolved import cycle |
| 2026-06-01 | Shida | Added ProxyRequest to StreamerClient, ProxyStreamerRequest handler |
| 2026-05-28 | Shida | Migrated to pkg/response envelope |
| 2026-05-21 | Peach | Added ping endpoint with 5s timeout |
| 2026-05-19 | Peach | Initial streamer CRUD |