Skip to content

ricountzero/prozess

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Order System

An event-driven order processing system in Go, built as a small choreography-style saga on top of a single Kafka topic. It demonstrates Kafka + Redis + PostgreSQL working together on a realistic e-commerce flow: create order → reserve stock → charge payment → ship, with a compensating action when payment fails.

Architecture

                     ┌─────────────┐
   POST /orders ───▶ │  order-api  │───▶ PostgreSQL (orders, order_items)
                     └──────┬──────┘───▶ Redis (idempotency key, status cache)
                            │ publish OrderCreated
                            ▼
                 ┌──────────────────────┐
                 │   order-events       │   a single Kafka topic,
                 │  (key = order_id)    │   partitioned by order_id
                 └──────────┬───────────┘   => events for one order are
                            │                   processed in order
        ┌───────────────────┼───────────────────┬────────────────────┐
        ▼                   ▼                   ▼                    ▼
 ┌─────────────┐    ┌───────────────┐    ┌───────────────┐   ┌────────────────┐
 │ inventory-  │    │ payment-      │    │ delivery-     │   │ status-updater │
 │ service     │    │ service       │    │ service       │   │                │
 │             │    │               │    │               │   │ writes audit   │
 │ OrderCreated│    │InventoryReserv│    │PaymentComplet.│   │ log + updates  │
 │  -> reserve │    │ -> charge     │    │ -> ship       │   │ orders.status  │
 │  stock      │    │ (random ~15%  │    │               │   │ + Redis cache  │
 │             │    │  decline)     │    │               │   │ (subscribed to │
 │PaymentFailed│    │               │    │               │   │ ALL events)    │
 │ -> release  │    │               │    │               │   │                │
 │  (compensa- │    │               │    │               │   │                │
 │  tion)      │    │               │    │               │   │                │
 └─────────────┘    └───────────────┘    └───────────────┘   └────────────────┘

Every service is an independent consumer group on the same order-events topic, each filtering for the event types it cares about. The Kafka message key is order_id, so all events for a given order land on the same partition and are processed strictly in order.

Order lifecycle

CREATED ─▶ INVENTORY_RESERVED ─▶ PAID ─▶ SHIPPED
   │                │
   └──────┬─────────┘
          ▼
      CANCELLED   (out of stock OR payment declined — in the latter case
                    stock is given back via the compensating
                    InventoryReleased event)

Roles of Kafka / Redis / PostgreSQL

  • Kafka (Redpanda) — the saga's event bus: guarantees event ordering within an order and decouples the services from one another.
  • PostgreSQL — the source of truth: orders, products (with atomic stock reservation via UPDATE ... WHERE stock >= qty), and an audit log of every saga event (order_events) for debugging/history.
  • Redis — 1) idempotency for POST /orders via Idempotency-Key (SETNX), 2) a cache of the current order status for fast GET /orders/{id} without hitting Postgres (cache-aside, kept fresh by status-updater).

Running it

You'll need Go 1.22+ and Docker.

make up      # brings up Redpanda (+ Console on :8081), Postgres, Redis
make seed    # seeds demo products (one product — prod-webcam — has zero stock)

Start the services in four separate terminals (or use tmux/overmind):

make run-api          # HTTP :8080
make run-inventory
make run-payment
make run-status
make run-delivery

Demo walkthrough

# list products
curl -s localhost:8080/products | jq

# create an order (the idempotency key guards against a double form submit)
curl -s -X POST localhost:8080/orders \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: demo-1' \
  -d '{"user_id":"u1","items":[{"product_id":"prod-mouse","qty":2},{"product_id":"prod-keyboard","qty":1}]}'
# => {"order_id":"...","status":"CREATED"}

# check status (the first read may come back CREATED from cache — wait a
# couple of seconds and the saga will reach SHIPPED on its own)
curl -s localhost:8080/orders/<order_id> | jq

# full event history for the order (audit trail)
curl -s localhost:8080/orders/<order_id>/events | jq

# resubmitting with the same Idempotency-Key does not create a second order
curl -s -X POST localhost:8080/orders -H 'Idempotency-Key: demo-1' -d '...'

# a product with zero stock -> the order ends up CANCELLED via InventoryFailed
curl -s -X POST localhost:8080/orders \
  -d '{"user_id":"u1","items":[{"product_id":"prod-webcam","qty":1}]}'

The payment-service declines payment at random (~15%) — create a few orders and you'll see both paths: PAID -> SHIPPED and PaymentFailed -> InventoryReleased -> CANCELLED.

The Redpanda Console at http://localhost:8081 shows raw messages on the order-events topic — handy for watching the JSON envelopes live.

Repository layout

cmd/api           HTTP API: create orders, read status/history/products
cmd/inventory     reserve and release stock
cmd/payment       simulate payment
cmd/delivery      create shipments
cmd/statusupdater single writer of order status + audit log + cache
internal/config   env-based configuration
internal/events   event envelope and payload types
internal/kafkax   producer/consumer wrappers + shared consume loop
internal/db       PostgreSQL access (pgx)
internal/cache    Redis access (idempotency, status cache)
migrations/       DB schema (applied automatically on Postgres' first start)
scripts/seed.sql  demo products

Demo-project limitations

  • A handler that returns an error is logged and the message is committed (skipped) rather than retried — production would need a retry/dead-letter topic here.
  • No metrics/tracing or API authorization — out of scope for this demo.

About

Kafkaesque order-processing saga in Go — Redpanda (Kafka) event choreography, PostgreSQL source of truth, Redis for idempotency & status caching.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors