package protocol import ( "fmt" "github.com/steveyegge/gastown/internal/mail" ) // Handler processes a protocol message and returns an error if processing failed. type Handler func(msg *mail.Message) error // HandlerRegistry maps message types to their handlers. type HandlerRegistry struct { handlers map[MessageType]Handler } // NewHandlerRegistry creates a new handler registry. func NewHandlerRegistry() *HandlerRegistry { return &HandlerRegistry{ handlers: make(map[MessageType]Handler), } } // Register adds a handler for a specific message type. func (r *HandlerRegistry) Register(msgType MessageType, handler Handler) { r.handlers[msgType] = handler } // Handle dispatches a message to the appropriate handler. // Returns an error if no handler is registered for the message type. func (r *HandlerRegistry) Handle(msg *mail.Message) error { msgType := ParseMessageType(msg.Subject) if msgType == "" { return fmt.Errorf("unknown message type for subject: %s", msg.Subject) } handler, ok := r.handlers[msgType] if !ok { return fmt.Errorf("no handler registered for message type: %s", msgType) } return handler(msg) } // CanHandle returns true if a handler is registered for the message's type. func (r *HandlerRegistry) CanHandle(msg *mail.Message) bool { msgType := ParseMessageType(msg.Subject) if msgType == "" { return false } _, ok := r.handlers[msgType] return ok } // WitnessHandler defines the interface for Witness protocol handlers. // The Witness receives messages from Refinery about merge status. type WitnessHandler interface { // HandleMerged is called when a branch was successfully merged. HandleMerged(payload *MergedPayload) error // HandleMergeFailed is called when a merge attempt failed. HandleMergeFailed(payload *MergeFailedPayload) error // HandleReworkRequest is called when a branch needs rebasing. HandleReworkRequest(payload *ReworkRequestPayload) error } // RefineryHandler defines the interface for Refinery protocol handlers. // The Refinery receives messages from Witness about ready branches. type RefineryHandler interface { // HandleMergeReady is called when a polecat's work is verified and ready. HandleMergeReady(payload *MergeReadyPayload) error } // WrapWitnessHandlers creates mail handlers from a WitnessHandler. func WrapWitnessHandlers(h WitnessHandler) *HandlerRegistry { registry := NewHandlerRegistry() registry.Register(TypeMerged, func(msg *mail.Message) error { payload := ParseMergedPayload(msg.Body) return h.HandleMerged(payload) }) registry.Register(TypeMergeFailed, func(msg *mail.Message) error { payload := ParseMergeFailedPayload(msg.Body) return h.HandleMergeFailed(payload) }) registry.Register(TypeReworkRequest, func(msg *mail.Message) error { payload := ParseReworkRequestPayload(msg.Body) return h.HandleReworkRequest(payload) }) return registry } // WrapRefineryHandlers creates mail handlers from a RefineryHandler. func WrapRefineryHandlers(h RefineryHandler) *HandlerRegistry { registry := NewHandlerRegistry() registry.Register(TypeMergeReady, func(msg *mail.Message) error { payload := ParseMergeReadyPayload(msg.Body) return h.HandleMergeReady(payload) }) return registry } // ProcessProtocolMessage processes a protocol message using the registry. // It returns (true, nil) if the message was handled successfully, // (true, error) if handling failed, or (false, nil) if not a protocol message. func (r *HandlerRegistry) ProcessProtocolMessage(msg *mail.Message) (bool, error) { if !IsProtocolMessage(msg.Subject) { return false, nil } if !r.CanHandle(msg) { return false, nil } err := r.Handle(msg) return true, err }