5.9 KiB
5.9 KiB
go-cart-actor — agents map
The commercial heart of the platform. Orleans-style grain actors for cart,
checkout, order, profile, inventory, plus a UCP (Universal Commerce
Protocol) HTTP adapter at internal/ucp/. Deploys multiple binaries in
parallel (one per concern) coordinated via k8s and an internal actor
discovery/RPC layer. See docs/checkout-order-handoff.md for the role split
with go-order-manager.
Where to start
cmd/cart/main.go— the one most commonly run in dev.pkg/actor/— the grain framework (start withgrain.go, thensimple_grain_pool.goandgrain_pool.go).pkg/cart/cart-grain.go— a concrete grain, the cleanest example.internal/ucp/handler.goanducp/{cart,checkout,order,profile}.go— the protocol adapter over the grains.go-cart-actor/README.md,TODO.md,NEW_MUTATIONS_SPEC.md— current intent and known gaps.
Architecture
- Grain model: each domain entity (cart, order, checkout…) is a grain
keyed by an opaque ID. Per-aggregate state machine lives in the grain's
state.go; mutations are individualmutation_*.gofiles underpkg/<domain>/and registered throughmutation_registry.go. - RPC: gRPC over
proto/—cart.proto,checkout.proto,order.proto,profile.proto,control_plane.proto. Pod discovery viapkg/discovery/+pkg/proxy/remotehost.go(k8s host discovery incmd/<bin>/k8s-host-discovery.go). - Binaries (
cmd/):cart/,checkout/,order/,profile/,inventory/— one each.backoffice/— the admin UI host, plugged intobackofficeviapkg/backofficeadmin/.ucp-artifacts/— emits the protocol artefacts (signing, handler bindings).
- UCP:
internal/ucp/is the protocol adapter — it talks to the grains via RPC, not directly. Separate frompkg/{cart,checkout,…}. - Cross-cutting:
pkg/outbox/,pkg/idempotency/,pkg/flow/,pkg/promotions/,pkg/voucher/,pkg/telemetry/. - Auth:
internal/customerauth/— password hashing (password.go), rate limit, mail notifier, redis store, opaque customer session tokens.
Important files by area
| Area | File(s) |
|---|---|
| Grain framework | pkg/actor/{grain,grain_pool,simple_grain_pool,state,disk_storage}.go |
| Grain RPC | pkg/actor/{grpc_server,grpc_server_test}.go |
| Cart mutations | pkg/cart/mutation_*.go (+ cart-grain.go) |
| Order mutations | pkg/order/mutation_*.go + pkg/order/order-grain.go |
| Order outbox / payment | pkg/order/{emit_created,payment,stripe,klarna}_*.go |
| Promotions / vouchers | pkg/promotions/, pkg/voucher/ |
| Idempotency | pkg/idempotency/store.go |
| Outbox (event publish) | pkg/outbox/outbox.go |
| UCP protocol adapter | internal/ucp/{handler,cart,checkout,order,customer,profile}.go, signing.go |
| Backoffice admin | pkg/backofficeadmin/{app,hub,fileserver,customer}.go |
| Customer auth | internal/customerauth/{server,redis,password,tokens,mail_notifier,ratelimit}.go |
| Telemetry / OTel | pkg/telemetry/{otel,logs}.go |
| k8s service discovery | pkg/discovery/discovery.go, pkg/proxy/remotehost.go, cmd/<bin>/k8s-host-discovery.go |
| Tests integration scaffold | cmd/cart/projection_*_test.go, pkg/promotions/apply_test.go |
Cross-project seams
platform/: usesplatform/auth,platform/catalog,platform/event,platform/inventory,platform/order,platform/tax,platform/rabbit.go-order-manager: subscribes to order events off the RabbitMQ topology (docs/checkout-order-handoff.md).go-shipping: pulled via HTTP fromcart(the cart client).slask-tracking: independent consumer of order events for analytics.backoffice(commerce tag): exposes thepkg/backofficeadmin/host.
Improvement suggestions
- Mutation file explosion: each behavior of a grain lives in its own
mutation_*.go. This is shallow — the deletion test says removing one just moves the same code to its sibling file. Consider grouping related mutations per feature slice (e.g. onecart_subscription.gofor add/remove/upsert subscriptiondetails), so the test surface and locality live together. pkg/cartvsinternal/ucpvspkg/checkout— three layers touch the same conceptual "cart" entity. The UCP adapter depends on the grain, the grain depends on the protocol-specific mutations, and the checkout layer brokers a different view of the cart. Drop the conceptual split here: consider promoting one domain (cart) as the seam and treating the others as adapters.- Inconsistent layout: most binaries are at
cmd/<name>/main.go, butinternal/ucp/,internal/customerauth/, andpkg/voucher/,pkg/outbox/sit at different depths. A short module-layout doc would prevent the next contributor from guessing where new helpers go. TODO.mdandNEW_MUTATIONS_SPEC.mdlive in the repo root. Both belong indocs/so the README is the only thing newcomers hit first.- Two proto variants:
proto/checkout.protoandproto/checkout/checkout.proto. Likely a historical artefact (seeproto/READMEif it exists, otherwise grepproto/forcheckoutto see which is actually imported). - Test coverage is uneven across
pkg/*— vendor-friendly modules likepkg/promotions/have_test.go, others likepkg/voucher/rely onparser_test.goonly. Worth a pass to seed unit tests at each public function entry. cookies.txtat repo root is not a build artefact and shouldn't be committed.