@neyugn/agent-kits 0.1.0
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/LICENSE +21 -0
- package/README.md +514 -0
- package/README.vi.md +410 -0
- package/README.zh.md +410 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +422 -0
- package/kits/coder/ARCHITECTURE.md +289 -0
- package/kits/coder/agents/ai-engineer.md +344 -0
- package/kits/coder/agents/backend-specialist.md +270 -0
- package/kits/coder/agents/cloud-architect.md +363 -0
- package/kits/coder/agents/code-reviewer.md +284 -0
- package/kits/coder/agents/data-engineer.md +401 -0
- package/kits/coder/agents/database-specialist.md +251 -0
- package/kits/coder/agents/debugger.md +209 -0
- package/kits/coder/agents/devops-engineer.md +281 -0
- package/kits/coder/agents/documentation-writer.md +296 -0
- package/kits/coder/agents/frontend-specialist.md +298 -0
- package/kits/coder/agents/i18n-specialist.md +348 -0
- package/kits/coder/agents/integration-specialist.md +314 -0
- package/kits/coder/agents/mobile-developer.md +271 -0
- package/kits/coder/agents/multi-tenant-architect.md +281 -0
- package/kits/coder/agents/orchestrator.md +263 -0
- package/kits/coder/agents/performance-analyst.md +327 -0
- package/kits/coder/agents/project-planner.md +277 -0
- package/kits/coder/agents/queue-specialist.md +282 -0
- package/kits/coder/agents/realtime-specialist.md +267 -0
- package/kits/coder/agents/security-auditor.md +253 -0
- package/kits/coder/agents/test-engineer.md +315 -0
- package/kits/coder/agents/ux-researcher.md +388 -0
- package/kits/coder/rules/.cursorrules +287 -0
- package/kits/coder/rules/CLAUDE.md +287 -0
- package/kits/coder/rules/CODEX.md +287 -0
- package/kits/coder/rules/GEMINI.md +287 -0
- package/kits/coder/scripts/checklist.py +318 -0
- package/kits/coder/scripts/kit_status.py +292 -0
- package/kits/coder/scripts/skills_manager.py +243 -0
- package/kits/coder/scripts/verify_all.py +391 -0
- package/kits/coder/skills/accessibility-patterns/SKILL.md +372 -0
- package/kits/coder/skills/accessibility-patterns/scripts/a11y_checker.py +211 -0
- package/kits/coder/skills/ai-rag-patterns/SKILL.md +444 -0
- package/kits/coder/skills/api-patterns/SKILL.md +316 -0
- package/kits/coder/skills/api-patterns/assets/.gitkeep +1 -0
- package/kits/coder/skills/api-patterns/references/deep-dive.md +21 -0
- package/kits/coder/skills/api-patterns/scripts/api_validator.py +253 -0
- package/kits/coder/skills/api-patterns/scripts/validate.py +56 -0
- package/kits/coder/skills/auth-patterns/SKILL.md +267 -0
- package/kits/coder/skills/aws-patterns/SKILL.md +576 -0
- package/kits/coder/skills/brainstorming/SKILL.md +370 -0
- package/kits/coder/skills/brainstorming/assets/.gitkeep +1 -0
- package/kits/coder/skills/brainstorming/references/deep-dive.md +21 -0
- package/kits/coder/skills/brainstorming/scripts/validate.py +56 -0
- package/kits/coder/skills/clean-code/SKILL.md +240 -0
- package/kits/coder/skills/clean-code/assets/.gitkeep +1 -0
- package/kits/coder/skills/clean-code/references/deep-dive.md +21 -0
- package/kits/coder/skills/clean-code/scripts/lint_runner.py +186 -0
- package/kits/coder/skills/clean-code/scripts/validate.py +56 -0
- package/kits/coder/skills/database-design/SKILL.md +255 -0
- package/kits/coder/skills/database-design/assets/.gitkeep +1 -0
- package/kits/coder/skills/database-design/references/deep-dive.md +21 -0
- package/kits/coder/skills/database-design/scripts/schema_validator.py +272 -0
- package/kits/coder/skills/database-design/scripts/validate.py +56 -0
- package/kits/coder/skills/docker-patterns/SKILL.md +240 -0
- package/kits/coder/skills/documentation-templates/SKILL.md +441 -0
- package/kits/coder/skills/e2e-testing/SKILL.md +457 -0
- package/kits/coder/skills/flutter-patterns/SKILL.md +330 -0
- package/kits/coder/skills/frontend-design/SKILL.md +127 -0
- package/kits/coder/skills/github-actions/SKILL.md +349 -0
- package/kits/coder/skills/gitlab-ci-patterns/SKILL.md +466 -0
- package/kits/coder/skills/graphql-patterns/SKILL.md +558 -0
- package/kits/coder/skills/i18n-localization/SKILL.md +345 -0
- package/kits/coder/skills/i18n-localization/scripts/i18n_checker.py +267 -0
- package/kits/coder/skills/kubernetes-patterns/SKILL.md +357 -0
- package/kits/coder/skills/mermaid-diagrams/SKILL.md +351 -0
- package/kits/coder/skills/mobile-design/SKILL.md +305 -0
- package/kits/coder/skills/monitoring-observability/SKILL.md +458 -0
- package/kits/coder/skills/multi-tenancy/SKILL.md +317 -0
- package/kits/coder/skills/multi-tenancy/assets/.gitkeep +1 -0
- package/kits/coder/skills/multi-tenancy/references/deep-dive.md +21 -0
- package/kits/coder/skills/multi-tenancy/scripts/validate.py +56 -0
- package/kits/coder/skills/nodejs-best-practices/SKILL.md +220 -0
- package/kits/coder/skills/performance-profiling/SKILL.md +333 -0
- package/kits/coder/skills/performance-profiling/assets/.gitkeep +1 -0
- package/kits/coder/skills/performance-profiling/references/deep-dive.md +21 -0
- package/kits/coder/skills/performance-profiling/scripts/validate.py +56 -0
- package/kits/coder/skills/plan-writing/SKILL.md +360 -0
- package/kits/coder/skills/plan-writing/assets/.gitkeep +1 -0
- package/kits/coder/skills/plan-writing/references/deep-dive.md +21 -0
- package/kits/coder/skills/plan-writing/scripts/validate.py +56 -0
- package/kits/coder/skills/postgres-patterns/SKILL.md +361 -0
- package/kits/coder/skills/prompt-engineering/SKILL.md +277 -0
- package/kits/coder/skills/queue-patterns/SKILL.md +359 -0
- package/kits/coder/skills/queue-patterns/assets/.gitkeep +1 -0
- package/kits/coder/skills/queue-patterns/references/deep-dive.md +21 -0
- package/kits/coder/skills/queue-patterns/scripts/validate.py +56 -0
- package/kits/coder/skills/react-native-patterns/SKILL.md +393 -0
- package/kits/coder/skills/react-patterns/SKILL.md +319 -0
- package/kits/coder/skills/realtime-patterns/SKILL.md +506 -0
- package/kits/coder/skills/realtime-patterns/assets/.gitkeep +1 -0
- package/kits/coder/skills/realtime-patterns/references/deep-dive.md +21 -0
- package/kits/coder/skills/realtime-patterns/scripts/validate.py +56 -0
- package/kits/coder/skills/redis-patterns/SKILL.md +484 -0
- package/kits/coder/skills/security-fundamentals/SKILL.md +363 -0
- package/kits/coder/skills/security-fundamentals/assets/.gitkeep +1 -0
- package/kits/coder/skills/security-fundamentals/references/deep-dive.md +21 -0
- package/kits/coder/skills/security-fundamentals/scripts/security_scan.py +326 -0
- package/kits/coder/skills/security-fundamentals/scripts/validate.py +56 -0
- package/kits/coder/skills/seo-patterns/SKILL.md +262 -0
- package/kits/coder/skills/seo-patterns/scripts/seo_checker.py +211 -0
- package/kits/coder/skills/systematic-debugging/SKILL.md +478 -0
- package/kits/coder/skills/systematic-debugging/assets/.gitkeep +1 -0
- package/kits/coder/skills/systematic-debugging/references/deep-dive.md +21 -0
- package/kits/coder/skills/systematic-debugging/scripts/validate.py +56 -0
- package/kits/coder/skills/tailwind-patterns/SKILL.md +395 -0
- package/kits/coder/skills/terraform-patterns/SKILL.md +470 -0
- package/kits/coder/skills/testing-patterns/SKILL.md +285 -0
- package/kits/coder/skills/testing-patterns/assets/.gitkeep +1 -0
- package/kits/coder/skills/testing-patterns/references/deep-dive.md +21 -0
- package/kits/coder/skills/testing-patterns/scripts/test_runner.py +219 -0
- package/kits/coder/skills/testing-patterns/scripts/validate.py +56 -0
- package/kits/coder/skills/typescript-patterns/SKILL.md +417 -0
- package/kits/coder/skills/ui-ux-pro-max/SKILL.md +364 -0
- package/kits/coder/skills/ui-ux-pro-max/data/charts.csv +26 -0
- package/kits/coder/skills/ui-ux-pro-max/data/colors.csv +97 -0
- package/kits/coder/skills/ui-ux-pro-max/data/icons.csv +101 -0
- package/kits/coder/skills/ui-ux-pro-max/data/landing.csv +31 -0
- package/kits/coder/skills/ui-ux-pro-max/data/products.csv +97 -0
- package/kits/coder/skills/ui-ux-pro-max/data/prompts.csv +24 -0
- package/kits/coder/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
- package/kits/coder/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
- package/kits/coder/skills/ui-ux-pro-max/data/styles.csv +59 -0
- package/kits/coder/skills/ui-ux-pro-max/data/typography.csv +58 -0
- package/kits/coder/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
- package/kits/coder/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
- package/kits/coder/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
- package/kits/coder/skills/ui-ux-pro-max/scripts/__pycache__/core.cpython-314.pyc +0 -0
- package/kits/coder/skills/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-314.pyc +0 -0
- package/kits/coder/skills/ui-ux-pro-max/scripts/core.py +257 -0
- package/kits/coder/skills/ui-ux-pro-max/scripts/design_system.py +488 -0
- package/kits/coder/skills/ui-ux-pro-max/scripts/search.py +76 -0
- package/kits/coder/workflows/.gitkeep +20 -0
- package/kits/coder/workflows/create.md +152 -0
- package/kits/coder/workflows/debug.md +223 -0
- package/kits/coder/workflows/deploy.md +283 -0
- package/kits/coder/workflows/orchestrate.md +243 -0
- package/kits/coder/workflows/plan.md +134 -0
- package/kits/coder/workflows/test.md +237 -0
- package/kits/coder/workflows/ui-ux-pro-max.md +109 -0
- package/package.json +49 -0
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: queue-patterns
|
|
3
|
+
description: Message queue and background job processing patterns. Use when designing job queues, implementing retry strategies, building worker pools, or handling dead letter queues. Covers BullMQ, RabbitMQ, and distributed job scheduling.
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
tags: [architecture, queue, jobs, async, reliability]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Queue Patterns - Background Job Processing Skill
|
|
9
|
+
|
|
10
|
+
> **Purpose:** Enable AI agents to design and implement reliable message queue systems with proper retry strategies, idempotency, and observability.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## š Navigation
|
|
15
|
+
|
|
16
|
+
- [Philosophy](#-philosophy)
|
|
17
|
+
- [Queue Selection](#-queue-selection)
|
|
18
|
+
- [Job Design](#-job-design)
|
|
19
|
+
- [Retry Strategies](#-retry-strategies)
|
|
20
|
+
- [Decision Frameworks](#-decision-frameworks)
|
|
21
|
+
- [Anti-Patterns](#-anti-patterns)
|
|
22
|
+
- [Checklist](#-implementation-checklist)
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## š” Philosophy
|
|
27
|
+
|
|
28
|
+
> **"A queue is a promise: jobs go in, results come out, nothing is lost."**
|
|
29
|
+
|
|
30
|
+
| Principle | Implementation |
|
|
31
|
+
| --------------------------- | -------------------------------------------------------- |
|
|
32
|
+
| **Jobs Are Sacred** | Every job must complete, fail explicitly, or move to DLQ |
|
|
33
|
+
| **Idempotency by Design** | Same job running twice = same outcome |
|
|
34
|
+
| **Reliability Over Speed** | Slow and correct beats fast and lossy |
|
|
35
|
+
| **Observability Mandatory** | Every job traceable from start to end |
|
|
36
|
+
| **Fail Closed** | Unknown errors ā retry, not ignore |
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## š§ QUEUE SELECTION
|
|
41
|
+
|
|
42
|
+
### Technology Comparison
|
|
43
|
+
|
|
44
|
+
| System | Language | Persistence | Best For | Complexity |
|
|
45
|
+
| ------------ | -------- | ----------- | -------------------------------- | ---------- |
|
|
46
|
+
| **BullMQ** | Node.js | Redis | Feature-rich, delays, priorities | Low |
|
|
47
|
+
| **RabbitMQ** | Multi | Disk | Routing, multi-language | Medium |
|
|
48
|
+
| **AWS SQS** | Any | Managed | Serverless, Lambda | Low |
|
|
49
|
+
| **Kafka** | Any | Disk | High throughput, streaming | High |
|
|
50
|
+
| **Celery** | Python | Redis/AMQP | Distributed Python tasks | Medium |
|
|
51
|
+
|
|
52
|
+
### Selection Decision Tree
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
START
|
|
56
|
+
ā
|
|
57
|
+
ā¼
|
|
58
|
+
āāāāāāāāāāāāāāāāāāāāāā
|
|
59
|
+
ā What's the stack? ā
|
|
60
|
+
āāāāāāāāāāāāāāāāāāāāāā
|
|
61
|
+
ā
|
|
62
|
+
āāā Node.js + Redis ā BullMQ
|
|
63
|
+
āāā Python ā Celery or ARQ
|
|
64
|
+
āāā Serverless ā SQS + Lambda
|
|
65
|
+
āāā Multi-language ā RabbitMQ
|
|
66
|
+
āāā High throughput/streaming ā Kafka
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Redis Persistence for BullMQ
|
|
70
|
+
|
|
71
|
+
| Mode | Durability | Performance | When to Use |
|
|
72
|
+
| ------------ | ---------- | ----------- | ----------------------- |
|
|
73
|
+
| **RDB only** | Low | High | Dev/test only |
|
|
74
|
+
| **AOF** | High | Medium | Production default |
|
|
75
|
+
| **AOF+RDB** | Highest | Lower | Critical/financial jobs |
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## š¦ JOB DESIGN
|
|
80
|
+
|
|
81
|
+
### Job Payload Best Practices
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
// ā BAD: Large objects in payload
|
|
85
|
+
queue.add("processOrder", {
|
|
86
|
+
order: {
|
|
87
|
+
/* full order object with 100+ fields */
|
|
88
|
+
},
|
|
89
|
+
customer: {
|
|
90
|
+
/* full customer object */
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// ā
GOOD: IDs only, fetch fresh in worker
|
|
95
|
+
queue.add("processOrder", {
|
|
96
|
+
orderId: "order-123",
|
|
97
|
+
customerId: "cust-456",
|
|
98
|
+
tenantId: "tenant-789", // Multi-tenant context
|
|
99
|
+
idempotencyKey: "order-123-v1", // Deduplication
|
|
100
|
+
correlationId: "req-uuid-abc", // Tracing
|
|
101
|
+
});
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Required Job Context (Multi-tenant)
|
|
105
|
+
|
|
106
|
+
| Field | Purpose | Required |
|
|
107
|
+
| ---------------- | ------------------------------- | ----------- |
|
|
108
|
+
| `tenantId` | Tenant context for multi-tenant | Yes |
|
|
109
|
+
| `idempotencyKey` | Prevent duplicate processing | Yes |
|
|
110
|
+
| `correlationId` | Request tracing | Yes |
|
|
111
|
+
| `userId` | Audit trail | Recommended |
|
|
112
|
+
| `priority` | Queue prioritization | Optional |
|
|
113
|
+
|
|
114
|
+
### Job Lifecycle States
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
WAITING ā ACTIVE ā COMPLETED
|
|
118
|
+
ā
|
|
119
|
+
āāāā¶ FAILED ā RETRY ā (back to WAITING)
|
|
120
|
+
ā ā
|
|
121
|
+
ā āāāā¶ MAX RETRIES ā DEAD LETTER
|
|
122
|
+
ā
|
|
123
|
+
āāāā¶ STALLED ā AUTO-RETRY (worker crashed)
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## š RETRY STRATEGIES
|
|
129
|
+
|
|
130
|
+
### Retry Pattern Comparison
|
|
131
|
+
|
|
132
|
+
| Strategy | Formula | Use Case | Example |
|
|
133
|
+
| ---------------- | --------------------------- | ----------------------- | ----------------------- |
|
|
134
|
+
| **Fixed** | `delay` | Simple transient errors | `5s, 5s, 5s` |
|
|
135
|
+
| **Exponential** | `base * 2^attempt` | API rate limits | `1s, 2s, 4s, 8s` |
|
|
136
|
+
| **Exp + Jitter** | `base * 2^n + random(0, 1)` | Distributed systems | Prevent thundering herd |
|
|
137
|
+
| **Linear** | `base * attempt` | Gradual backoff | `5s, 10s, 15s, 20s` |
|
|
138
|
+
|
|
139
|
+
### BullMQ Retry Configuration
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
// Recommended configuration
|
|
143
|
+
{
|
|
144
|
+
attempts: 5,
|
|
145
|
+
backoff: {
|
|
146
|
+
type: 'exponential',
|
|
147
|
+
delay: 1000, // 1s base
|
|
148
|
+
},
|
|
149
|
+
removeOnComplete: {
|
|
150
|
+
age: 3600, // Keep completed jobs for 1 hour
|
|
151
|
+
count: 1000 // Keep max 1000 completed jobs
|
|
152
|
+
},
|
|
153
|
+
removeOnFail: false // Keep failed for debugging
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Retry Decision Matrix
|
|
158
|
+
|
|
159
|
+
| Error Type | Detection | Action |
|
|
160
|
+
| -------------------------------- | ------------------- | ------------------------- |
|
|
161
|
+
| **Transient** (network, timeout) | 5xx, ETIMEDOUT | Retry with backoff |
|
|
162
|
+
| **Permanent** (validation, auth) | 4xx | Move to DLQ immediately |
|
|
163
|
+
| **Resource** (rate limit) | 429 | Retry with longer backoff |
|
|
164
|
+
| **Unknown** | Unhandled exception | Retry (assume transient) |
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## š§ DECISION FRAMEWORKS
|
|
169
|
+
|
|
170
|
+
### Queue Architecture Decisions
|
|
171
|
+
|
|
172
|
+
| Need | Solution |
|
|
173
|
+
| -------------------------- | --------------------------------- |
|
|
174
|
+
| Fast priority jobs | Separate priority queue |
|
|
175
|
+
| Delayed execution | Scheduled jobs with `delay` |
|
|
176
|
+
| Rate limiting external API | Limiter group in BullMQ |
|
|
177
|
+
| Strict ordering | FIFO with job grouping |
|
|
178
|
+
| Large batch processing | Parent-child jobs (chunking) |
|
|
179
|
+
| Multi-tenant isolation | Queue per tenant OR tenant prefix |
|
|
180
|
+
|
|
181
|
+
### Concurrency Patterns
|
|
182
|
+
|
|
183
|
+
| Pattern | Configuration | Use Case |
|
|
184
|
+
| ------------------ | ---------------------------------------- | -------------------------- |
|
|
185
|
+
| **Fixed Pool** | `concurrency: 10` | Predictable load |
|
|
186
|
+
| **Rate Limited** | `limiter: { max: 100, duration: 60000 }` | External API limits |
|
|
187
|
+
| **Priority Queue** | Multiple queues with different workers | VIP customers |
|
|
188
|
+
| **FIFO per Key** | Job grouping by key | Order-sensitive operations |
|
|
189
|
+
|
|
190
|
+
### Dead Letter Queue (DLQ) Strategy
|
|
191
|
+
|
|
192
|
+
```
|
|
193
|
+
Job fails ā Retry 1 ā Retry 2 ... ā Max retries
|
|
194
|
+
ā
|
|
195
|
+
ā¼
|
|
196
|
+
āāāāāāāāāāāāāāāāāā
|
|
197
|
+
ā Dead Letter ā
|
|
198
|
+
ā Queue ā
|
|
199
|
+
ā ā
|
|
200
|
+
ā ⢠Inspect ā
|
|
201
|
+
ā ⢠Fix issue ā
|
|
202
|
+
ā ⢠Replay ā
|
|
203
|
+
āāāāāāāāāāāāāāāāāā
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
**DLQ Operations:**
|
|
207
|
+
|
|
208
|
+
1. **Monitor**: Alert on DLQ growth
|
|
209
|
+
2. **Inspect**: View failed job payload and error
|
|
210
|
+
3. **Diagnose**: Identify root cause
|
|
211
|
+
4. **Fix**: Deploy fix for the bug
|
|
212
|
+
5. **Replay**: Reprocess jobs from DLQ
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## ā” WORKER PATTERNS
|
|
217
|
+
|
|
218
|
+
### Idempotent Handler Pattern
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
async function processJob(job: Job) {
|
|
222
|
+
const { orderId, idempotencyKey } = job.data;
|
|
223
|
+
|
|
224
|
+
// Check if already processed
|
|
225
|
+
const existing = await db.findByIdempotencyKey(idempotencyKey);
|
|
226
|
+
if (existing) {
|
|
227
|
+
logger.info("Job already processed, skipping", { idempotencyKey });
|
|
228
|
+
return existing.result; // Return cached result
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Process the job
|
|
232
|
+
const result = await doActualWork(orderId);
|
|
233
|
+
|
|
234
|
+
// Store result with idempotency key
|
|
235
|
+
await db.saveWithIdempotencyKey(idempotencyKey, result);
|
|
236
|
+
|
|
237
|
+
return result;
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Graceful Shutdown Pattern
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
const worker = new Worker("my-queue", handler);
|
|
245
|
+
|
|
246
|
+
process.on("SIGTERM", async () => {
|
|
247
|
+
logger.info("SIGTERM received, closing worker...");
|
|
248
|
+
|
|
249
|
+
// Stop accepting new jobs
|
|
250
|
+
await worker.close();
|
|
251
|
+
|
|
252
|
+
// Wait for current jobs to complete (with timeout)
|
|
253
|
+
await worker.waitUntilReady();
|
|
254
|
+
|
|
255
|
+
logger.info("Worker closed gracefully");
|
|
256
|
+
process.exit(0);
|
|
257
|
+
});
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Worker Pool Sizing
|
|
261
|
+
|
|
262
|
+
| Job Type | Duration | Suggested Concurrency |
|
|
263
|
+
| --------------------- | -------- | ----------------------- |
|
|
264
|
+
| CPU-bound | > 1s | 1-2 per CPU core |
|
|
265
|
+
| I/O-bound (API calls) | < 1s | 10-50 |
|
|
266
|
+
| Mixed | Variable | 5-10 with rate limiting |
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
## ā ANTI-PATTERNS
|
|
271
|
+
|
|
272
|
+
### Critical Mistakes
|
|
273
|
+
|
|
274
|
+
| Anti-Pattern | Risk | Correct Approach |
|
|
275
|
+
| ------------------------- | ----------------------------------- | ------------------------------------ |
|
|
276
|
+
| **Large payloads** | Memory bloat, serialization issues | Store IDs, fetch fresh in worker |
|
|
277
|
+
| **No retry config** | Transient failures become permanent | Always configure exponential backoff |
|
|
278
|
+
| **Ignoring DLQ** | Failed jobs disappear silently | Monitor and alert on DLQ |
|
|
279
|
+
| **No idempotency** | Duplicate processing corrupts data | Use idempotency key pattern |
|
|
280
|
+
| **Unbounded concurrency** | Resource exhaustion | Set appropriate limits |
|
|
281
|
+
| **Fire and forget** | No visibility into failures | Track completion, handle failures |
|
|
282
|
+
| **Single queue for all** | Priority jobs blocked by bulk | Separate queues by type/priority |
|
|
283
|
+
| **Swallowing errors** | Silent failures | Throw errors, let queue handle retry |
|
|
284
|
+
|
|
285
|
+
### Code Smells
|
|
286
|
+
|
|
287
|
+
```typescript
|
|
288
|
+
// ā SMELL: Catching and ignoring errors
|
|
289
|
+
try {
|
|
290
|
+
await processJob(job);
|
|
291
|
+
} catch (error) {
|
|
292
|
+
console.log("Job failed, continuing..."); // NEVER
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// ā
CORRECT: Let queue handle retry
|
|
296
|
+
async function processJob(job: Job) {
|
|
297
|
+
// Just do the work - errors bubble up to queue
|
|
298
|
+
await doWork(job.data);
|
|
299
|
+
// Queue will retry on failure
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// ā SMELL: No timeout
|
|
303
|
+
const result = await externalApi.call(data); // Could hang forever
|
|
304
|
+
|
|
305
|
+
// ā
CORRECT: Always timeout
|
|
306
|
+
const result = await Promise.race([
|
|
307
|
+
externalApi.call(data),
|
|
308
|
+
timeout(30000, new Error("External API timeout")),
|
|
309
|
+
]);
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
## ā
IMPLEMENTATION CHECKLIST
|
|
315
|
+
|
|
316
|
+
### Job Definition
|
|
317
|
+
|
|
318
|
+
- [ ] Payload contains only IDs (not full objects)
|
|
319
|
+
- [ ] Idempotency key included
|
|
320
|
+
- [ ] Tenant context included (multi-tenant)
|
|
321
|
+
- [ ] Correlation ID for tracing
|
|
322
|
+
- [ ] Appropriate timeout configured
|
|
323
|
+
|
|
324
|
+
### Retry Configuration
|
|
325
|
+
|
|
326
|
+
- [ ] Exponential backoff enabled
|
|
327
|
+
- [ ] Max attempts set (typically 3-5)
|
|
328
|
+
- [ ] Remove on complete configured (with limits)
|
|
329
|
+
- [ ] Remove on fail = false (keep for debugging)
|
|
330
|
+
- [ ] DLQ handling defined
|
|
331
|
+
|
|
332
|
+
### Worker Implementation
|
|
333
|
+
|
|
334
|
+
- [ ] Handler is idempotent
|
|
335
|
+
- [ ] Graceful shutdown implemented
|
|
336
|
+
- [ ] Concurrency limits set
|
|
337
|
+
- [ ] Error handling lets errors bubble up
|
|
338
|
+
- [ ] Logging includes job ID and correlation ID
|
|
339
|
+
|
|
340
|
+
### Monitoring
|
|
341
|
+
|
|
342
|
+
- [ ] Queue depth metric exposed
|
|
343
|
+
- [ ] Processing time metric exposed
|
|
344
|
+
- [ ] DLQ size alerting configured
|
|
345
|
+
- [ ] Failed job rate alerting
|
|
346
|
+
- [ ] Worker health checks
|
|
347
|
+
|
|
348
|
+
---
|
|
349
|
+
|
|
350
|
+
## š References
|
|
351
|
+
|
|
352
|
+
- [BullMQ Documentation](https://docs.bullmq.io/)
|
|
353
|
+
- [RabbitMQ Best Practices](https://www.cloudamqp.com/blog/part1-rabbitmq-best-practice.html)
|
|
354
|
+
- [Idempotency Patterns](https://blog.bytebytego.com/p/idempotency-patterns)
|
|
355
|
+
- [Dead Letter Queue Design](https://aws.amazon.com/blogs/compute/implementing-dead-letter-queues-for-amazon-sqs/)
|
|
356
|
+
|
|
357
|
+
---
|
|
358
|
+
|
|
359
|
+
> **Remember:** Queues are the backbone of async systems. A dropped job is a broken promise. Design for failure: every job should either complete, explicitly fail to DLQ, or be retried. No job should silently disappear.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Assets directory - add templates, images, etc.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Reference Documentation for Queue Patterns
|
|
2
|
+
|
|
3
|
+
[TODO: Add detailed reference content here]
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
[Detailed explanation of concepts]
|
|
8
|
+
|
|
9
|
+
## Deep Dive Topics
|
|
10
|
+
|
|
11
|
+
### Topic 1
|
|
12
|
+
|
|
13
|
+
[Content]
|
|
14
|
+
|
|
15
|
+
### Topic 2
|
|
16
|
+
|
|
17
|
+
[Content]
|
|
18
|
+
|
|
19
|
+
## Examples
|
|
20
|
+
|
|
21
|
+
[Real-world examples]
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Example validator for queue-patterns
|
|
4
|
+
|
|
5
|
+
Usage:
|
|
6
|
+
python validate.py <project_path>
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import sys
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def validate(project_path: str) -> dict:
|
|
14
|
+
"""Main validation logic"""
|
|
15
|
+
results = {
|
|
16
|
+
'errors': [],
|
|
17
|
+
'warnings': [],
|
|
18
|
+
'passed': []
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
# TODO: Add validation logic
|
|
22
|
+
results['passed'].append('Placeholder validation passed')
|
|
23
|
+
|
|
24
|
+
return results
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def print_results(results: dict):
|
|
28
|
+
"""Pretty print results"""
|
|
29
|
+
print("\nš Validation Results\n")
|
|
30
|
+
|
|
31
|
+
if results['errors']:
|
|
32
|
+
print(f"ā Errors ({len(results['errors'])})")
|
|
33
|
+
for error in results['errors']:
|
|
34
|
+
print(f" - {error}")
|
|
35
|
+
|
|
36
|
+
if results['warnings']:
|
|
37
|
+
print(f"\nā ļø Warnings ({len(results['warnings'])})")
|
|
38
|
+
for warning in results['warnings']:
|
|
39
|
+
print(f" - {warning}")
|
|
40
|
+
|
|
41
|
+
if results['passed']:
|
|
42
|
+
print(f"\nā
Passed ({len(results['passed'])})")
|
|
43
|
+
for passed in results['passed']:
|
|
44
|
+
print(f" - {passed}")
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
if __name__ == "__main__":
|
|
48
|
+
if len(sys.argv) < 2:
|
|
49
|
+
print("Usage: python validate.py <project_path>")
|
|
50
|
+
sys.exit(1)
|
|
51
|
+
|
|
52
|
+
project_path = sys.argv[1]
|
|
53
|
+
results = validate(project_path)
|
|
54
|
+
print_results(results)
|
|
55
|
+
|
|
56
|
+
sys.exit(1 if results['errors'] else 0)
|