3.5 KiB
3.5 KiB
go-redis-inventory — agents map
Redis-backed inventory + reservation service. Tracks stock levels and
runs atomic reservation operations via Lua scripts; also consumes an
inventory_changed pub/sub channel to mirror upstream changes.
Where to start
README.md— start here, it has the high-level intent.pkg/inventory/types.go— all the data structures (InventoryItem,InventoryReference,CartReserveRequest, …).pkg/inventory/redis_service.go— basic get / batch get / reserve path- the Lua scripts (
reserveScript,reservationCheck).
- the Lua scripts (
pkg/inventory/redis_reservation_service.go— cart-shaped reservations with release/availability semantics + corresponding_test.go.pkg/inventory/listener.go—InventoryChangeListeneron theinventory_changedpub/sub channel.pkg/inventory/adapter.go—ReservationPolicyAdapterbridging toplatform/inventory.ReservationPolicy.
Architecture
- Two responsibilities, one process: (1) hold and serve inventory state; (2) mirror upstream changes via pub/sub.
- Atomicity: reservation idempotency and TTL semantics come from Lua
scripts embedded here. The scripts are the seam — if they change, the
test in
redis_reservation_service_test.gois the contract. - Adapter: the
ReservationPolicyAdapteris the seam toplatform/inventory. Two adapters (this service and any other downstream caller) is what makes it a real seam, not a hypothetical one.
Important files by area
| Area | File |
|---|---|
| Domain model | pkg/inventory/types.go |
| Core service | pkg/inventory/redis_service.go |
| Reservation service (cart) | pkg/inventory/redis_reservation_service.go |
| Pub/sub listener | pkg/inventory/listener.go |
| Platform adapter | pkg/inventory/adapter.go |
| Reservation tests | pkg/inventory/redis_reservation_service_test.go |
Cross-project seams
platform/inventory: implementsReservationPolicyvia the adapter.go-cart-actor: consumes reservations through that adapter.- Redis pub/sub: receives
inventory_changedevents.
Improvement suggestions
types.gocarries mixed concerns —InventoryItem(storage) sits next toCartReserveRequest(request). Split intotypes/(storage-level) andtypes/cart.go(request) so callers can depend on only the slice they need.- Two reservation services:
redis_service.gohas its own reserve,redis_reservation_service.gohas another, plus aLeveltype (level.go). The relationship between them isn't documented; an architecture paragraph at the top of the package would help (doc.goorpkg/inventory/README.md). listener.gois single-channel — it consumes onlyinventory_changed. If more channels need the same lifecycle (reconnect, dedupe, back-off), factor out a tinypubsub.Consumerand let the listener wrap it.- Lua scripts live inside Go source. Promote them to
.luafiles, registered via//go:embed— that makes them version-controlled and testable independently of the Go code. - No config validation. A malformed
REDIS_URL/CHANNELboots and fails at first call. Fail fast inmain.gowith explicit error messages.