@@ -5,36 +5,72 @@ import (
55 "encoding/json"
66)
77
8- // Handler processes a typed payload. This is the primary interface to implement.
8+ // Proc (procedure) processes a message without returning a result.
9+ // Use this for fire-and-forget patterns like event handlers.
910//
10- // The type parameter T is the payload type that the handler expects. The router
11- // automatically unmarshals the raw JSON payload to this type and validates it
12- // if T implements validation.Validatable.
11+ // The type parameter T is the payload type. The router automatically
12+ // unmarshals JSON to T and validates it if T implements Validate() error.
1313//
1414// Example:
1515//
16- // type UserCreatedHandler struct {
16+ // type UserCreatedProc struct {
1717// db *sql.DB
1818// }
1919//
20- // func (h *UserCreatedHandler) Handle (ctx context.Context, p UserCreatedPayload) error {
21- // _, err := h .db.ExecContext(ctx, "INSERT INTO users ...", p .UserID, p.Email )
20+ // func (p *UserCreatedProc) Run (ctx context.Context, payload UserCreatedPayload) error {
21+ // _, err := p .db.ExecContext(ctx, "INSERT INTO users ...", payload .UserID)
2222// return err
2323// }
24- type Handler [T any ] interface {
25- Handle (ctx context.Context , payload T ) error
24+ type Proc [T any ] interface {
25+ Run (ctx context.Context , payload T ) error
2626}
2727
28- // HandlerFunc is a function adapter for Handler . Use this for simple handlers
28+ // ProcFunc is a function adapter for Proc . Use for simple procedures
2929// that don't need a struct:
3030//
31- // dispatch.RegisterFunc (r, "ping ", func(ctx context.Context, p PingPayload ) error {
31+ // dispatch.RegisterProc (r, "user/created ", func(ctx context.Context, p Payload ) error {
3232// return nil
3333// })
34- type HandlerFunc [T any ] func (ctx context.Context , payload T ) error
34+ type ProcFunc [T any ] func (ctx context.Context , payload T ) error
3535
36- // Handle implements the Handler interface.
37- func (f HandlerFunc [T ]) Handle (ctx context.Context , payload T ) error {
36+ // Run implements the Proc interface.
37+ func (f ProcFunc [T ]) Run (ctx context.Context , payload T ) error {
38+ return f (ctx , payload )
39+ }
40+
41+ // Func (function) processes a message and returns a typed result.
42+ // Use this for request-response patterns like Step Functions tasks.
43+ //
44+ // The type parameters are: T for input payload, R for result.
45+ // The router automatically unmarshals T, validates it, and marshals R.
46+ //
47+ // Example:
48+ //
49+ // type LookupUserFunc struct {
50+ // client IdentityClient
51+ // }
52+ //
53+ // func (f *LookupUserFunc) Call(ctx context.Context, in LookupInput) (*LookupResult, error) {
54+ // user, err := f.client.GetUser(ctx, in.UserID)
55+ // if err != nil {
56+ // return nil, err
57+ // }
58+ // return &LookupResult{Email: user.Email}, nil
59+ // }
60+ type Func [T , R any ] interface {
61+ Call (ctx context.Context , payload T ) (R , error )
62+ }
63+
64+ // FuncFunc is a function adapter for Func. Use for simple functions
65+ // that don't need a struct:
66+ //
67+ // dispatch.RegisterFunc(r, "lookup-user", func(ctx context.Context, in Input) (*Result, error) {
68+ // return &Result{...}, nil
69+ // })
70+ type FuncFunc [T , R any ] func (ctx context.Context , payload T ) (R , error )
71+
72+ // Call implements the Func interface.
73+ func (f FuncFunc [T , R ]) Call (ctx context.Context , payload T ) (R , error ) {
3874 return f (ctx , payload )
3975}
4076
@@ -49,6 +85,7 @@ func (f HandlerFunc[T]) Handle(ctx context.Context, payload T) error {
4985// - SNS notifications
5086// - Step Functions task tokens
5187// - Kinesis records
88+ // - SQS messages
5289// - Custom formats
5390//
5491// Example:
@@ -61,18 +98,15 @@ func (f HandlerFunc[T]) Handle(ctx context.Context, payload T) error {
6198// return dispatch.HasFields("type", "payload")
6299// }
63100//
64- // func (s *mySource) Parse(raw []byte) (dispatch.Parsed , error) {
101+ // func (s *mySource) Parse(raw []byte) (dispatch.Message , error) {
65102// var env struct {
66103// Type string `json:"type"`
67104// Payload json.RawMessage `json:"payload"`
68105// }
69106// if err := json.Unmarshal(raw, &env); err != nil {
70- // return dispatch.Parsed {}, err
107+ // return dispatch.Message {}, err
71108// }
72- // if env.Type == "" {
73- // return dispatch.Parsed{}, errors.New("missing type field")
74- // }
75- // return dispatch.Parsed{Key: env.Type, Payload: env.Payload}, nil
109+ // return dispatch.Message{Key: env.Type, Payload: env.Payload}, nil
76110// }
77111type Source interface {
78112 // Name returns the source identifier for logging and metrics.
@@ -84,39 +118,39 @@ type Source interface {
84118 Discriminator () Discriminator
85119
86120 // Parse attempts to parse raw bytes as this source's format.
87- // Returns the parsed result and nil if successful, or an error describing
88- // why parsing failed.
89- Parse (raw []byte ) (Parsed , error )
121+ // Returns the parsed message and nil if successful, or an error
122+ // describing why parsing failed.
123+ Parse (raw []byte ) (Message , error )
90124}
91125
92126// SourceFunc creates a Source from a name, discriminator, and parse function.
93- // Use this for simple sources that don't need a struct:
127+ // Use for simple sources that don't need a struct:
94128//
95129// r.AddSource(dispatch.SourceFunc(
96130// "legacy",
97131// dispatch.HasFields("type", "payload"),
98- // func(raw []byte) (dispatch.Parsed , error) {
132+ // func(raw []byte) (dispatch.Message , error) {
99133// // parse logic
100134// },
101135// ))
102- func SourceFunc (name string , disc Discriminator , parse func ([]byte ) (Parsed , error )) Source {
136+ func SourceFunc (name string , disc Discriminator , parse func ([]byte ) (Message , error )) Source {
103137 return & sourceFunc {name : name , disc : disc , parse : parse }
104138}
105139
106140type sourceFunc struct {
107141 name string
108142 disc Discriminator
109- parse func ([]byte ) (Parsed , error )
143+ parse func ([]byte ) (Message , error )
110144}
111145
112- func (s * sourceFunc ) Name () string { return s .name }
113- func (s * sourceFunc ) Discriminator () Discriminator { return s .disc }
114- func (s * sourceFunc ) Parse (raw []byte ) (Parsed , error ) { return s .parse (raw ) }
146+ func (s * sourceFunc ) Name () string { return s .name }
147+ func (s * sourceFunc ) Discriminator () Discriminator { return s .disc }
148+ func (s * sourceFunc ) Parse (raw []byte ) (Message , error ) { return s .parse (raw ) }
115149
116- // Parsed contains the result of source parsing.
117- type Parsed struct {
150+ // Message contains the result of source parsing.
151+ type Message struct {
118152 // Key is the routing key used to find the handler.
119- // This is matched against keys passed to Register .
153+ // This is matched against keys passed to RegisterProc/RegisterFunc .
120154 Key string
121155
122156 // Version is the schema version of the payload, if available.
@@ -126,12 +160,26 @@ type Parsed struct {
126160 // Payload is the raw JSON to unmarshal into the handler's type.
127161 Payload json.RawMessage
128162
129- // Complete is called after the handler finishes, regardless of success or failure.
130- // Use this for transport-specific completion semantics like Step Functions
131- // SendTaskSuccess/SendTaskFailure.
163+ // Replier handles sending responses back to the caller.
164+ // For fire-and-forget sources (EventBridge, SNS), this is nil.
165+ // For request-response sources (Step Functions), this sends results back.
166+ //
167+ // When Replier is set and a Func is registered:
168+ // - On success: router marshals result and calls Replier.Reply
169+ // - On error: router calls Replier.Fail
132170 //
133- // If Complete is nil, no completion callback is made.
134- // If Complete returns an error, that error is returned from Process.
135- // The err parameter is the handler's error (or nil on success).
136- Complete func (ctx context.Context , err error ) error
171+ // When Replier is set and a Proc is registered:
172+ // - On success: router calls Replier.Reply with empty JSON ({})
173+ // - On error: router calls Replier.Fail
174+ Replier Replier
175+ }
176+
177+ // Replier sends responses back to the message originator.
178+ // Implement this for request-response transport patterns.
179+ type Replier interface {
180+ // Reply sends a successful response with the given JSON payload.
181+ Reply (ctx context.Context , result json.RawMessage ) error
182+
183+ // Fail sends a failure response with the given error.
184+ Fail (ctx context.Context , err error ) error
137185}
0 commit comments