package main import ( "context" "log" "strconv" "time" "git.k6n.net/mats/platform/event" invlevel "git.k6n.net/mats/platform/inventory" "git.k6n.net/mats/platform/rabbit" "github.com/redis/go-redis/v9" ) // emitLevelIfChanged classifies qty into a Level and emits an // inventory.level_changed bus event only when it differs from the level last // emitted for this SKU+location (the levelKey marker). Exact quantity never // leaves the service; only the coarse crossing does. Shared by every write path // (catalog feed, order.created commit). A nil conn (no bus) makes it a no-op. func emitLevelIfChanged(ctx context.Context, rdb *redis.Client, conn *rabbit.Conn, country string, low int64, sku, loc string, qty int64) { if conn == nil { return } lvl := invlevel.LevelFor(qty, low) // Atomic read-old + write-new of the level marker; redis.Nil means the // marker didn't exist yet (first observation), which we treat as a crossing. prev, err := rdb.SetArgs(ctx, levelKey(sku, loc), string(lvl), redis.SetArgs{Get: true}).Result() if err != nil && err != redis.Nil { log.Printf("inventory: level marker sku=%s: %v", sku, err) return } if prev == string(lvl) { return // no threshold crossing — stay off the bus } payload, err := invlevel.LevelChanged{SKU: sku, Location: loc, Level: lvl}.Encode() if err != nil { log.Printf("inventory: encode level payload sku=%s: %v", sku, err) return } ev := event.Event{ ID: "invlvl-" + sku + "-" + loc + "-" + strconv.FormatInt(time.Now().UnixNano(), 36), Type: event.InventoryLevelChanged, Source: "inventory", Subject: sku, Payload: payload, Time: time.Now(), Meta: map[string]string{"country": country}, } if err := rabbit.PublishEvent(conn.Connection(), "inventory", ev); err != nil { log.Printf("inventory: publish level event sku=%s: %v", sku, err) } }