No description
  • Python 97.9%
  • Go 0.7%
  • Mako 0.7%
  • Nix 0.7%
Find a file Use this template
hayshin 60f774d450
All checks were successful
CI / generated (push) Successful in 2m51s
CI / go-sdk (push) Successful in 5m32s
CI / python-sdk (push) Successful in 52s
CI / lock (push) Successful in 7s
CI / lint (push) Successful in 1m12s
CI / typecheck (push) Successful in 1m8s
CI / test (push) Successful in 1m3s
CI / package (push) Has been skipped
CI / ci (push) Successful in 0s
ci(proto): verify prebuilt Buf setup
- measure generated SDK drift checks without Nix or Buf compilation
2026-07-18 18:23:33 +05:00
.forgejo/workflows ci(proto): run drift checks on uv runner 2026-07-18 17:26:48 +05:00
deploy feat(sdk): scaffold canonical protobuf clients 2026-07-18 16:57:55 +05:00
migrations feat(pagination): use keyset cursors for item listings 2026-07-17 22:01:46 +05:00
proto/gen/item/v1 feat(sdk): scaffold canonical protobuf clients 2026-07-18 16:57:55 +05:00
scripts feat(sdk): scaffold canonical protobuf clients 2026-07-18 16:57:55 +05:00
sdk feat(sdk): scaffold canonical protobuf clients 2026-07-18 16:57:55 +05:00
src feat(sdk): scaffold canonical protobuf clients 2026-07-18 16:57:55 +05:00
tests feat(sdk): scaffold canonical protobuf clients 2026-07-18 16:57:55 +05:00
.dockerignore feat(sdk): scaffold canonical protobuf clients 2026-07-18 16:57:55 +05:00
.env.example feat(nats): add deployment stream provisioner 2026-07-17 22:11:32 +05:00
.gitignore refactor: streamline microservice template tooling 2026-07-17 21:27:54 +05:00
actionlint.yaml feat(sdk): scaffold canonical protobuf clients 2026-07-18 16:57:55 +05:00
alembic.ini refactor: streamline microservice template tooling 2026-07-17 21:27:54 +05:00
buf.gen.yaml feat(sdk): scaffold canonical protobuf clients 2026-07-18 16:57:55 +05:00
buf.yaml feat(sdk): scaffold canonical protobuf clients 2026-07-18 16:57:55 +05:00
devenv.lock feat(sdk): scaffold canonical protobuf clients 2026-07-18 16:57:55 +05:00
devenv.nix feat(sdk): scaffold canonical protobuf clients 2026-07-18 16:57:55 +05:00
devenv.yaml feat(sdk): scaffold canonical protobuf clients 2026-07-18 16:57:55 +05:00
docker-compose.yml refactor(devenv): reuse shared compose services 2026-07-17 21:45:58 +05:00
LICENSE Create LICENSE 2023-09-06 13:30:56 +06:00
pyproject.toml feat(sdk): scaffold canonical protobuf clients 2026-07-18 16:57:55 +05:00
README.md feat(sdk): scaffold canonical protobuf clients 2026-07-18 16:57:55 +05:00
uv.lock feat(sdk): scaffold canonical protobuf clients 2026-07-18 16:57:55 +05:00

Python microservice reference

Reference gRPC microservice built on platform-pkg. It provides complete Item CRUD backed by PostgreSQL and emits domain events through a transactional outbox relayed to NATS JetStream.

Demonstrated architecture

  • gRPC Item API, health service, optional reflection, shared error mapping, and OpenTelemetry instrumentation
  • transport → service → repository → entity layers
  • explicit SQLAlchemy transaction boundaries through platform_pkg.client.postgres.TransactionManager
  • atomic domain writes and outbox events through platform_pkg.outbox
  • NATS JetStream relay with retries, claims, deduplication IDs, and Prometheus metrics
  • private telemetry listener with liveness, dependency-aware readiness, and metrics
  • dedicated Alembic migrator and JetStream provisioning processes
  • signal-aware graceful shutdown and grouped component lifecycle
  • unit and full PostgreSQL/NATS integration tests
  • non-root production image with migration gating

Quick start

cp .env.example .env
devenv shell
setup
compose-up
migrate
provision
run

Call service through reflection:

grpcurl -plaintext \
  -d '{"name":"widget","type":"ITEM_TYPE_STANDARD"}' \
  localhost:50051 item.v1.ItemService/CreateItem

Telemetry:

curl localhost:8080/health/live
curl localhost:8080/health/ready
curl localhost:8080/metrics/

Development

proto                 # regenerate Python and Go SDK bindings
proto-check           # regenerate, lint, and fail on committed SDK drift
python-sdk-check      # test and build Python SDK distributions
go-sdk-check          # test Go SDK
migration create_item # generate migration revision
migrate               # upgrade database to head
provision             # create or reconcile the service-owned JetStream stream
customize NAME DOMAIN --repository OWNER/REPO # rename service, domain, and SDKs
fmt                    # format and apply Ruff fixes
fmt-check              # check formatting and Ruff rules
typecheck              # run strict mypy checks
test-unit              # run unit tests only
test                   # run all enabled tests; integration tests require opt-in
test-integration       # start PostgreSQL/NATS and run end-to-end tests
build                  # build production image

platform-pkg is consumed from stable tag v0.4.0; uv.lock pins the exact commit. Shared devenv commands and Docker service definitions come from py-pkg; the profile exports PY_PKG_DOCKER_COMPOSE for local Compose extensions.

Layout

proto/gen/item/v1/       protobuf contracts
sdk/go/item/v1/          generated Go client module
sdk/python/               canonical Python client package
src/
  app.py                 dependency wiring and component group
  main.py                signal-aware service entrypoint
  migrator.py            dedicated migration entrypoint
  provisioner.py         dedicated JetStream provisioning entrypoint
  entities/              domain models
  repos/                 transaction-bound PostgreSQL repositories
  services/              business logic and outbox event creation
  transport/grpc/        protobuf controller
  db/models.py           SQLAlchemy schema metadata
migrations/               service and outbox migrations
tests/                    unit and end-to-end integration tests
deploy/                   production image and Compose deployment

Customize template

Run the one-time customization command from a clean working tree:

customize catalog-service product --repository medvoice/catalog
uv lock
proto
fmt
typecheck
test

This derives and updates project, application, image, PostgreSQL schema, JetStream stream, NATS subject, protobuf package, SDK package/module paths, table, migration, and test identities. catalog-service product --repository medvoice/catalog produces schema catalog_service, stream CATALOG_SERVICE, subjects under catalog.product, protobuf package product.v1, Python package medvoice-catalog, and Go module git.hayshin.dev/medvoice/catalog/sdk/go. Python bindings are rebuilt automatically; run proto afterward to regenerate both SDKs.

Plural names default to <domain>s. Supply irregular plurals explicitly:

customize catalog-service category \
  --repository medvoice/catalog \
  --domain-plural categories

Use --subject-namespace NAME to override the subject namespace derived from the service name. The command refuses modified tracked files and already-customized repositories so partial or repeated replacement cannot silently corrupt identity.

Client SDKs

Service code imports protobuf types from canonical package under sdk/python; root pyproject.toml installs it as local path dependency. Consumers pin released SDK tags.

Go nested module:

go get git.hayshin.dev/medvoice/catalog/sdk/go@v0.1.0

Python with uv:

[project]
dependencies = ["medvoice-catalog"]

[tool.uv.sources]
medvoice-catalog = { git = "https://git.hayshin.dev/medvoice/catalog.git", tag = "sdk/python/v0.1.0", subdirectory = "sdk/python" }

Update Python SDK version in sdk/python/pyproject.toml, then run Release Python SDK or Release Go SDK workflow from protected main. Releases use repository tags and attach Python distributions; no package registry is required.

Production

Set production PostgreSQL, NATS, logging, tracing, and reflection values in .env, then run:

docker compose -f deploy/docker-compose.prod.yml up -d --build

Compose runs migration and JetStream provisioning jobs before starting application. For orchestrated deployments, run python -m src.migrator up and python -m src.provisioner as deployment jobs; do not run either independently in every replica. Provisioner reconciles service-owned stream subjects and should use deployment credentials with JetStream management permission. Application credentials need only publish access to configured subject prefix.