routing.go raw

   1  // Package routing provides event routing services for the ORLY relay.
   2  // It dispatches events to specialized handlers based on event kind.
   3  package routing
   4  
   5  import (
   6  	"next.orly.dev/pkg/nostr/encoders/event"
   7  )
   8  
   9  // Action indicates what to do after routing.
  10  type Action int
  11  
  12  const (
  13  	// Continue means continue to normal processing.
  14  	Continue Action = iota
  15  	// Handled means event was fully handled, return success.
  16  	Handled
  17  	// Error means an error occurred.
  18  	Error
  19  )
  20  
  21  // Result contains the routing decision.
  22  type Result struct {
  23  	Action  Action
  24  	Message string // Success or error message
  25  	Error   error  // Error if Action == Error
  26  }
  27  
  28  // ContinueResult returns a result indicating normal processing should continue.
  29  func ContinueResult() Result {
  30  	return Result{Action: Continue}
  31  }
  32  
  33  // HandledResult returns a result indicating the event was fully handled.
  34  func HandledResult(msg string) Result {
  35  	return Result{Action: Handled, Message: msg}
  36  }
  37  
  38  // ErrorResult returns a result indicating an error occurred.
  39  func ErrorResult(err error) Result {
  40  	return Result{Action: Error, Error: err}
  41  }
  42  
  43  // Handler processes a specific event kind.
  44  // authedPubkey is the authenticated pubkey of the connection (may be nil).
  45  type Handler func(ev *event.E, authedPubkey []byte) Result
  46  
  47  // KindCheck tests whether an event kind matches a category (e.g., ephemeral).
  48  type KindCheck struct {
  49  	Name    string
  50  	Check   func(kind uint16) bool
  51  	Handler Handler
  52  }
  53  
  54  // Router dispatches events to specialized handlers.
  55  type Router interface {
  56  	// Route checks if event should be handled specially.
  57  	Route(ev *event.E, authedPubkey []byte) Result
  58  
  59  	// Register adds a handler for a specific kind.
  60  	Register(kind uint16, handler Handler)
  61  
  62  	// RegisterKindCheck adds a handler for a kind category.
  63  	RegisterKindCheck(name string, check func(uint16) bool, handler Handler)
  64  }
  65  
  66  // DefaultRouter implements Router with a handler registry.
  67  type DefaultRouter struct {
  68  	handlers   map[uint16]Handler
  69  	kindChecks []KindCheck
  70  }
  71  
  72  // New creates a new DefaultRouter.
  73  func New() *DefaultRouter {
  74  	return &DefaultRouter{
  75  		handlers:   make(map[uint16]Handler),
  76  		kindChecks: make([]KindCheck, 0),
  77  	}
  78  }
  79  
  80  // Register adds a handler for a specific kind.
  81  func (r *DefaultRouter) Register(kind uint16, handler Handler) {
  82  	r.handlers[kind] = handler
  83  }
  84  
  85  // RegisterKindCheck adds a handler for a kind category.
  86  func (r *DefaultRouter) RegisterKindCheck(name string, check func(uint16) bool, handler Handler) {
  87  	r.kindChecks = append(r.kindChecks, KindCheck{
  88  		Name:    name,
  89  		Check:   check,
  90  		Handler: handler,
  91  	})
  92  }
  93  
  94  // Route checks if event should be handled specially.
  95  func (r *DefaultRouter) Route(ev *event.E, authedPubkey []byte) Result {
  96  	// Check exact kind matches first (higher priority)
  97  	if handler, ok := r.handlers[ev.Kind]; ok {
  98  		return handler(ev, authedPubkey)
  99  	}
 100  
 101  	// Check kind property handlers (ephemeral, replaceable, etc.)
 102  	for _, kc := range r.kindChecks {
 103  		if kc.Check(ev.Kind) {
 104  			return kc.Handler(ev, authedPubkey)
 105  		}
 106  	}
 107  
 108  	return ContinueResult()
 109  }
 110  
 111  // HasHandler returns true if a handler is registered for the given kind.
 112  func (r *DefaultRouter) HasHandler(kind uint16) bool {
 113  	if _, ok := r.handlers[kind]; ok {
 114  		return true
 115  	}
 116  	for _, kc := range r.kindChecks {
 117  		if kc.Check(kind) {
 118  			return true
 119  		}
 120  	}
 121  	return false
 122  }
 123