บทที่ 28 · Part 7 — Production Engineering

Production Readiness Capstone

รวม OpenAPI, Chi, MySQL, Redis, worker, tests, observability และ operational limits ในบริการเดียว

บทที่ผ่านมาแยกปัญหาเพื่อเรียน แต่ production service ต้องให้ contract, ownership, cancellation, data, concurrency, tests และ operations ทำงานร่วมกัน Capstone นี้จึงไม่ได้เพิ่ม pattern ใหม่ มันบังคับให้ทุก decision ต่อกันได้ตั้งแต่ OpenAPI request จนถึง shutdown โดยไม่มี “เดี๋ยว production ค่อยเติม”

จบบทนี้คุณจะ

  • วาง architecture ของ Settlement Job Service ด้วย defaults จากทั้งคอร์ส
  • สร้าง implementation plan ที่เดินเป็น vertical slices และพิสูจน์ได้ทีละช่วง
  • ใช้ production readiness checklist ตัดสินว่า service พร้อมรับงานหรือยัง

Target Architecture

Client ส่ง idempotency key เพื่อสร้าง settlement batch API validate contract แล้ว transaction ใน MySQL บันทึก batch กับ outbox eventพร้อมกัน Dispatcher ใช้ event เริ่ม Temporal Workflow แบบ idempotent Activities ประมวลผลและเขียน authoritative statusกลับ MySQL ส่วน Redis เก็บ read model ที่สร้างใหม่ได้

Redis miss ต้อง fallback ไป MySQL และ decision ที่เปลี่ยนเงิน/สถานะธุรกิจอ่าน authoritative data เท่านั้น Outbox ป้องกัน dual-write gap ระหว่าง MySQL commit กับ workflow start แต่ยังต้องมี dispatcher retry, deduplication และ reconciliation เพราะไม่มี exactly-once ข้ามระบบ

Policy ที่เกี่ยวกับเงินจริง

settlement window, amount limit, maker-checker, reconciliation tolerance และ retention ต้องมาจาก business/compliance owner พร้อมเอกสารและวันที่ ตัวอย่างนี้ใช้ integer minor unitสำหรับจำนวนเงิน และสอนตำแหน่งวาง control เท่านั้น ไม่ได้กำหนด policy ให้ระบบจริงหรือรับรอง compliance

Course Defaults ที่ต้องอธิบายได้

BoundaryDefaultเหตุผลหลัก
HTTPnet/http + Chistdlib compatibility และ middleware model เล็ก
ContractOpenAPI 3.0 + oapi-codegen strict + validatortyped request/response และ spec-first workflow
Applicationconcrete service + consumer-owned portsdependency direction และ testability
MySQLdatabase/sql + go-sql-driver/mysqlexplicit SQL และ mature pool
Redisgo-redis/v9maintained client พร้อม pooling
Async orchestrationTemporal Workflow + Activitiesdurable multi-step lifecycle; I/O อยู่ Activity
DImanual wiring; samber/do เมื่อ graph/lifecycleคุ้มexplicit ก่อน container
Errorsstdlib errors; samber/oops เมื่อ structured contextจำเป็นstable vocabulary ก่อน stack/metadata
Teststesting, go-cmp, httptest, testcontainers-go, synctestbehaviorตั้งแต่ unitถึง runtime boundary
Observabilityslog, Prometheus, OpenTelemetry, secured pprofsignals เชื่อม contextเดียวกัน

ตารางนี้ไม่ใช่ shopping list Dependency ใดที่ projectไม่ใช้ต้องตัดออก เช่นถ้าไม่มี complex DI graph ไม่ต้องเพิ่ม samber/do; ถ้าไม่มี Redis read latency requirement ให้เริ่มจาก MySQL source เดียว

Package และ Binary Boundaries

โครงเริ่มต้นที่ตั้งใจให้เรียบง่าย:

cmd/api/                  HTTP composition root
cmd/worker/               dispatcher and Temporal Worker composition root
internal/settlement/      use cases, domain vocabulary, consumer ports
internal/httpapi/         generated transport and handler adapters
internal/mysql/           batch, outbox and transaction adapters
internal/redisstatus/     derived status adapter
internal/temporalworker/  workflows and activities

settlement ไม่ import Chi, generated OpenAPI types, MySQL driver, Redis หรือ Temporal SDK adapter HTTP/worker binaries share application packagesแต่มี config, pool และ lifecycle ต่างกันตาม runtime

สร้างเป็น Vertical Slices

Slice 1 — Contract และ Pure Rules

นิยาม OpenAPI create/get endpoints, stable error responses และ application request/result เขียน unit tests ของ validation/status transition ด้วย builders ที่ deterministic ยังไม่ต่อ network

Slice 2 — HTTP to Application

Generate strict interfaces, เพิ่ม request validator/auth placeholder ที่มี owner, map DTO ↔ application types และทดสอบด้วย httptest ครอบคลุม body limit, invalid schema, error mapping และ cancellation

Slice 3 — Authoritative Persistence

เพิ่ม MySQL adapterและ transaction ที่บันทึก batch+outboxพร้อมกัน Parameterized SQL, context และ domain error translation ต้องครบ Integration test ผ่าน testcontainers-go พิสูจน์ constraints, rollback, duplicate idempotency key และ rows cleanup

Slice 4 — Durable Processing และ Read Model

Dispatcher start workflowด้วย stable workflow/idempotency identity Activities ถือ injected DB/Redis clients และถูกออกแบบให้ retry safe Redis update เป็น derived projection; test cache miss/fallback และ rebuild แยก Temporal SDK tests ตามแนวทางใน Testing

Slice 5 — Capacity และ Operations

ตั้ง HTTP/Activity concurrency, DB/Redis pools และ queue bounds จาก fleet budget เพิ่ม structured logs, metrics/traces, readiness, graceful shutdown, race/integration/load tests จากนั้นเก็บ CPU/heap/trace baseline ก่อน optimize

Failure Walkthrough ที่ต้องตอบได้

ทีมต้องอธิบายกรณี crash ทุกช่อง: หลัง commitก่อน response client retryจะพบ idempotency record; หลัง start workflowก่อน mark delivered dispatcher retryแล้ว Temporal identityป้องกัน duplicate orchestration; Activity side effect ยังต้องมี idempotency ของตัวเอง ไม่สรุปว่า Temporalทำให้ external API exactly-once

Acceptance Evidence

  • go test ./..., go vet ./..., static analysis และ govulncheck ผ่านบน pinned tools
  • CI รัน supported Go 1.25.x/1.26.x และ race job
  • OpenAPI generated diff reproducible และ contract tests ครบ success/failure
  • MySQL/Redis integration tests isolated และ cleanupได้
  • worker tests ครอบคลุม retry, cancel, concurrency limit, shutdown และ leak
  • load test แสดง saturation behavior เมื่อ DB pool/queueเต็ม ไม่ใช่เฉพาะ throughputสูงสุด
  • dashboard เห็น request/error/latency, DB wait, Redis timeout, outbox age, worker slots และ job outcome
  • runbook มี deploy/rollback, stuck outbox, cache rebuild, dependency outage และ graceful shutdown
  • performance claim มี baseline/profile/benchstat หรือถูกลบออก

Definition of Done

Service พร้อม production เมื่อทีมตอบได้ว่า request หนึ่งมี contract อะไร, state authoritative อยู่ไหน, งานลูกหยุดอย่างไร, overload ถูกส่งกลับแบบใด, failure ใด retry ได้, signals ใดพาไปถึง root cause และหลักฐานใดพิสูจน์คำตอบเหล่านั้น ไม่ใช่เมื่อเลือก library ครบทุกชื่อในคอร์ส

ทางไปต่อ

ทบทวน HTTP APIs, Unit Testing, Runtime-Aware Data Clients และ Service Lifecycle จาก decision ที่ Capstone เปิดเผย หาก workload ต้องการ Temporal จริง ให้เรียน Temporal for Fintech ต่อเพื่อเข้าใจ determinism, retries, versioning และ production operations ในระดับ SDK/platform