LOCAL_DEV_SETUP — inventory-service
Sibling: DEPLOYMENT_TOPOLOGY · TESTING_STRATEGY · API_CONTRACTS · DATA_MODEL
Stand up inventory-service locally in under five minutes. The dev stack uses the platform's shared docker-compose.dev.yml plus this service's overrides; no GCP credentials are needed for unit + integration runs.
1. Prerequisites
| Tool | Version | Notes |
|---|---|---|
| Node | 20 LTS | Use volta or nvm |
| pnpm | 9.x | Repo uses pnpm workspaces |
| Docker | 24+ with Compose v2 | docker compose (not docker-compose) |
| direnv | optional | Auto-loads .envrc |
| psql | 15+ | For ad-hoc inspection |
Postman or httpie | latest | API exercising |
Repo root: D:\GhasiTech\Ghasi-edTech\ghasi-melmastoon\ (platform/ workspace).
2. One-time bootstrap
cd D:\GhasiTech\Ghasi-edTech\ghasi-melmastoon\platform\services\inventory-service
pnpm install
cp .env.example .env.local # commit-safe defaults
docker compose -f ..\..\dev\docker-compose.dev.yml up -d postgres pubsub-emulator redis otel-collector
pnpm db:migrate # node-pg-migrate against the dev DB
pnpm db:seed # seed canary tenant + 1 property + 4 room types
postgres exposes 5432; pubsub-emulator exposes 8085; redis exposes 6379; otel-collector exposes 4318.
3. Environment
.env.example ships with safe defaults:
NODE_ENV=development
SERVICE_NAME=inventory-service
SERVICE_VERSION=dev
DATABASE_URL=postgres://inventory:inventory@localhost:5432/melmastoon_dev
DATABASE_SCHEMA=inventory
DATABASE_POOL_MAX=20
PUBSUB_EMULATOR_HOST=localhost:8085
PUBSUB_PROJECT_ID=melmastoon-local
PUBSUB_TOPIC_PREFIX=melmastoon
REDIS_URL=redis://localhost:6379
REDIS_KEY_PREFIX=inventory:
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
OTEL_SERVICE_NAME=inventory-service
JWT_PUBLIC_KEY_URL=http://localhost:9090/.well-known/jwks.json # mock IAM
TENANT_HEADER=X-Tenant-Id
IDEMPOTENCY_TTL_SECONDS=86400
CALENDAR_HORIZON_DAYS=540
HOLD_EXPIRY_DEFAULT_SECONDS=900
ADVISORY_LOCK_TIMEOUT_MS=800
Local secrets land in .env.local (gitignored). .envrc (direnv) merges .env.example and .env.local.
4. Day-to-day commands
| Command | Purpose |
|---|---|
pnpm dev | Start with tsx watch; reloads on TS change; binds :3010 |
pnpm test | Vitest run-once for unit + application |
pnpm test:int | Integration suite under Testcontainers |
pnpm test:concurrency | Concurrency suite (heavier; ~3 min) |
pnpm test:jepsen | Jepsen-style suite (slow; ~10 min; requires Docker) |
pnpm lint | ESLint + Prettier |
pnpm typecheck | tsc --noEmit |
pnpm db:migrate | Apply pending migrations |
pnpm db:reset | Drop + recreate dev DB; reapply migrations + seed |
pnpm seed:tenant -- --tenantId tnt_dev_alpha --rooms 25 | Seed an additional tenant |
pnpm openapi:emit | Regenerate openapi.yaml from controllers |
pnpm events:validate | Validate events/*.schema.json against produced payloads |
5. Useful curl recipes (canary tenant)
# Availability search
curl -X POST http://localhost:3010/api/v1/inventory/availability/search `
-H "Authorization: Bearer $env:DEV_JWT" `
-H "X-Tenant-Id: tnt_dev_alpha" `
-H "Content-Type: application/json" `
-d '{"propertyId":"ppt_dev_main","checkIn":"2026-06-10","checkOut":"2026-06-13","occupancy":{"adults":2}}'
# Walk-in allocation (immediate)
curl -X POST http://localhost:3010/api/v1/inventory/allocations `
-H "Authorization: Bearer $env:DEV_JWT" `
-H "X-Tenant-Id: tnt_dev_alpha" `
-H "Idempotency-Key: $(New-Guid)" `
-H "Content-Type: application/json" `
-d '{"propertyId":"ppt_dev_main","roomTypeId":"rmt_std_dbl","stay":{"checkIn":"2026-06-10","checkOut":"2026-06-12"},"channel":"walk_in"}'
6. Pub/Sub emulator helpers
$env:PUBSUB_EMULATOR_HOST="localhost:8085"
$env:PUBSUB_PROJECT_ID="melmastoon-local"
pnpm pubsub:bootstrap # creates topics + subscriptions per EVENT_SCHEMAS.md
pnpm pubsub:publish reservation.held.v1 .\fixtures\reservation-held.example.json
pnpm pubsub:tail inventory.allocation.confirmed.v1
7. Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
relation "inventory.room_type_inventory_daily_2026_06" does not exist | partition not created for that month | pnpm jobs:rotate-partitions or pnpm db:reset |
MELMASTOON.INVENTORY.LOCK_TIMEOUT on every hold | another process holds the row lock — usually the integration suite running in parallel | stop the other test run; restart pnpm dev |
MELMASTOON.AUTHN.MISSING_JWT | dev JWT expired | pnpm dev:jwt:mint --tenant tnt_dev_alpha --role staff > $env:DEV_JWT_FILE; $env:DEV_JWT = Get-Content $env:DEV_JWT_FILE |
pubsub publish failed: emulator not reachable | emulator not started | docker compose up -d pubsub-emulator |
OOM on pnpm test:jepsen | Docker memory < 6 GB | raise Docker Desktop memory to 8 GB+ |
8. Cross-references
- Migrations: MIGRATION_PLAN
- API contracts to exercise: API_CONTRACTS
- Events to publish/consume locally: EVENT_SCHEMAS
- Reservation local setup: reservation-service LOCAL_DEV_SETUP