package protosocket import ( "context" "crypto/rand" "encoding/hex" "fmt" "sync" ) type HandlerFunc func(context.Context, Envelope) Envelope type Dispatcher struct { mu sync.RWMutex handlers map[string]HandlerFunc } func NewDispatcher() *Dispatcher { return &Dispatcher{ handlers: make(map[string]HandlerFunc), } } func (d *Dispatcher) Register(action string, handler HandlerFunc) { d.mu.Lock() defer d.mu.Unlock() d.handlers[action] = handler } func (d *Dispatcher) Dispatch(ctx context.Context, env Envelope) Envelope { d.mu.RLock() handler, ok := d.handlers[env.Action] d.mu.RUnlock() if !ok { return Envelope{ ProtocolVersion: ProtocolVersion, ID: generateID(), CorrelationID: env.ID, Type: "error", Channel: env.Channel, Action: env.Action, Error: &EnvelopeError{ Code: "UNSUPPORTED_ACTION", Message: fmt.Sprintf("unsupported action: %s", env.Action), }, } } return handler(ctx, env) } func generateID() string { b := make([]byte, 16) if _, err := rand.Read(b); err != nil { return "error-id-fallback" } return hex.EncodeToString(b) }