Cross-Workflow Structure Rules (Prompt-Ready)
Dokumen ini adalah standar struktur folder dan tanggung jawab file untuk apps/worker-workflow/src/cross-workflow.
Tujuan:
- menjaga struktur tetap konsisten dan mudah diikuti tim
- memudahkan refactor tanpa mengubah behavior runtime
- menjadi prompt/aturan kerja saat mengembangkan feature
cross-workflow
1. Prinsip Utama
Gunakan pola:
context-first(feature module)flat(hindari nested layer berlebihan jika belum perlu)nama file menjelaskan peran
Konsep yang dipakai:
consumer= adapter transport (JetStream/NATS,ack/nak)service= use-case utama cross-workflowcontracts= boundary agreement (type,interface, DTO)utils= pure function/helper tanpa DI- custom decorator JetStream:
@JetStreamConsumer(...)= metadata subscribe (class-level)@MessageHandler()= penanda method handler message (method-level)
2. Struktur Folder Standar
apps/worker-workflow/src/cross-workflow/
├── cross-workflow.module.ts
├── constants/
├── contracts/
├── docs/
├── services/
└── utils/
Aturan:
services/cukup flat selama hanya ada 1 consumer + 1 service utamacontracts/tetap di root (bukan diservices)utils/tetap di root untuk pure helperdocs/berisi behavior dan aturan (bukan runtime source)
3. Tanggung Jawab Tiap Folder
3.1 constants/
- konstanta subject, consumer group, durable, deliver
- tidak berisi logic runtime
3.2 contracts/
- payload/contract boundary antar komponen
- boleh berisi
type/interface/DTO/abstract contract - tidak boleh berisi query DB / business logic /
@Injectable()
Contoh saat ini:
cross-workflow.contract.ts
3.3 services/
*.consumer.tsuntuk adapter transport*.service.tsuntuk use-case utama- test colocated (
*.spec.ts)
3.4 utils/
- helper pure function (contoh normalisasi relation type)
- tidak mengakses DB/NATS
3.5 docs/
- system behavior, struktur aturan, catatan pengembangan
4. Aturan Naming File
-
*.consumer.ts- adapter transport
- contoh:
cross-workflow.consumer.ts
-
*.service.ts- use-case utama / orchestration bisnis
- contoh:
cross-workflow.service.ts
-
*.contract.ts- boundary contract (
type/interface/DTO) - contoh:
cross-workflow.contract.ts
- boundary contract (
-
*.spec.ts- test colocated dengan runtime file
-
*.util.ts- pure utility function
- contoh:
relation-type.util.ts
5. Pembagian Tanggung Jawab File (Penting)
5.1 consumer
Boleh:
- deklarasi metadata subscribe via
@JetStreamConsumer(...) - decode CDC payload
- filter event minimum (table/op/id)
- mapping CDC -> trigger payload
- manual
ack/nak - memanggil
CrossWorkflowService.execute(...)
Tidak boleh:
- query DB kompleks
- transaksi bisnis lintas tabel
- logic readiness/target resolution
Catatan pola current:
- bootstrap/registrasi consumer dijalankan
JetStreamConsumerRegistryService waitUntilReady()dijalankan registry (berdasarkan metadata consumer)consumertetap pegang manualack/nakdi@MessageHandler()
5.2 service
Boleh:
- transaction boundary (
QueryRunner) - source/target submission query
- resolve connection config
- relation-type branching (
ONE_TO_MANY,MANY_TO_ONE) - readiness check
- trigger target via
SubmissionServiceV2
Tidak boleh:
- subscribe/ack/nak concern
- decode raw CDC payload
5.3 utils
Boleh:
- normalisasi nilai config (mis.
relationType)
Tidak boleh:
- akses DB
- DI Nest
6. Aturan Penempatan Type (Hitam Putih)
- Boundary payload/event lintas file/module ->
contracts/*.contract.ts - Type internal yang hanya dipakai test -> simpan di
*.spec.ts - Hindari top-level
type/interfacedi runtime file kecuali benar-benar trivial dan lokal - Jika internal type reusable mulai banyak, buat
contracts/internal/*.types.ts
Contoh:
CrossWorkflowTriggerPayload->contracts/cross-workflow.contract.ts
7. Pola Custom Decorator Untuk Consumer (Standar Saat Ini)
Gunakan pola ini untuk consumer JetStream:
- Class consumer diberi
@JetStreamConsumer({...}) - Method handler message diberi
@MessageHandler() consumerOpts()chain tetap ditulis di file consumer (readable)- Manual
ack/naktetap ditulis di method handler - Jangan implement
OnApplicationBootstrap/OnModuleDestroyjika memakai registry
7.1 Contoh ringkas
@JetStreamConsumer({
name: 'Cross Workflow Trigger',
subject: String(CROSS_WORKFLOW_CONSUMER.SUBJECT),
waitUntilReady: true,
unhandledErrorNakDelayMs: 8000,
buildOpts: () =>
consumerOpts()
.durable(CROSS_WORKFLOW_CONSUMER.DURABLE)
.deliverGroup(CROSS_WORKFLOW_CONSUMER.GROUP)
.deliverTo(CROSS_WORKFLOW_CONSUMER.DELIVER)
.manualAck()
.ackExplicit()
.deliverNew()
.maxDeliver(CROSS_WORKFLOW_CONSUMER.MAX_REDELIVERY),
})
@Injectable()
export class CrossWorkflowConsumer {
constructor(private readonly service: CrossWorkflowService) {}
@MessageHandler()
async handle(msg: JetStreamConsumableMessage) {
// decode -> filter -> map -> service.execute -> ack/nak
}
}
7.2 Registry yang wajib tersedia di module
- import
DiscoveryModule(@nestjs/core) - register
JetStreamConsumerRegistryServicesebagai provider module
8. Aturan Refactor (Safety Rules)
Saat refactor:
- utamakan behavior-preserving
- ubah struktur/naming dulu, jangan ubah behavior bisnis sekaligus
- setelah perubahan:
- update import path
- jalankan typecheck worker-workflow
- jalankan test
cross-workflow
Checklist minimum:
pnpm exec tsc -p apps/worker-workflow/tsconfig.json --noEmitpnpm exec jest apps/worker-workflow/src/cross-workflow/services/cross-workflow.consumer.spec.ts apps/worker-workflow/src/cross-workflow/services/cross-workflow.service.spec.ts packages/lib/src/service/nats/jetstream-consumer/jetstream-consumer-registry.service.spec.ts --runInBand
9. Prompt Refactor (Siap Pakai)
Refactor folder/file di `apps/worker-workflow/src/cross-workflow` mengikuti aturan:
- context-first
- struktur flat (`constants`, `contracts`, `services`, `utils`, `docs`)
- transport adapter memakai suffix `*.consumer.ts`
- use-case utama memakai suffix `*.service.ts`
- boundary payload/type berada di `contracts/*.contract.ts`
- util pure function berada di `utils/*.util.ts`
- jika consumer memakai JetStream:
- gunakan `@JetStreamConsumer(...)` pada class
- gunakan `@MessageHandler()` pada method handler
- simpan `consumerOpts()` chain dan manual `ack/nak` di file consumer
- jangan ubah behavior runtime kecuali diminta
Setelah refactor:
1. update import path
2. jalankan typecheck worker-workflow
3. jalankan test `cross-workflow`
4. laporkan file yang dipindah/diubah dan risiko perubahan
10. Prompt Pengembangan Behavior Baru (Siap Pakai)
Tambahkan behavior baru di feature `apps/worker-workflow/src/cross-workflow` dengan aturan:
- filter CDC dan decode tetap di `cross-workflow.consumer.ts`
- transaksi, query, dan orchestration bisnis di `cross-workflow.service.ts`
- payload boundary baru ditaruh di `contracts/*.contract.ts`
- helper pure function ditaruh di `utils/*.util.ts`
- pertahankan manual `ack/nak` di consumer
- pertahankan behavior-preserving untuk flow lama
Setelah implementasi:
1. update/ tambah test consumer dan service
2. jalankan typecheck worker-workflow
3. laporkan perubahan behavior (jika ada)