pgbus 0.0.1 → 0.1.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.
- checksums.yaml +4 -4
- data/README.md +37 -3
- data/Rakefile +98 -1
- data/app/controllers/pgbus/application_controller.rb +8 -0
- data/app/controllers/pgbus/recurring_tasks_controller.rb +36 -0
- data/app/helpers/pgbus/application_helper.rb +41 -0
- data/app/models/pgbus/application_record.rb +7 -0
- data/app/models/pgbus/batch_entry.rb +31 -0
- data/app/models/pgbus/blocked_execution.rb +40 -0
- data/app/models/pgbus/process_entry.rb +9 -0
- data/app/models/pgbus/processed_event.rb +9 -0
- data/app/models/pgbus/recurring_execution.rb +33 -0
- data/app/models/pgbus/recurring_task.rb +42 -0
- data/app/models/pgbus/semaphore.rb +29 -0
- data/app/views/layouts/pgbus/application.html.erb +1 -0
- data/app/views/pgbus/dashboard/_stats_cards.html.erb +9 -1
- data/app/views/pgbus/dead_letter/_messages_table.html.erb +55 -18
- data/app/views/pgbus/jobs/_enqueued_table.html.erb +46 -8
- data/app/views/pgbus/recurring_tasks/_tasks_table.html.erb +79 -0
- data/app/views/pgbus/recurring_tasks/index.html.erb +6 -0
- data/app/views/pgbus/recurring_tasks/show.html.erb +122 -0
- data/config/routes.rb +7 -0
- data/lib/active_job/queue_adapters/pgbus_adapter.rb +29 -0
- data/lib/generators/pgbus/add_recurring_generator.rb +56 -0
- data/lib/generators/pgbus/install_generator.rb +76 -2
- data/lib/generators/pgbus/templates/add_recurring_tables.rb.erb +31 -0
- data/lib/generators/pgbus/templates/migration.rb.erb +72 -4
- data/lib/generators/pgbus/templates/recurring.yml.erb +40 -0
- data/lib/generators/pgbus/templates/upgrade_pgmq.rb.erb +30 -0
- data/lib/generators/pgbus/upgrade_pgmq_generator.rb +60 -0
- data/lib/pgbus/active_job/adapter.rb +0 -3
- data/lib/pgbus/active_job/executor.rb +27 -12
- data/lib/pgbus/batch.rb +60 -69
- data/lib/pgbus/cli.rb +11 -16
- data/lib/pgbus/client.rb +25 -7
- data/lib/pgbus/concurrency/blocked_execution.rb +32 -37
- data/lib/pgbus/concurrency/semaphore.rb +11 -39
- data/lib/pgbus/concurrency.rb +10 -2
- data/lib/pgbus/configuration.rb +33 -0
- data/lib/pgbus/engine.rb +19 -1
- data/lib/pgbus/event_bus/handler.rb +4 -14
- data/lib/pgbus/instrumentation.rb +29 -0
- data/lib/pgbus/pgmq_schema/pgmq_v1.11.0.sql +2123 -0
- data/lib/pgbus/pgmq_schema.rb +159 -0
- data/lib/pgbus/process/consumer.rb +8 -9
- data/lib/pgbus/process/dispatcher.rb +26 -24
- data/lib/pgbus/process/heartbeat.rb +15 -23
- data/lib/pgbus/process/signal_handler.rb +23 -1
- data/lib/pgbus/process/supervisor.rb +51 -2
- data/lib/pgbus/process/worker.rb +37 -9
- data/lib/pgbus/recurring/already_recorded.rb +7 -0
- data/lib/pgbus/recurring/command_job.rb +16 -0
- data/lib/pgbus/recurring/config_loader.rb +35 -0
- data/lib/pgbus/recurring/schedule.rb +102 -0
- data/lib/pgbus/recurring/scheduler.rb +102 -0
- data/lib/pgbus/recurring/task.rb +111 -0
- data/lib/pgbus/serializer.rb +10 -6
- data/lib/pgbus/version.rb +1 -1
- data/lib/pgbus/web/data_source.rb +187 -22
- data/lib/pgbus.rb +8 -0
- data/lib/tasks/pgbus_pgmq.rake +62 -0
- metadata +51 -24
- data/.bun-version +0 -1
- data/.claude/commands/architect.md +0 -100
- data/.claude/commands/github-review-comments.md +0 -237
- data/.claude/commands/lfg.md +0 -271
- data/.claude/commands/review-pr.md +0 -69
- data/.claude/commands/security.md +0 -122
- data/.claude/commands/tdd.md +0 -148
- data/.claude/rules/agents.md +0 -49
- data/.claude/rules/coding-style.md +0 -91
- data/.claude/rules/git-workflow.md +0 -56
- data/.claude/rules/performance.md +0 -73
- data/.claude/rules/testing.md +0 -67
- data/CLAUDE.md +0 -80
- data/CODE_OF_CONDUCT.md +0 -10
- data/bun.lock +0 -18
- data/docs/README.md +0 -28
- data/docs/switch_from_good_job.md +0 -279
- data/docs/switch_from_sidekiq.md +0 -226
- data/docs/switch_from_solid_queue.md +0 -247
- data/package.json +0 -9
- data/sig/pgbus.rbs +0 -4
data/.claude/commands/lfg.md
DELETED
|
@@ -1,271 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: "Executes full autonomous engineering workflow with verification. Use when implementing complete features, tackling GitHub issues, or running end-to-end development cycles."
|
|
3
|
-
model: claude-opus-4-6
|
|
4
|
-
argument-hint: "GitHub issue number/URL or feature description"
|
|
5
|
-
allowed-tools: Bash(gh issue view:*), Bash(gh search:*), Bash(gh issue list:*), Bash(gh pr create:*), Bash(gh pr view:*), Bash(bundle exec:*), Bash(git:*), Read, Write, Edit, Glob, Grep, Agent
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# LFG - Full Autonomous Workflow
|
|
9
|
-
|
|
10
|
-
Execute a complete engineering workflow with verification at each phase.
|
|
11
|
-
|
|
12
|
-
## Phase 0: Branch Setup
|
|
13
|
-
|
|
14
|
-
**BEFORE any other work, prepare the git branch:**
|
|
15
|
-
|
|
16
|
-
1. Check the current branch: `git branch --show-current`
|
|
17
|
-
2. If NOT on `main`, switch: `git checkout main`
|
|
18
|
-
3. Pull latest: `git pull origin main`
|
|
19
|
-
4. Create feature branch: `git checkout -b issue-{number}-{brief-description}` (or `feature/{description}` if no issue number)
|
|
20
|
-
|
|
21
|
-
---
|
|
22
|
-
|
|
23
|
-
## Phase 1: Understand
|
|
24
|
-
|
|
25
|
-
### Step 1: Gather Requirements
|
|
26
|
-
|
|
27
|
-
If `$ARGUMENTS` is a GitHub issue number or URL:
|
|
28
|
-
|
|
29
|
-
```bash
|
|
30
|
-
gh issue view <number> --json title,body,labels,assignees,comments
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
If `$ARGUMENTS` is a description, use it directly.
|
|
34
|
-
|
|
35
|
-
### Step 2: Define Acceptance Criteria
|
|
36
|
-
|
|
37
|
-
**MANDATORY:** Write explicit acceptance criteria:
|
|
38
|
-
|
|
39
|
-
- **GIVEN** [context/setup]
|
|
40
|
-
- **WHEN** [action taken]
|
|
41
|
-
- **THEN** [expected outcome]
|
|
42
|
-
|
|
43
|
-
You MUST NOT proceed until you can articulate these clearly.
|
|
44
|
-
|
|
45
|
-
### Step 3: Comprehension Gate
|
|
46
|
-
|
|
47
|
-
Before proceeding, you must:
|
|
48
|
-
|
|
49
|
-
1. State the problem/feature in one sentence
|
|
50
|
-
2. Explain WHY this is needed (business context)
|
|
51
|
-
3. List what will change from the user's perspective
|
|
52
|
-
4. Identify edge cases not explicitly mentioned
|
|
53
|
-
5. Explain the data flow or code path involved
|
|
54
|
-
|
|
55
|
-
If you cannot complete ALL five items, investigate further.
|
|
56
|
-
|
|
57
|
-
### Step 4: Create Task List
|
|
58
|
-
|
|
59
|
-
Create a TaskCreate todo list with specific implementation steps.
|
|
60
|
-
|
|
61
|
-
---
|
|
62
|
-
|
|
63
|
-
## Phase 2: Explore
|
|
64
|
-
|
|
65
|
-
1. Find related files (Glob/Grep or Explore agent)
|
|
66
|
-
2. Read existing patterns in similar features
|
|
67
|
-
3. Understand dependencies and integration points
|
|
68
|
-
4. Check existing test coverage
|
|
69
|
-
5. Review PGMQ client interactions in `lib/pgbus/client.rb`
|
|
70
|
-
6. Check ActiveJob adapter in `lib/pgbus/active_job/`
|
|
71
|
-
7. Review event bus patterns in `lib/pgbus/event_bus/`
|
|
72
|
-
8. Check process model in `lib/pgbus/process/`
|
|
73
|
-
|
|
74
|
-
---
|
|
75
|
-
|
|
76
|
-
## Phase 3: Plan
|
|
77
|
-
|
|
78
|
-
1. List files to modify with specific changes
|
|
79
|
-
2. List new files to create with purpose
|
|
80
|
-
3. Identify migration changes needed (PGMQ queues, metadata tables)
|
|
81
|
-
4. Plan test coverage (TDD: tests FIRST)
|
|
82
|
-
5. Update task list with implementation steps
|
|
83
|
-
6. Consider backwards compatibility with existing queue configurations
|
|
84
|
-
|
|
85
|
-
---
|
|
86
|
-
|
|
87
|
-
## Phase 4: Implement (TDD)
|
|
88
|
-
|
|
89
|
-
For each logical unit:
|
|
90
|
-
|
|
91
|
-
### 4.1: Write Failing Test First
|
|
92
|
-
|
|
93
|
-
Create a test that demonstrates the expected behavior. Run it to confirm it FAILS:
|
|
94
|
-
|
|
95
|
-
```bash
|
|
96
|
-
bundle exec rspec <spec_file>
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
### 4.2: Implement Minimum Code
|
|
100
|
-
|
|
101
|
-
Write the MINIMUM code to make the test pass. Follow project patterns:
|
|
102
|
-
|
|
103
|
-
| Never Do | Always Do |
|
|
104
|
-
|----------|-----------|
|
|
105
|
-
| Direct PGMQ SQL calls | Use `Pgbus::Client` wrapper |
|
|
106
|
-
| Skip queue prefixing | Always use `config.queue_name()` |
|
|
107
|
-
| Hardcode queue names | Use configuration |
|
|
108
|
-
| Skip visibility timeout | Use PGMQ's native VT mechanism |
|
|
109
|
-
| Ignore dead letter routing | Check `read_ct` against `max_retries` |
|
|
110
|
-
| Raw SQL in controllers | Use `Web::DataSource` for dashboard |
|
|
111
|
-
|
|
112
|
-
### 4.3: Refactor
|
|
113
|
-
|
|
114
|
-
Once green, refactor while keeping tests passing.
|
|
115
|
-
|
|
116
|
-
### 4.4: Validate
|
|
117
|
-
|
|
118
|
-
```bash
|
|
119
|
-
bundle exec rubocop <changed_files>
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
### 4.5: Repeat
|
|
123
|
-
|
|
124
|
-
Move to next logical unit. Mark task items complete.
|
|
125
|
-
|
|
126
|
-
---
|
|
127
|
-
|
|
128
|
-
## Phase 5: Deep Root Cause Analysis (Bug Fixes Only)
|
|
129
|
-
|
|
130
|
-
**If this is a bug fix, apply deep investigation before implementing:**
|
|
131
|
-
|
|
132
|
-
### Trace the Data Lifecycle
|
|
133
|
-
|
|
134
|
-
For the message/job/event causing the issue:
|
|
135
|
-
- Where and when was the message enqueued? By what adapter call?
|
|
136
|
-
- What visibility timeout was set? Has it expired?
|
|
137
|
-
- What ASSUMPTIONS does the code make at the failure point?
|
|
138
|
-
- Which assumption was violated, and WHY?
|
|
139
|
-
|
|
140
|
-
### Use Git History
|
|
141
|
-
|
|
142
|
-
```bash
|
|
143
|
-
git log --oneline -20 <file>
|
|
144
|
-
git blame <file>
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
- When was the code written? What was the original intent?
|
|
148
|
-
- Has something ELSE changed that invalidated the original assumptions?
|
|
149
|
-
|
|
150
|
-
### Map All Callers
|
|
151
|
-
|
|
152
|
-
Don't just look at the method that failed:
|
|
153
|
-
- Use Grep to find all call sites
|
|
154
|
-
- Different contexts (ActiveJob adapter vs event bus vs dashboard)?
|
|
155
|
-
- Does the error only happen in ONE context? Why?
|
|
156
|
-
|
|
157
|
-
### Five Whys
|
|
158
|
-
|
|
159
|
-
Keep asking WHY until you reach a meaningful fix point:
|
|
160
|
-
|
|
161
|
-
1. Error: X happened -> Why?
|
|
162
|
-
2. Because Y -> Why was Y in that state?
|
|
163
|
-
3. Because Z -> Why wasn't Z prevented?
|
|
164
|
-
4. Because no check existed -> Why not?
|
|
165
|
-
5. **THIS** is where the fix belongs
|
|
166
|
-
|
|
167
|
-
### Fix Location Principle
|
|
168
|
-
|
|
169
|
-
The best fix is usually NOT where the error is raised:
|
|
170
|
-
- Nil message in executor -> fix in worker that should provide non-nil
|
|
171
|
-
- Queue not found -> fix in code that should ensure_queue first
|
|
172
|
-
- Race condition -> PGMQ-level visibility timeout
|
|
173
|
-
- Dead letter overflow -> fix the retry/DLQ routing logic
|
|
174
|
-
|
|
175
|
-
**Ask: "Where is the EARLIEST point I could prevent this error?" Fix there.**
|
|
176
|
-
|
|
177
|
-
### Unacceptable Superficial Fixes -- DO NOT DO THESE
|
|
178
|
-
|
|
179
|
-
- `rescue nil` without understanding why the exception occurs
|
|
180
|
-
- `&.` to silence nil errors without investigating why nil occurs
|
|
181
|
-
- `if object.present?` guards without understanding why missing
|
|
182
|
-
- `return if message.nil?` to silently skip processing
|
|
183
|
-
- Wrapping everything in `begin/rescue` to swallow errors
|
|
184
|
-
|
|
185
|
-
**These HIDE bugs. The root cause continues causing issues elsewhere.**
|
|
186
|
-
|
|
187
|
-
---
|
|
188
|
-
|
|
189
|
-
## Phase 6: Verify
|
|
190
|
-
|
|
191
|
-
**ALL of these must pass before committing:**
|
|
192
|
-
|
|
193
|
-
```bash
|
|
194
|
-
bundle exec rubocop # Style
|
|
195
|
-
bundle exec rspec <relevant_specs> # Tests
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
### Solution Verification
|
|
199
|
-
|
|
200
|
-
Re-read the original requirements and verify:
|
|
201
|
-
- "If I were the requester, would I consider this fully resolved?"
|
|
202
|
-
- "Have I addressed the ROOT CAUSE, not just the symptom?"
|
|
203
|
-
- "Do my tests prove the issue is ACTUALLY fixed, not just suppressed?"
|
|
204
|
-
- "Does this maintain backwards compatibility?"
|
|
205
|
-
|
|
206
|
-
---
|
|
207
|
-
|
|
208
|
-
## Phase 7: Commit & PR
|
|
209
|
-
|
|
210
|
-
### Commit
|
|
211
|
-
|
|
212
|
-
```bash
|
|
213
|
-
git add <specific_files>
|
|
214
|
-
git commit -m "$(cat <<'EOF'
|
|
215
|
-
feat(scope): brief description
|
|
216
|
-
|
|
217
|
-
## Summary
|
|
218
|
-
[What changed and why]
|
|
219
|
-
|
|
220
|
-
## Test Coverage
|
|
221
|
-
- spec 1: validates requirement X
|
|
222
|
-
- spec 2: validates edge case Y
|
|
223
|
-
|
|
224
|
-
## Verification
|
|
225
|
-
- [x] bundle exec rubocop passes
|
|
226
|
-
- [x] bundle exec rspec passes
|
|
227
|
-
EOF
|
|
228
|
-
)"
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
### Push & PR
|
|
232
|
-
|
|
233
|
-
```bash
|
|
234
|
-
git push -u origin $(git branch --show-current)
|
|
235
|
-
|
|
236
|
-
gh pr create --title "feat(scope): brief description" --body "$(cat <<'EOF'
|
|
237
|
-
## Summary
|
|
238
|
-
- Key change 1
|
|
239
|
-
- Key change 2
|
|
240
|
-
|
|
241
|
-
Closes #<issue_number>
|
|
242
|
-
|
|
243
|
-
## Test plan
|
|
244
|
-
- [ ] Scenario 1
|
|
245
|
-
- [ ] Scenario 2
|
|
246
|
-
EOF
|
|
247
|
-
)"
|
|
248
|
-
```
|
|
249
|
-
|
|
250
|
-
---
|
|
251
|
-
|
|
252
|
-
## Verification Checklist
|
|
253
|
-
|
|
254
|
-
- [ ] All acceptance criteria met
|
|
255
|
-
- [ ] Tests written BEFORE implementation
|
|
256
|
-
- [ ] `bundle exec rubocop` passes
|
|
257
|
-
- [ ] `bundle exec rspec` passes
|
|
258
|
-
- [ ] Backwards compatibility maintained
|
|
259
|
-
- [ ] PGMQ operations go through Client wrapper
|
|
260
|
-
- [ ] PR created with description
|
|
261
|
-
|
|
262
|
-
---
|
|
263
|
-
|
|
264
|
-
## Handoff
|
|
265
|
-
|
|
266
|
-
When complete:
|
|
267
|
-
- All phases executed
|
|
268
|
-
- Verification passed
|
|
269
|
-
- PR created and linked
|
|
270
|
-
|
|
271
|
-
Now, execute this workflow for the provided issue or feature.
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Review a GitHub pull request for code quality, patterns, and best practices
|
|
3
|
-
model: claude-opus-4-6
|
|
4
|
-
argument-hint: "PR URL or number (e.g., 5 or https://github.com/mhenrixon/pgbus/pull/5)"
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# PR Review
|
|
8
|
-
|
|
9
|
-
Review PR for pattern compliance and issues. Be concise.
|
|
10
|
-
|
|
11
|
-
## Workflow
|
|
12
|
-
|
|
13
|
-
1. Fetch PR details and diff via `mcp__github__pull_request_read`
|
|
14
|
-
2. Categorize files by type
|
|
15
|
-
3. Check for pattern violations
|
|
16
|
-
4. Output structured review
|
|
17
|
-
|
|
18
|
-
## Pattern Violations to Check
|
|
19
|
-
|
|
20
|
-
```ruby
|
|
21
|
-
# WRONG -> RIGHT
|
|
22
|
-
Direct PGMQ calls outside Client -> Use Pgbus::Client wrapper
|
|
23
|
-
Raw SQL in controllers/views -> Use Web::DataSource
|
|
24
|
-
Hardcoded queue names -> Use config.queue_name()
|
|
25
|
-
Missing visibility timeout -> Always pass vt: parameter
|
|
26
|
-
Skip dead letter routing -> Check read_ct > max_retries
|
|
27
|
-
No error handling in workers -> Rescue and log via Pgbus.logger
|
|
28
|
-
Polling without LISTEN/NOTIFY -> Use enable_notify_insert
|
|
29
|
-
Missing queue prefix -> All queues go through config.queue_name
|
|
30
|
-
Thread.new for concurrency -> Use Concurrent::* primitives
|
|
31
|
-
rescue StandardError => nil -> Specific error handling
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
## Output Format
|
|
35
|
-
|
|
36
|
-
```
|
|
37
|
-
## Files Requiring Manual Review
|
|
38
|
-
|
|
39
|
-
| File | Reason |
|
|
40
|
-
|------|--------|
|
|
41
|
-
| lib/pgbus/process/worker.rb | Worker recycling logic, verify thresholds |
|
|
42
|
-
| lib/pgbus/client.rb | PGMQ interaction, check thread safety |
|
|
43
|
-
|
|
44
|
-
## Critical Issues
|
|
45
|
-
|
|
46
|
-
- `lib/pgbus/client.rb:45` - Missing mutex synchronization
|
|
47
|
-
- `lib/pgbus/process/worker.rb:12` - Memory check not platform-aware
|
|
48
|
-
|
|
49
|
-
## Suggestions (non-blocking)
|
|
50
|
-
|
|
51
|
-
- Consider extracting X to shared module
|
|
52
|
-
|
|
53
|
-
## Verdict
|
|
54
|
-
|
|
55
|
-
**Request Changes** - Fix thread safety before merge
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
## Tools
|
|
59
|
-
|
|
60
|
-
```
|
|
61
|
-
mcp__github__pull_request_read
|
|
62
|
-
method: "get" -> PR details
|
|
63
|
-
method: "get_diff" -> Changes
|
|
64
|
-
method: "get_files" -> File list
|
|
65
|
-
method: "get_status" -> CI status
|
|
66
|
-
|
|
67
|
-
bundle exec rubocop -> Style checks
|
|
68
|
-
bundle exec rspec -> Tests
|
|
69
|
-
```
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: "Reviews code for security vulnerabilities. Use when auditing PGMQ operations, connection handling, SQL injection risks, or dashboard authentication."
|
|
3
|
-
model: claude-opus-4-6
|
|
4
|
-
argument-hint: "code, feature, or area to review for security"
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Security Specialist
|
|
8
|
-
|
|
9
|
-
You are the **Security review and vulnerability audit specialist** for pgbus.
|
|
10
|
-
|
|
11
|
-
## Trigger Contexts
|
|
12
|
-
|
|
13
|
-
Use this skill when:
|
|
14
|
-
- Auditing PGMQ SQL operations for injection risks
|
|
15
|
-
- Reviewing connection pool handling
|
|
16
|
-
- Checking for race conditions in message processing
|
|
17
|
-
- Reviewing deserialization of job arguments / event payloads
|
|
18
|
-
- Auditing the dashboard web UI
|
|
19
|
-
- Reviewing worker process management
|
|
20
|
-
|
|
21
|
-
## Key Security Concerns for This Gem
|
|
22
|
-
|
|
23
|
-
### SQL Injection via Queue Names
|
|
24
|
-
|
|
25
|
-
```ruby
|
|
26
|
-
# BAD: Unsanitized queue name in SQL
|
|
27
|
-
connection.execute("SELECT * FROM pgmq.q_#{queue_name}")
|
|
28
|
-
|
|
29
|
-
# GOOD: Sanitize queue names
|
|
30
|
-
def sanitize_name(name)
|
|
31
|
-
name.gsub(/[^a-zA-Z0-9_]/, "")
|
|
32
|
-
end
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
PGMQ queue names are interpolated into SQL identifiers. The `Client` validates names, but any new code touching queue names must sanitize.
|
|
36
|
-
|
|
37
|
-
### Connection Pool Safety
|
|
38
|
-
|
|
39
|
-
- pgmq-ruby uses `connection_pool` gem for thread-safe pooling
|
|
40
|
-
- Never hold a connection across async boundaries
|
|
41
|
-
- `TransactionalClient` pins a single connection -- ensure it's not leaked
|
|
42
|
-
- When using `-> { ActiveRecord::Base.connection.raw_connection }`, connection lifecycle is Rails-managed
|
|
43
|
-
|
|
44
|
-
### Message Deserialization
|
|
45
|
-
|
|
46
|
-
```ruby
|
|
47
|
-
# BAD: Unsafe deserialization
|
|
48
|
-
Marshal.load(message.message)
|
|
49
|
-
|
|
50
|
-
# GOOD: JSON only
|
|
51
|
-
JSON.parse(message.message)
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
- All payloads are JSONB -- stick to JSON.parse
|
|
55
|
-
- ActiveJob's `deserialize` handles GlobalID resolution -- trust it but validate
|
|
56
|
-
- Event payloads with `_global_id` call `GlobalID::Locator.locate` -- ensure objects exist
|
|
57
|
-
|
|
58
|
-
### Dashboard Authentication
|
|
59
|
-
|
|
60
|
-
- `web_auth` block receives the raw request -- must be configured by the host app
|
|
61
|
-
- Default is `nil` (allow all) -- document this clearly
|
|
62
|
-
- Dashboard inherits from `ActionController::Base` (isolated from host app)
|
|
63
|
-
- Never expose raw PGMQ internals without sanitization
|
|
64
|
-
- Filter sensitive job arguments in the UI
|
|
65
|
-
|
|
66
|
-
### Worker Process Security
|
|
67
|
-
|
|
68
|
-
- Supervisor forks child processes -- signal handling must be correct
|
|
69
|
-
- Worker recycling kills processes -- ensure graceful cleanup
|
|
70
|
-
- Heartbeat writes to DB -- validate process ownership
|
|
71
|
-
- Memory measurement uses `ps` / `/proc` -- no shell injection risk (pid is numeric)
|
|
72
|
-
|
|
73
|
-
### Visibility Timeout / Message Safety
|
|
74
|
-
|
|
75
|
-
- Messages become visible again after VT expires -- idempotency is critical
|
|
76
|
-
- `read_ct` tracks redeliveries -- DLQ routing must be reliable
|
|
77
|
-
- `FOR UPDATE SKIP LOCKED` prevents double-processing -- verify all read paths use it
|
|
78
|
-
- Archive vs delete: archived messages are queryable, deleted are gone
|
|
79
|
-
|
|
80
|
-
## Verification Checklist
|
|
81
|
-
|
|
82
|
-
- [ ] No SQL injection via queue names
|
|
83
|
-
- [ ] All PGMQ operations go through Client (sanitized)
|
|
84
|
-
- [ ] Connection pool properly managed
|
|
85
|
-
- [ ] No unsafe deserialization (JSON only)
|
|
86
|
-
- [ ] Dashboard auth is configurable and documented
|
|
87
|
-
- [ ] Worker signals handled correctly
|
|
88
|
-
- [ ] No secrets in logs or error messages
|
|
89
|
-
- [ ] Idempotency enforced for event handlers
|
|
90
|
-
|
|
91
|
-
## Security Tools
|
|
92
|
-
|
|
93
|
-
```bash
|
|
94
|
-
# Static analysis
|
|
95
|
-
bundle exec rubocop
|
|
96
|
-
|
|
97
|
-
# Check for known vulnerabilities in dependencies
|
|
98
|
-
bundle audit check --update
|
|
99
|
-
|
|
100
|
-
# Review queue name handling
|
|
101
|
-
grep -r "pgmq\.q_\|pgmq\.a_" lib/
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
## Common Mistakes to Avoid
|
|
105
|
-
|
|
106
|
-
| Wrong | Right |
|
|
107
|
-
|-------|-------|
|
|
108
|
-
| String interpolation in SQL | Parameterized queries or sanitized identifiers |
|
|
109
|
-
| Marshal.load on payloads | JSON.parse only |
|
|
110
|
-
| Global PGMQ client without pool | Connection pool with thread safety |
|
|
111
|
-
| Default-open dashboard | Require explicit auth configuration |
|
|
112
|
-
| Swallowing worker errors | Log and track via failed_events table |
|
|
113
|
-
| Infinite visibility timeout | Always set reasonable VT with DLQ fallback |
|
|
114
|
-
|
|
115
|
-
## Handoff
|
|
116
|
-
|
|
117
|
-
When complete, summarize:
|
|
118
|
-
- Vulnerabilities found (with severity)
|
|
119
|
-
- Remediation steps
|
|
120
|
-
- Tests to add
|
|
121
|
-
|
|
122
|
-
Now, focus on security review for the current task.
|
data/.claude/commands/tdd.md
DELETED
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: "Use when implementing any feature or fixing any bug -- enforces RED-GREEN-REFACTOR: write failing test first, implement minimum code to pass, then refactor."
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# TDD Command
|
|
6
|
-
|
|
7
|
-
Enforce test-driven development methodology with RED -> GREEN -> REFACTOR cycle.
|
|
8
|
-
|
|
9
|
-
## The TDD Cycle
|
|
10
|
-
|
|
11
|
-
```text
|
|
12
|
-
RED -> GREEN -> REFACTOR -> REPEAT
|
|
13
|
-
|
|
14
|
-
RED: Write a failing test (test MUST fail first)
|
|
15
|
-
GREEN: Write MINIMAL code to pass (nothing more)
|
|
16
|
-
REFACTOR: Improve code while keeping tests green
|
|
17
|
-
REPEAT: Next feature/scenario
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
## When to Use
|
|
21
|
-
|
|
22
|
-
- Implementing new features
|
|
23
|
-
- Adding new queue types or event handlers
|
|
24
|
-
- Fixing bugs (write test that reproduces bug FIRST)
|
|
25
|
-
- Refactoring existing code
|
|
26
|
-
- Modifying the ActiveJob adapter
|
|
27
|
-
- Changing worker/process behavior
|
|
28
|
-
- Adding dashboard endpoints
|
|
29
|
-
|
|
30
|
-
## Workflow
|
|
31
|
-
|
|
32
|
-
### Step 1: Write Failing Tests (RED)
|
|
33
|
-
|
|
34
|
-
```ruby
|
|
35
|
-
# spec/pgbus/example_spec.rb
|
|
36
|
-
RSpec.describe Pgbus::NewFeature do
|
|
37
|
-
describe "#process" do
|
|
38
|
-
context "when message is valid" do
|
|
39
|
-
it "processes successfully" do
|
|
40
|
-
expect(subject.process(message)).to eq(:success)
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
context "when max retries exceeded" do
|
|
45
|
-
it "routes to dead letter queue" do
|
|
46
|
-
expect(subject.process(stale_message)).to eq(:dead_lettered)
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
### Step 2: Run Tests - Verify FAIL
|
|
54
|
-
|
|
55
|
-
```bash
|
|
56
|
-
bundle exec rspec spec/pgbus/example_spec.rb
|
|
57
|
-
|
|
58
|
-
FAIL - NotImplementedError / Expected behavior not met
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
**Tests MUST fail before implementing.** This confirms:
|
|
62
|
-
- Tests are actually running
|
|
63
|
-
- Tests are testing the right thing
|
|
64
|
-
- Implementation doesn't already exist
|
|
65
|
-
|
|
66
|
-
### Step 3: Implement Minimal Code (GREEN)
|
|
67
|
-
|
|
68
|
-
Write the minimum code to make the test pass.
|
|
69
|
-
|
|
70
|
-
### Step 4: Run Tests - Verify PASS
|
|
71
|
-
|
|
72
|
-
```bash
|
|
73
|
-
bundle exec rspec spec/pgbus/example_spec.rb
|
|
74
|
-
|
|
75
|
-
N examples, 0 failures
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
### Step 5: Refactor (IMPROVE)
|
|
79
|
-
|
|
80
|
-
Improve code while keeping tests green:
|
|
81
|
-
- Extract methods to reduce complexity
|
|
82
|
-
- Improve naming
|
|
83
|
-
- Reduce duplication
|
|
84
|
-
- Ensure thread safety
|
|
85
|
-
|
|
86
|
-
### Step 6: Run Full Suite
|
|
87
|
-
|
|
88
|
-
```bash
|
|
89
|
-
bundle exec rspec
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
## Coverage Requirements
|
|
93
|
-
|
|
94
|
-
| Code Type | Minimum Coverage |
|
|
95
|
-
|-----------|------------------|
|
|
96
|
-
| All code | 80% |
|
|
97
|
-
| ActiveJob adapter | 100% |
|
|
98
|
-
| Event bus (handler, registry) | 100% |
|
|
99
|
-
| Process model (worker, supervisor) | 100% |
|
|
100
|
-
| Client (PGMQ wrapper) | 100% |
|
|
101
|
-
| Web::DataSource | 100% |
|
|
102
|
-
| Configuration | 100% |
|
|
103
|
-
|
|
104
|
-
## Test Types to Include
|
|
105
|
-
|
|
106
|
-
### Unit Tests (Configuration, Event, Serializer)
|
|
107
|
-
- Happy path scenarios
|
|
108
|
-
- Edge cases (nil values, empty queues, expired VT)
|
|
109
|
-
- Error conditions
|
|
110
|
-
|
|
111
|
-
### Integration Tests (Client, Adapter, Worker)
|
|
112
|
-
- ActiveJob enqueue/execute lifecycle
|
|
113
|
-
- Worker claim-process-archive flow
|
|
114
|
-
- Dead letter queue routing
|
|
115
|
-
- Event publish/subscribe round-trip
|
|
116
|
-
|
|
117
|
-
### Web Tests (DataSource, Authentication)
|
|
118
|
-
- DataSource with mocked PGMQ client
|
|
119
|
-
- Authentication block allow/deny
|
|
120
|
-
- Helper formatting
|
|
121
|
-
|
|
122
|
-
## Best Practices
|
|
123
|
-
|
|
124
|
-
**DO:**
|
|
125
|
-
- Write the test FIRST, before any implementation
|
|
126
|
-
- Run tests and verify they FAIL before implementing
|
|
127
|
-
- Write MINIMAL code to make tests pass
|
|
128
|
-
- Refactor only after tests are green
|
|
129
|
-
- Mock PGMQ client in unit tests (avoid DB dependency)
|
|
130
|
-
- Test worker recycling thresholds explicitly
|
|
131
|
-
|
|
132
|
-
**DON'T:**
|
|
133
|
-
- Write implementation before tests
|
|
134
|
-
- Skip running tests after each change
|
|
135
|
-
- Write too much code at once
|
|
136
|
-
- Ignore failing tests
|
|
137
|
-
- Test implementation details (test behavior)
|
|
138
|
-
- Skip testing error paths
|
|
139
|
-
|
|
140
|
-
## Checklist
|
|
141
|
-
|
|
142
|
-
- [ ] Tests written BEFORE implementation
|
|
143
|
-
- [ ] Tests fail initially (RED phase verified)
|
|
144
|
-
- [ ] Minimal code written to pass (GREEN)
|
|
145
|
-
- [ ] Code refactored with tests still passing
|
|
146
|
-
- [ ] Coverage meets requirements (80%+)
|
|
147
|
-
- [ ] All edge cases covered
|
|
148
|
-
- [ ] Backwards compatibility maintained
|
data/.claude/rules/agents.md
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
# Agent Orchestration Rules
|
|
2
|
-
|
|
3
|
-
## Available Agents
|
|
4
|
-
|
|
5
|
-
| Agent | Purpose | When to Use |
|
|
6
|
-
|-------|---------|-------------|
|
|
7
|
-
| Explore | Codebase exploration | Finding files, understanding patterns |
|
|
8
|
-
| Plan | Implementation planning | Complex features, architectural decisions |
|
|
9
|
-
| general-purpose | Multi-step tasks | Research, complex searches |
|
|
10
|
-
|
|
11
|
-
## Immediate Agent Usage
|
|
12
|
-
|
|
13
|
-
Use agents PROACTIVELY without waiting for user prompt:
|
|
14
|
-
|
|
15
|
-
1. **Complex feature requests** -> Use Plan agent first
|
|
16
|
-
2. **Codebase exploration** -> Use Explore agent
|
|
17
|
-
3. **Multi-file searches** -> Use Explore agent (not direct Glob/Grep)
|
|
18
|
-
4. **Architectural decisions** -> Use Plan agent
|
|
19
|
-
|
|
20
|
-
## Parallel Execution
|
|
21
|
-
|
|
22
|
-
**ALWAYS** use parallel Task execution for independent operations:
|
|
23
|
-
|
|
24
|
-
```markdown
|
|
25
|
-
# GOOD: Parallel execution
|
|
26
|
-
Launch multiple agents simultaneously:
|
|
27
|
-
1. Agent 1: Explore client/adapter patterns
|
|
28
|
-
2. Agent 2: Check event bus patterns
|
|
29
|
-
3. Agent 3: Review test coverage
|
|
30
|
-
|
|
31
|
-
# BAD: Sequential when unnecessary
|
|
32
|
-
First explore, wait, then check patterns, wait, then review...
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
## When to Use Explore Agent
|
|
36
|
-
|
|
37
|
-
Use the Explore agent (subagent_type=Explore) instead of direct Glob/Grep when:
|
|
38
|
-
- Open-ended codebase exploration
|
|
39
|
-
- Searching for patterns across client, adapter, event bus, and process layers
|
|
40
|
-
- Answering questions about codebase structure
|
|
41
|
-
- Finding related implementations across modules
|
|
42
|
-
|
|
43
|
-
## When NOT to Use Agents
|
|
44
|
-
|
|
45
|
-
Use direct tools when:
|
|
46
|
-
- Reading a specific known file path
|
|
47
|
-
- Simple pattern match in known location
|
|
48
|
-
- Single-file edits
|
|
49
|
-
- Running specific commands
|