Files
go-cart-actor/pkg/cart/recovery/recovery.go
T
mats 26fd6dc970
Build and Publish / BuildAndDeployArm64 (push) Failing after 6s
Build and Publish / BuildAndDeployAmd64 (push) Failing after 4s
more cart
2026-07-01 22:11:37 +02:00

50 lines
2.1 KiB
Go

// Package recovery is the v0 abandoned-cart-recovery seam.
//
// The contract is intentionally narrow: a Scanner finds candidates whose last
// mutation is within an "abandoned" window and that have BOTH an attachable
// contact (email and/or push tokens) and items in the cart, then hands them
// to a Notifier. The Notifier decides what to do — for now a logging shim.
//
// The seam intentionally avoids:
//
// - Email/push-token delivery (lives in the notifier impl).
// - Idempotency tracking ("did we already notify?"). v0: scanner windows
// are sized so a cart falls in once per detection threshold. Real
// idempotency is the next pass — see suggest_followups / plan-commerce-
// maturity C3.
// - Cross-pod coordination. Each cart pod owns its own shard of event logs
// (replicated read cache, no leader), so per-pod scanning is correct.
// A future AMQP fan-out of `cart.recovery.candidate` would let a single
// dedicated notifier consume instead — out of scope here.
package recovery
import (
"context"
"git.k6n.net/mats/go-cart-actor/pkg/cart"
)
// RecoveryCandidate is the projectable "we'd remind this shopper" shape.
// Fields surface just enough for a future email template / push payload; the
// underlying grain carries everything else.
type RecoveryCandidate struct {
CartID cart.CartId
UserID string // empty if the cart hasn't been linked to a profile
Email string
PushTokens []cart.PushToken
ItemCount int
TotalIncVat int64 // minor units (money.Cents == int64)
Currency string
// LastChange is best-effort: the scanner reads the event-log file's
// modification time. A pending notifier shouldn't use it as the canonical
// "when was this cart touched?" wall clock — see cart.LastChange.
LastChangeUnix int64
}
// Notifier is the seam a real email/push implementation plugs into. The
// LoggingNotifier is the v0 default. The cart service ships the seam even
// before a real send exists so call-sites and tracking can be wired once.
type Notifier interface {
NotifyAbandoned(ctx context.Context, c RecoveryCandidate) error
}