alt/services/worker/internal/socket/handlers.go
toki bdbfe8228e feat: scheduled market data refresh - parser_map, refresh status model, CLI output, scheduler backfill, socket handlers
- Add parser_map for market data refresh configuration propagation (cli/worker/api)
- Implement refresh status model with SQLite persistence (status_store.go)
- Add scheduler refresh status headless output to CLI operator
- Extend backfill scheduler with status tracking (start/complete/fail)
- Add socket events for scheduler refresh status (start/complete/fail)
- Update proto definitions for refresh status
- Add generated PB files for client
2026-06-22 18:46:45 +09:00

100 lines
2.8 KiB
Go

package socket
import (
protoSocket "git.toki-labs.com/toki/proto-socket/go"
altv1 "git.toki-labs.com/toki/alt/packages/contracts/gen/go/alt/v1"
)
type sessionHandler struct {
requestType string
register func(*protoSocket.WsClient)
}
// sessionHandlers returns the handlers registered on every worker session.
// Hello is always present; market and backtest command/query handlers attach
// through the same registry instead of bespoke registration paths.
func sessionHandlers(deps Deps) []sessionHandler {
handlers := []sessionHandler{
helloHandler(deps),
}
handlers = append(handlers, marketHandlers(deps)...)
handlers = append(handlers, backtestHandlers(deps)...)
handlers = append(handlers, paperHandlers(deps)...)
handlers = append(handlers, liveHandlers(deps)...)
return handlers
}
// registerSessionHandlers builds the OnClientConnected callback bound to the
// given dependencies.
func registerSessionHandlers(deps Deps) func(*protoSocket.WsClient) {
handlers := sessionHandlers(deps)
return func(client *protoSocket.WsClient) {
registerHandlers(client, handlers)
}
}
func registerHandlers(client *protoSocket.WsClient, handlers []sessionHandler) {
for _, handler := range handlers {
if handler.register == nil {
continue
}
handler.register(client)
}
}
func helloHandler(deps Deps) sessionHandler {
return sessionHandler{
requestType: protoSocket.TypeNameOf(&altv1.HelloRequest{}),
register: func(client *protoSocket.WsClient) {
protoSocket.AddRequestListenerTyped[*altv1.HelloRequest, *altv1.HelloResponse](
&client.Communicator,
func(req *altv1.HelloRequest) (*altv1.HelloResponse, error) {
return handleHello(deps, req)
},
)
},
}
}
func handleHello(deps Deps, req *altv1.HelloRequest) (*altv1.HelloResponse, error) {
protocolVersion := req.GetAltProtocolVersion()
if protocolVersion == "" {
protocolVersion = defaultAltProtocolVersion
}
return &altv1.HelloResponse{
ServerName: serverName,
ServerVersion: serverVersion,
AltProtocolVersion: protocolVersion,
Capabilities: capabilitiesForDeps(deps),
}, nil
}
func capabilitiesForDeps(deps Deps) []string {
caps := []string{"hello"}
if deps.Instruments != nil && deps.Bars != nil {
caps = append(caps, "market-read")
}
if deps.DailyBarImporter != nil {
caps = append(caps, "market-import")
}
if deps.MonthlyAggregator != nil {
caps = append(caps, "monthly-aggregate")
}
if deps.Analysis != nil && deps.Results != nil {
caps = append(caps, "backtest-read")
}
if deps.Starter != nil {
caps = append(caps, "backtest-start", "worker-execution")
}
if deps.Paper != nil {
caps = append(caps, "paper-trading")
}
if deps.Live != nil {
caps = append(caps, "live-trading")
}
if deps.RefreshStatus != nil {
caps = append(caps, "scheduler")
}
return caps
}