vibes-plug 2.11.0 → 2.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cursor/rules/vibes-plug-core.mdc +3 -3
- package/.cursorrules +3 -3
- package/AGENTS.md +4 -4
- package/BLUEPRINT.md +16 -6
- package/CHANGELOG.md +37 -0
- package/CLAUDE.md +8 -8
- package/README.md +85 -115
- package/index.js +1 -1
- package/package.json +2 -2
- package/plugin.json +2 -2
- package/scripts/check-anti-slop.js +53 -0
- package/scripts/generate_swarm_gif.py +2 -2
- package/skills/ai-llm-integration-expert/SKILL.md +22 -15
- package/skills/ai-prompt-engineering-expert/SKILL.md +133 -83
- package/skills/anti-slop/SKILL.md +133 -0
- package/skills/async-queue-temporal-expert/SKILL.md +135 -158
- package/skills/authentication-identity-expert/SKILL.md +172 -278
- package/skills/brainstorming/SKILL.md +26 -26
- package/skills/database-orm-expert/SKILL.md +164 -303
- package/skills/deep-research-analyst/SKILL.md +136 -0
- package/skills/design-system-architect/SKILL.md +31 -1
- package/skills/email-notification-expert/SKILL.md +31 -4
- package/skills/error-resilience-expert/SKILL.md +21 -0
- package/skills/fullstack-expert/SKILL.md +183 -260
- package/skills/glsl-shader-expert/SKILL.md +190 -107
- package/skills/graph-rag-knowledge-expert/SKILL.md +42 -1
- package/skills/mcp-server-architect/SKILL.md +15 -1
- package/skills/prd-architect/SKILL.md +181 -206
- package/skills/production-ready-hardener/SKILL.md +16 -19
- package/skills/pwa-offline-first-expert/SKILL.md +42 -1
- package/skills/pydantic-ai-expert/SKILL.md +161 -0
- package/skills/saas-architect/SKILL.md +154 -0
- package/skills/senior-frontend/SKILL.md +9 -11
- package/skills/senior-frontend/scripts/frontend_scaffolder.py +1 -1
- package/skills/session-memory-manager/SKILL.md +128 -0
- package/skills/synthetic-data-finetuning-expert/SKILL.md +155 -0
- package/skills/ui-ux-pro-max/SKILL.md +4 -2
- package/skills/vercel-ai-sdk-expert/SKILL.md +181 -0
- package/skills/voice-ai-realtime-agent/SKILL.md +41 -1
- package/skills/web-3d-graphics-expert/SKILL.md +313 -137
- package/skills/web-game-engine-expert/SKILL.md +329 -102
- package/skills/webxr-ar-vr-expert/SKILL.md +162 -123
- package/skills/zero-to-prod-orchestrator/SKILL.md +26 -24
- package/skills/ai-cost-token-optimizer/SKILL.md +0 -82
- package/skills/ai-evals-benchmark-expert/SKILL.md +0 -188
- package/skills/asisten-ramah/SKILL.md +0 -47
- package/skills/auto-doc-updater/SKILL.md +0 -220
- package/skills/autonomous-chaos-monkey/SKILL.md +0 -63
- package/skills/background-jobs-queue-expert/SKILL.md +0 -235
- package/skills/database-migration-versioning-expert/SKILL.md +0 -90
- package/skills/edge-serverless-db-expert/SKILL.md +0 -99
- package/skills/mcp-client-orchestrator/SKILL.md +0 -76
- package/skills/mobile-push-notification-expert/SKILL.md +0 -71
- package/skills/monday-design-aesthetic/SKILL.md +0 -73
- package/skills/project-context-mapper/SKILL.md +0 -85
- package/skills/saas-mvp-launcher/SKILL.md +0 -260
- package/skills/saas-transformer/SKILL.md +0 -500
- package/skills/saas-transformer/references/billing_integration_guide.md +0 -401
- package/skills/self-evolving-memory-graph/SKILL.md +0 -91
- package/skills/session-context-loader/SKILL.md +0 -83
- package/skills/session-handoff-resume/SKILL.md +0 -164
- package/skills/skill-baru/SKILL.md +0 -178
- package/skills/supabase-migration/SKILL.md +0 -91
- package/skills/token-saver/SKILL.md +0 -119
- package/skills/ui-components-expert/SKILL.md +0 -166
- package/skills/vibe-code-gardener/SKILL.md +0 -181
- /package/skills/{saas-transformer → saas-architect}/references/feature_gating_patterns.md +0 -0
- /package/skills/{saas-transformer → saas-architect}/references/saas_transformation_checklist.md +0 -0
- /package/skills/{saas-transformer → saas-architect}/scripts/saas_transformation_scanner.py +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: async-queue-temporal-expert
|
|
3
|
-
description: "
|
|
3
|
+
description: "Unified expert guide for async job queues & durable workflows: BullMQ v5 (Redis queues), Trigger.dev v3 (serverless tasks), Inngest, and Temporal.io (distributed sagas) / Panduan ahli terpadu untuk antrean job asinkron & workflow tahan-gagal: BullMQ v5, Trigger.dev v3, Inngest, dan Temporal.io."
|
|
4
4
|
author: "Roedy Rustam"
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
# Async Queue & Durable Workflow Expert (
|
|
7
|
+
# Async Queue & Durable Workflow Expert (2026 Unified Edition)
|
|
8
8
|
|
|
9
9
|
[English](#english) | [Bahasa Indonesia](#bahasa-indonesia)
|
|
10
10
|
|
|
@@ -14,103 +14,112 @@ author: "Roedy Rustam"
|
|
|
14
14
|
## English
|
|
15
15
|
|
|
16
16
|
### Purpose & Overview
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
###
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
Unified production-grade guide for background execution pipelines, async job queues, and distributed state machines. Covers the full spectrum from simple Redis-backed task queues to complex multi-service sagas with compensating rollbacks.
|
|
18
|
+
|
|
19
|
+
### 3-Tier Execution Model
|
|
20
|
+
| Tier | Engine | Best For |
|
|
21
|
+
|------|--------|----------|
|
|
22
|
+
| **Tier 1: Redis Task Queues** | BullMQ v5 | High-throughput worker jobs, priority queues, rate limiting, DLQ |
|
|
23
|
+
| **Tier 2: Serverless Durable Tasks** | Trigger.dev v3 / Inngest | Step-checkpointed tasks, automatic resume across crashes, zero infra |
|
|
24
|
+
| **Tier 3: Distributed Sagas** | Temporal.io | Multi-service orchestration, compensating rollbacks, long-running workflows |
|
|
25
|
+
|
|
26
|
+
### Core Capabilities
|
|
27
|
+
1. **Idempotency & Deduplication**: Deterministic `jobId` keys prevent double billing or duplicate emails.
|
|
28
|
+
2. **Dead Letter Queues (DLQ)**: Auto-relocate permanently failing jobs for audit and alerting.
|
|
29
|
+
3. **Exponential Backoff with Jitter**: Prevents thundering herds on upstream services.
|
|
30
|
+
4. **Tenant Priority Queues**: VIP/enterprise tiers get lower BullMQ priority numbers (higher throughput).
|
|
31
|
+
5. **Durable State Machines**: Workflows survive restarts, deployments, and network partitions.
|
|
32
|
+
6. **Saga Compensations**: Multi-step transactions with automated reverse-order rollbacks.
|
|
24
33
|
|
|
25
34
|
---
|
|
26
35
|
|
|
27
|
-
###
|
|
36
|
+
### Tier 1: BullMQ v5 — Redis Task Queues (TypeScript)
|
|
28
37
|
|
|
29
|
-
#### Recipe 1: Temporal.io Saga Pattern with Compensations (TypeScript SDK)
|
|
30
38
|
```typescript
|
|
31
|
-
import {
|
|
32
|
-
import
|
|
39
|
+
import { Queue, Worker, Job } from 'bullmq';
|
|
40
|
+
import Redis from 'ioredis';
|
|
33
41
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
startToCloseTimeout: '1 minute',
|
|
38
|
-
retry: {
|
|
39
|
-
initialInterval: '1s',
|
|
40
|
-
backoffCoefficient: 2,
|
|
41
|
-
maximumAttempts: 5,
|
|
42
|
-
nonRetryableErrorTypes: ['InvalidCardError', 'AccountSuspendedError'],
|
|
43
|
-
},
|
|
44
|
-
});
|
|
42
|
+
const redisConnection = new Redis(process.env.REDIS_URL!, {
|
|
43
|
+
maxRetriesPerRequest: null, // Required by BullMQ
|
|
44
|
+
});
|
|
45
45
|
|
|
46
|
-
export interface
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
export interface NotificationPayload {
|
|
47
|
+
tenantId: string;
|
|
48
|
+
userId: string;
|
|
49
|
+
type: 'email' | 'webhook';
|
|
50
|
+
payload: Record<string, unknown>;
|
|
51
|
+
idempotencyKey: string;
|
|
50
52
|
}
|
|
51
53
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
//
|
|
60
|
-
|
|
61
|
-
|
|
54
|
+
// Main Queue
|
|
55
|
+
export const notificationQueue = new Queue<NotificationPayload>('notifications', {
|
|
56
|
+
connection: redisConnection,
|
|
57
|
+
defaultJobOptions: {
|
|
58
|
+
attempts: 5,
|
|
59
|
+
backoff: { type: 'exponential', delay: 1500 },
|
|
60
|
+
removeOnComplete: { age: 86400, count: 5000 },
|
|
61
|
+
removeOnFail: false, // Preserved for DLQ audit
|
|
62
|
+
},
|
|
63
|
+
});
|
|
62
64
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
65
|
+
// Dead Letter Queue
|
|
66
|
+
export const notificationDLQ = new Queue('notifications-dlq', {
|
|
67
|
+
connection: redisConnection,
|
|
68
|
+
});
|
|
66
69
|
|
|
67
|
-
|
|
68
|
-
|
|
70
|
+
// Enqueue with deduplication & priority
|
|
71
|
+
export async function enqueueNotification(data: NotificationPayload, isVip = false) {
|
|
72
|
+
return await notificationQueue.add('send_notification', data, {
|
|
73
|
+
jobId: `notif_${data.idempotencyKey}`, // Deterministic dedup key
|
|
74
|
+
priority: isVip ? 1 : 10,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
69
77
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
78
|
+
// Worker with concurrency & rate limiting
|
|
79
|
+
export const notificationWorker = new Worker<NotificationPayload>(
|
|
80
|
+
'notifications',
|
|
81
|
+
async (job: Job<NotificationPayload>) => {
|
|
82
|
+
if (job.data.type === 'email') await deliverEmail(job.data);
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
connection: redisConnection,
|
|
86
|
+
concurrency: 20,
|
|
87
|
+
limiter: { max: 100, duration: 1000 },
|
|
88
|
+
}
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
// DLQ forwarding on retry exhaustion
|
|
92
|
+
notificationWorker.on('failed', async (job, error) => {
|
|
93
|
+
if (job && job.attemptsMade >= (job.opts.attempts || 5)) {
|
|
94
|
+
await notificationDLQ.add('failed_notification', {
|
|
95
|
+
originalJobId: job.id, failedReason: error.message,
|
|
96
|
+
data: job.data, exhaustedAt: new Date().toISOString(),
|
|
83
97
|
});
|
|
84
98
|
}
|
|
85
|
-
}
|
|
99
|
+
});
|
|
86
100
|
```
|
|
87
101
|
|
|
88
|
-
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
### Tier 2: Trigger.dev v3 — Serverless Durable Tasks
|
|
105
|
+
|
|
89
106
|
```typescript
|
|
90
107
|
import { task } from '@trigger.dev/sdk/v3';
|
|
91
108
|
|
|
92
|
-
export const
|
|
109
|
+
export const generateReport = task({
|
|
93
110
|
id: 'generate-enterprise-report',
|
|
94
|
-
retry: {
|
|
95
|
-
maxAttempts: 4,
|
|
96
|
-
minTimeoutInMs: 2000,
|
|
97
|
-
factor: 2,
|
|
98
|
-
randomize: true, // Jitter
|
|
99
|
-
},
|
|
111
|
+
retry: { maxAttempts: 4, minTimeoutInMs: 2000, factor: 2, randomize: true },
|
|
100
112
|
run: async (payload: { tenantId: string; month: string }, { ctx }) => {
|
|
101
|
-
//
|
|
113
|
+
// Each step is a durable checkpoint — survives crashes
|
|
102
114
|
const data = await ctx.run('fetch-telemetry', async () => {
|
|
103
115
|
return await fetchTelemetryFromWarehouse(payload.tenantId, payload.month);
|
|
104
116
|
});
|
|
105
|
-
|
|
106
117
|
const pdfUrl = await ctx.run('render-pdf', async () => {
|
|
107
118
|
return await generateReportPdf(data);
|
|
108
119
|
});
|
|
109
|
-
|
|
110
120
|
await ctx.run('dispatch-webhook', async () => {
|
|
111
121
|
return await sendWebhookNotification(payload.tenantId, pdfUrl);
|
|
112
122
|
});
|
|
113
|
-
|
|
114
123
|
return { success: true, pdfUrl };
|
|
115
124
|
},
|
|
116
125
|
});
|
|
@@ -118,123 +127,91 @@ export const generateEnterpriseAnalyticsReport = task({
|
|
|
118
127
|
|
|
119
128
|
---
|
|
120
129
|
|
|
121
|
-
###
|
|
122
|
-
- [ ] Implement Saga rollback handlers for multi-step distributed payments and user provisioning.
|
|
123
|
-
- [ ] Enforce deterministic code inside Temporal workflows (never use `Math.random()`, `Date.now()`, or direct DB calls in workflow files; run them inside activities).
|
|
124
|
-
- [ ] Store large payloads in object storage (S3/R2); pass only IDs and signed URLs through queues.
|
|
125
|
-
- [ ] Configure DLQ (Dead Letter Queue) and alert thresholds for persistent failures.
|
|
126
|
-
|
|
127
|
-
## Orchestration & Integration
|
|
128
|
-
- Integrates with: `js-backend-expert`, `background-jobs-queue-expert`, `error-resilience-expert`, `saas-billing`, `doku-payment-gateway`.
|
|
129
|
-
|
|
130
|
-
---
|
|
131
|
-
|
|
132
|
-
<a name="bahasa-indonesia"></a>
|
|
133
|
-
## Bahasa Indonesia
|
|
134
|
-
|
|
135
|
-
### Tujuan & Gambaran Umum
|
|
136
|
-
Panduan arsitektur tingkat produksi untuk merancang pipeline eksekusi background yang tahan-gagal (durable execution), antrean tugas asinkron, dan state machine terdistribusi menggunakan **Temporal.io**, **Trigger.dev v3**, **Inngest**, dan **BullMQ v5**. Menjamin penyelesaian mutlak tugas berdurasi panjang terhadap pembatasan rate limit API, kegagalan worker, dan partisi jaringan.
|
|
137
|
-
|
|
138
|
-
### Kemampuan Utama
|
|
139
|
-
1. **State Machine Tahan-Gagal (Durable Execution)**: Alur kerja (workflow) tetap bertahan saat restart server, deployment, atau gangguan database tanpa kehilangan progres state.
|
|
140
|
-
2. **Pola Transaksi Terdistribusi (Saga Pattern)**: Transaksi multi-langkah yang dilengkapi dengan aktivitas kompensasi (rollback otomatis) jika langkah lanjutan gagal permanen.
|
|
141
|
-
3. **Idempotensi & Anti-Duplikasi**: Menjamin kunci idempotensi unik pada setiap transaksi guna mencegah duplikasi penagihan atau email berulang.
|
|
142
|
-
4. **Pembatasan Rate Limit & DLQ**: Throttling berbasis token bucket, exponential backoff dengan jitter acak, dan dead-letter queue (DLQ) untuk mengisolasi tugas beracun (*poison pills*).
|
|
143
|
-
|
|
144
|
-
---
|
|
145
|
-
|
|
146
|
-
### Resep Implementasi Produksi
|
|
130
|
+
### Tier 3: Temporal.io — Distributed Saga with Compensations
|
|
147
131
|
|
|
148
|
-
#### Resep 1: Pola Saga Temporal.io dengan Logika Kompensasi (TypeScript)
|
|
149
132
|
```typescript
|
|
150
133
|
import { proxyActivities, ApplicationFailure } from '@temporalio/workflow';
|
|
151
134
|
import type * as activities from './activities';
|
|
152
135
|
|
|
153
|
-
const {
|
|
136
|
+
const { chargeCustomer, provisionLicense, sendWelcomeEmail, refundCustomer, revokeLicense } =
|
|
154
137
|
proxyActivities<typeof activities>({
|
|
155
138
|
startToCloseTimeout: '1 minute',
|
|
156
139
|
retry: {
|
|
157
|
-
initialInterval: '1s',
|
|
158
|
-
|
|
159
|
-
maximumAttempts: 5,
|
|
140
|
+
initialInterval: '1s', backoffCoefficient: 2, maximumAttempts: 5,
|
|
141
|
+
nonRetryableErrorTypes: ['InvalidCardError', 'AccountSuspendedError'],
|
|
160
142
|
},
|
|
161
143
|
});
|
|
162
144
|
|
|
163
|
-
export
|
|
164
|
-
customerId: string;
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
export async function workflowSagaLangganan(input: InputWorkflowLangganan) {
|
|
170
|
-
const kompensasi: Array<() => Promise<void>> = [];
|
|
171
|
-
|
|
145
|
+
export async function subscriptionSagaWorkflow(input: {
|
|
146
|
+
customerId: string; planId: string; amountCents: number;
|
|
147
|
+
}) {
|
|
148
|
+
const compensations: Array<() => Promise<void>> = [];
|
|
172
149
|
try {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
kompensasi.unshift(() => kembalikanDana(hasilTagihan.chargeId));
|
|
176
|
-
|
|
177
|
-
// Langkah 2: Aktifkan Lisensi
|
|
178
|
-
const hasilLisensi = await aktifkanLisensi(input.customerId, input.planId);
|
|
179
|
-
kompensasi.unshift(() => cabutLisensi(hasilLisensi.licenseId));
|
|
150
|
+
const charge = await chargeCustomer(input.customerId, input.amountCents);
|
|
151
|
+
compensations.unshift(() => refundCustomer(charge.chargeId));
|
|
180
152
|
|
|
181
|
-
|
|
182
|
-
|
|
153
|
+
const license = await provisionLicense(input.customerId, input.planId);
|
|
154
|
+
compensations.unshift(() => revokeLicense(license.licenseId));
|
|
183
155
|
|
|
184
|
-
|
|
156
|
+
await sendWelcomeEmail(input.customerId, license.licenseKey);
|
|
157
|
+
return { status: 'COMPLETED' };
|
|
185
158
|
} catch (error) {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
try {
|
|
189
|
-
await compensate();
|
|
190
|
-
} catch (err) {
|
|
191
|
-
console.error('Kompensasi gagal:', err);
|
|
192
|
-
}
|
|
159
|
+
for (const compensate of compensations) {
|
|
160
|
+
try { await compensate(); } catch (e) { console.error('Compensation failed:', e); }
|
|
193
161
|
}
|
|
194
162
|
throw ApplicationFailure.create({
|
|
195
|
-
message: `Saga
|
|
196
|
-
nonRetryable: true,
|
|
163
|
+
message: `Saga rolled back: ${(error as Error).message}`, nonRetryable: true,
|
|
197
164
|
});
|
|
198
165
|
}
|
|
199
166
|
}
|
|
200
167
|
```
|
|
201
168
|
|
|
202
|
-
|
|
203
|
-
```typescript
|
|
204
|
-
import { task } from '@trigger.dev/sdk/v3';
|
|
205
|
-
|
|
206
|
-
export const buatLaporanAnalitik = task({
|
|
207
|
-
id: 'buat-laporan-analitik',
|
|
208
|
-
retry: {
|
|
209
|
-
maxAttempts: 4,
|
|
210
|
-
factor: 2,
|
|
211
|
-
randomize: true, // Jitter
|
|
212
|
-
},
|
|
213
|
-
run: async (payload: { tenantId: string; bulan: string }, { ctx }) => {
|
|
214
|
-
const data = await ctx.run('ambil-data', async () => {
|
|
215
|
-
return await ambilDataWarehouse(payload.tenantId, payload.bulan);
|
|
216
|
-
});
|
|
169
|
+
> **Temporal Determinism Rule**: Never use `Math.random()`, `Date.now()`, or direct DB calls inside workflow files. Run them inside activities.
|
|
217
170
|
|
|
218
|
-
|
|
219
|
-
return await renderDokumenPdf(data);
|
|
220
|
-
});
|
|
171
|
+
---
|
|
221
172
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
173
|
+
### Implementation Checklist
|
|
174
|
+
- [ ] Configure `maxRetriesPerRequest: null` on ioredis for BullMQ v5.
|
|
175
|
+
- [ ] Use deterministic `jobId` from business logic (`order_${orderId}`) for deduplication.
|
|
176
|
+
- [ ] Forward permanently dead jobs to DLQ via `worker.on('failed')` listener.
|
|
177
|
+
- [ ] Implement rate limiting via worker `limiter` to protect third-party APIs.
|
|
178
|
+
- [ ] Enforce deterministic code inside Temporal workflows (activities for side-effects).
|
|
179
|
+
- [ ] Store large payloads in S3/R2; pass only IDs through queues.
|
|
180
|
+
- [ ] Implement Saga rollback handlers for multi-step distributed payments.
|
|
225
181
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
});
|
|
229
|
-
```
|
|
182
|
+
## Orchestration & Integration
|
|
183
|
+
- Integrates with: `js-backend-expert`, `cron-scheduler-expert`, `error-resilience-expert`, `saas-billing`, `doku-payment-gateway`, `data-telemetry-expert`.
|
|
230
184
|
|
|
231
185
|
---
|
|
232
186
|
|
|
187
|
+
<a name="bahasa-indonesia"></a>
|
|
188
|
+
## Bahasa Indonesia
|
|
189
|
+
|
|
190
|
+
### Tujuan & Gambaran Umum
|
|
191
|
+
Panduan terpadu tingkat produksi untuk pipeline eksekusi latar belakang, antrean job asinkron, dan state machine terdistribusi. Mencakup spektrum penuh dari antrean Redis sederhana hingga saga multi-layanan dengan rollback kompensasi.
|
|
192
|
+
|
|
193
|
+
### Model Eksekusi 3-Tier
|
|
194
|
+
| Tier | Engine | Cocok Untuk |
|
|
195
|
+
|------|--------|-------------|
|
|
196
|
+
| **Tier 1: Antrean Redis** | BullMQ v5 | Job worker throughput tinggi, prioritas, rate limiting, DLQ |
|
|
197
|
+
| **Tier 2: Task Serverless** | Trigger.dev v3 / Inngest | Task dengan checkpoint, resume otomatis, tanpa infra |
|
|
198
|
+
| **Tier 3: Saga Terdistribusi** | Temporal.io | Orkestrasi multi-layanan, rollback kompensasi, workflow jangka panjang |
|
|
199
|
+
|
|
200
|
+
### Kemampuan Utama
|
|
201
|
+
1. **Idempotensi & Deduplikasi**: Kunci `jobId` deterministik mencegah duplikasi penagihan atau email.
|
|
202
|
+
2. **Dead Letter Queue (DLQ)**: Pemindahan otomatis job gagal total untuk audit.
|
|
203
|
+
3. **Backoff Eksponensial + Jitter**: Mencegah thundering herd pada server hilir.
|
|
204
|
+
4. **Prioritas Tenant**: Tier VIP/enterprise mendapat prioritas lebih tinggi (angka lebih kecil di BullMQ).
|
|
205
|
+
5. **State Machine Tahan-Gagal**: Workflow bertahan saat restart, deployment, dan partisi jaringan.
|
|
206
|
+
6. **Kompensasi Saga**: Transaksi multi-langkah dengan rollback otomatis urutan mundur.
|
|
207
|
+
|
|
233
208
|
### Checklist Implementasi
|
|
234
|
-
- [ ]
|
|
235
|
-
- [ ]
|
|
236
|
-
- [ ]
|
|
237
|
-
- [ ]
|
|
209
|
+
- [ ] Atur `maxRetriesPerRequest: null` pada ioredis untuk BullMQ v5.
|
|
210
|
+
- [ ] Gunakan `jobId` deterministik dari ID bisnis (`invoice_${invoiceId}`) untuk deduplikasi.
|
|
211
|
+
- [ ] Pasang listener `worker.on('failed')` untuk forward job gagal ke DLQ.
|
|
212
|
+
- [ ] Terapkan rate limiter pada worker untuk stabilitas API eksternal.
|
|
213
|
+
- [ ] Pastikan kode Temporal selalu deterministik (side-effect hanya di activities).
|
|
214
|
+
- [ ] Simpan file besar di S3/R2; kirim hanya referensi ID melalui queue.
|
|
238
215
|
|
|
239
216
|
## Integrasi Orkestrasi
|
|
240
|
-
- Terintegrasi dengan: `js-backend-expert`, `
|
|
217
|
+
- Terintegrasi dengan: `js-backend-expert`, `cron-scheduler-expert`, `error-resilience-expert`, `saas-billing`, `doku-payment-gateway`, `data-telemetry-expert`.
|