Paper trading readiness에서 API/worker/CLI가 같은 protobuf 계약으로 paper state를 시작하고 조회할 수 있어야 한다. Headless 운영 경로를 먼저 닫기 위해 contract, worker runtime, API forwarding, CLI scenario, client parser map과 검증 artifact를 함께 반영한다.
90 lines
2.5 KiB
Go
90 lines
2.5 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)...)
|
|
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.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")
|
|
}
|
|
return caps
|
|
}
|