Skip to main content

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

ToolVersionNotes
Node20 LTSUse volta or nvm
pnpm9.xRepo uses pnpm workspaces
Docker24+ with Compose v2docker compose (not docker-compose)
direnvoptionalAuto-loads .envrc
psql15+For ad-hoc inspection
Postman or httpielatestAPI 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

CommandPurpose
pnpm devStart with tsx watch; reloads on TS change; binds :3010
pnpm testVitest run-once for unit + application
pnpm test:intIntegration suite under Testcontainers
pnpm test:concurrencyConcurrency suite (heavier; ~3 min)
pnpm test:jepsenJepsen-style suite (slow; ~10 min; requires Docker)
pnpm lintESLint + Prettier
pnpm typechecktsc --noEmit
pnpm db:migrateApply pending migrations
pnpm db:resetDrop + recreate dev DB; reapply migrations + seed
pnpm seed:tenant -- --tenantId tnt_dev_alpha --rooms 25Seed an additional tenant
pnpm openapi:emitRegenerate openapi.yaml from controllers
pnpm events:validateValidate 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

SymptomLikely causeFix
relation "inventory.room_type_inventory_daily_2026_06" does not existpartition not created for that monthpnpm jobs:rotate-partitions or pnpm db:reset
MELMASTOON.INVENTORY.LOCK_TIMEOUT on every holdanother process holds the row lock — usually the integration suite running in parallelstop the other test run; restart pnpm dev
MELMASTOON.AUTHN.MISSING_JWTdev JWT expiredpnpm 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 reachableemulator not starteddocker compose up -d pubsub-emulator
OOM on pnpm test:jepsenDocker memory < 6 GBraise Docker Desktop memory to 8 GB+

8. Cross-references