order sagas
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
package order
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"git.k6n.net/mats/go-cart-actor/pkg/flow"
|
||||
)
|
||||
|
||||
// Publisher is the minimal seam the amqp_emit hook needs. cmd/order supplies a
|
||||
// RabbitMQ-backed implementation; tests pass a fake. Keeping it an interface
|
||||
// keeps pkg/order free of an AMQP dependency.
|
||||
type Publisher interface {
|
||||
Publish(exchange, routingKey string, body []byte) error
|
||||
}
|
||||
|
||||
// RegisterEmitHook registers the "amqp_emit" flow hook, which publishes a flow
|
||||
// event to a message broker — the bridge from a saga step to other services
|
||||
// (loyalty, ERP sync, notifications) without coupling the flow to them. It is
|
||||
// the commerce analogue of the CMS event listeners. Params (optional):
|
||||
//
|
||||
// {"exchange": "", "routingKey": "order-events"}
|
||||
//
|
||||
// The body is {step, phase, id, error, vars}. With a nil publisher the hook is
|
||||
// still registered (so the editor lists it) but errors at run time — and since
|
||||
// hook errors never abort a flow, that failure is logged, not fatal.
|
||||
func RegisterEmitHook(reg *flow.Registry, pub Publisher) {
|
||||
reg.Hook("amqp_emit", func(_ context.Context, st *flow.State, info flow.HookInfo, params json.RawMessage) error {
|
||||
if pub == nil {
|
||||
return fmt.Errorf("amqp_emit: no publisher configured")
|
||||
}
|
||||
var p struct {
|
||||
Exchange string `json:"exchange"`
|
||||
RoutingKey string `json:"routingKey"`
|
||||
}
|
||||
if len(params) > 0 {
|
||||
if err := json.Unmarshal(params, &p); err != nil {
|
||||
return fmt.Errorf("amqp_emit: bad params: %w", err)
|
||||
}
|
||||
}
|
||||
if p.RoutingKey == "" {
|
||||
p.RoutingKey = "order-events"
|
||||
}
|
||||
errStr := ""
|
||||
if info.Err != nil {
|
||||
errStr = info.Err.Error()
|
||||
}
|
||||
body, _ := json.Marshal(map[string]any{
|
||||
"step": info.Step,
|
||||
"phase": info.Phase,
|
||||
"id": st.ID,
|
||||
"error": errStr,
|
||||
"vars": st.Vars,
|
||||
})
|
||||
return pub.Publish(p.Exchange, p.RoutingKey, body)
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user