all the refactor
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
package order
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"git.k6n.net/mats/go-cart-actor/pkg/flow"
|
||||
"git.k6n.net/mats/platform/event"
|
||||
contract "git.k6n.net/mats/platform/order"
|
||||
)
|
||||
|
||||
// RegisterOrderCreatedEmit registers the "emit_order_created" flow hook: it
|
||||
// publishes an event.OrderCreated envelope (payload contract.Created) for the
|
||||
// order, reading the grain via app and publishing durably via pub.
|
||||
//
|
||||
// It is a HOOK, not an action, on purpose: hook errors are logged, never abort
|
||||
// the flow. The order is already placed and paid by the time this fires, so a
|
||||
// transient publish hiccup must not roll it back — and pub is the durable outbox
|
||||
// (a local fsync'd append), so "failure" here means disk error, then the relay
|
||||
// retries delivery on its own. With a nil publisher (dev without AMQP) it is a
|
||||
// no-op. Attach it to the "after" hooks of the final paid step, e.g. capture.
|
||||
func RegisterOrderCreatedEmit(reg *flow.Registry, app Applier, pub Publisher, exchange, source string) {
|
||||
reg.Hook("emit_order_created", func(ctx context.Context, st *flow.State, _ flow.HookInfo, _ json.RawMessage) error {
|
||||
if pub == nil {
|
||||
return nil // no broker configured (dev)
|
||||
}
|
||||
o, err := app.Get(ctx, st.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
created := buildOrderCreated(o)
|
||||
if len(created.Lines) == 0 {
|
||||
return nil // nothing for a reactor to act on
|
||||
}
|
||||
payload, err := created.Encode()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ev := event.Event{
|
||||
ID: "order-created-" + created.OrderID,
|
||||
Type: event.OrderCreated,
|
||||
Source: source,
|
||||
Subject: created.OrderID,
|
||||
Payload: payload,
|
||||
Time: time.Now(),
|
||||
Meta: map[string]string{"country": created.Country},
|
||||
}
|
||||
body, err := json.Marshal(ev)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return pub.Publish(exchange, string(event.OrderCreated), body)
|
||||
})
|
||||
}
|
||||
|
||||
// buildOrderCreated projects the grain onto the exported order.created contract.
|
||||
// Lines carry only SKU + quantity (what reactors need); inventory commits at the
|
||||
// order's Country location.
|
||||
func buildOrderCreated(o *OrderGrain) contract.Created {
|
||||
lines := make([]contract.Line, 0, len(o.Lines))
|
||||
for _, l := range o.Lines {
|
||||
if l.Sku == "" || l.Quantity <= 0 {
|
||||
continue
|
||||
}
|
||||
lines = append(lines, contract.Line{SKU: l.Sku, Quantity: l.Quantity, Location: l.Location})
|
||||
}
|
||||
return contract.Created{
|
||||
OrderID: OrderId(o.Id).String(),
|
||||
OrderReference: o.OrderReference,
|
||||
CartID: o.CartId,
|
||||
Country: o.Country,
|
||||
Currency: o.Currency,
|
||||
CustomerEmail: o.CustomerEmail,
|
||||
Lines: lines,
|
||||
PlacedAtMs: nowMs(),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user