Files
go-cart-actor/pkg/cart/recovery/logging_notifier.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

60 lines
1.7 KiB
Go

package recovery
import (
"context"
"log"
"git.k6n.net/mats/go-cart-actor/pkg/cart"
)
// LoggingNotifier is the v0 default: it writes one INFO line per candidate
// and returns nil. It deliberately does NOT pretend to send anything.
//
// Future implementations (MailerSend, FCM, APNs) implement the same Notifier
// interface; the scanner doesn't change. LoggingNotifier also serves as the
// "dry-run" mode in production by leaving the seam unconfigured.
type LoggingNotifier struct{}
// NewLoggingNotifier returns a Notifier that logs every candidate. The struct
// is empty today; the constructor is kept for parity with future notifiers
// that need credentials / config.
func NewLoggingNotifier() *LoggingNotifier { return &LoggingNotifier{} }
// NotifyAbandoned logs the cart id, contact present, and a tiny summary.
// Push tokens are summarized by platform only — never log the raw token, so
// a misconfigured log aggregator can't leak device handles.
func (LoggingNotifier) NotifyAbandoned(_ context.Context, c RecoveryCandidate) error {
hasEmail := c.Email != ""
hasPush := len(c.PushTokens) > 0
channel := "none"
switch {
case hasEmail && hasPush:
channel = "email+push"
case hasEmail:
channel = "email"
case hasPush:
channel = "push"
}
log.Printf(
"recovery [dry-run]: cart=%d user=%q channel=%s items=%d total=%d currency=%s email=%q pushPlatforms=%v lastChangeUnix=%d",
c.CartID,
c.UserID,
channel,
c.ItemCount,
c.TotalIncVat,
c.Currency,
c.Email,
platformsOf(c.PushTokens),
c.LastChangeUnix,
)
return nil
}
func platformsOf(tokens []cart.PushToken) []string {
out := make([]string, 0, len(tokens))
for _, t := range tokens {
out = append(out, t.Platform)
}
return out
}