- Python 97.9%
- Go 0.7%
- Mako 0.7%
- Nix 0.7%
|
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
- measure generated SDK drift checks without Nix or Buf compilation |
||
|---|---|---|
| .forgejo/workflows | ||
| deploy | ||
| migrations | ||
| proto/gen/item/v1 | ||
| scripts | ||
| sdk | ||
| src | ||
| tests | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| actionlint.yaml | ||
| alembic.ini | ||
| buf.gen.yaml | ||
| buf.yaml | ||
| devenv.lock | ||
| devenv.nix | ||
| devenv.yaml | ||
| docker-compose.yml | ||
| LICENSE | ||
| pyproject.toml | ||
| README.md | ||
| uv.lock | ||
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.