claude-agent-framework 1.0.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/README.md +128 -0
- package/bin/claude-framework +3 -0
- package/framework/agents/design-lead.md +240 -0
- package/framework/agents/product-owner.md +179 -0
- package/framework/agents/tech-lead.md +226 -0
- package/framework/commands/ayuda.md +127 -0
- package/framework/commands/a/303/261adir.md +98 -0
- package/framework/commands/backup.md +397 -0
- package/framework/commands/cambiar.md +110 -0
- package/framework/commands/cloud.md +457 -0
- package/framework/commands/code.md +142 -0
- package/framework/commands/debug.md +334 -0
- package/framework/commands/deploy.md +383 -0
- package/framework/commands/deshacer.md +120 -0
- package/framework/commands/estado.md +218 -0
- package/framework/commands/explica.md +227 -0
- package/framework/commands/feature.md +120 -0
- package/framework/commands/git.md +427 -0
- package/framework/commands/historial.md +202 -0
- package/framework/commands/learn.md +408 -0
- package/framework/commands/movil.md +245 -0
- package/framework/commands/nuevo.md +118 -0
- package/framework/commands/plan.md +134 -0
- package/framework/commands/prd.md +113 -0
- package/framework/commands/probar.md +148 -0
- package/framework/commands/revisar.md +208 -0
- package/framework/commands/seeds.md +230 -0
- package/framework/commands/seguridad.md +226 -0
- package/framework/commands/tasks.md +157 -0
- package/framework/skills/architecture/algorithms.md +970 -0
- package/framework/skills/architecture/clean-code.md +1080 -0
- package/framework/skills/architecture/design-patterns.md +1984 -0
- package/framework/skills/architecture/functional-programming.md +972 -0
- package/framework/skills/architecture/solid.md +991 -0
- package/framework/skills/cloud/cloud-aws.md +848 -0
- package/framework/skills/cloud/cloud-azure.md +931 -0
- package/framework/skills/cloud/cloud-gcp.md +848 -0
- package/framework/skills/cloud/message-queues.md +1229 -0
- package/framework/skills/core/accessibility.md +401 -0
- package/framework/skills/core/api.md +474 -0
- package/framework/skills/core/authentication.md +306 -0
- package/framework/skills/core/authorization.md +388 -0
- package/framework/skills/core/background-jobs.md +341 -0
- package/framework/skills/core/caching.md +473 -0
- package/framework/skills/core/code-review.md +341 -0
- package/framework/skills/core/controllers.md +290 -0
- package/framework/skills/core/cua.md +285 -0
- package/framework/skills/core/documentation.md +472 -0
- package/framework/skills/core/file-uploads.md +351 -0
- package/framework/skills/core/hotwire-native.md +296 -0
- package/framework/skills/core/hotwire.md +278 -0
- package/framework/skills/core/i18n.md +334 -0
- package/framework/skills/core/imports-exports.md +750 -0
- package/framework/skills/core/infrastructure.md +337 -0
- package/framework/skills/core/models.md +228 -0
- package/framework/skills/core/notifications.md +672 -0
- package/framework/skills/core/payments.md +581 -0
- package/framework/skills/core/performance.md +361 -0
- package/framework/skills/core/rails-scaffold.md +131 -0
- package/framework/skills/core/search.md +518 -0
- package/framework/skills/core/security.md +565 -0
- package/framework/skills/core/seeds.md +307 -0
- package/framework/skills/core/seo.md +542 -0
- package/framework/skills/core/testing.md +393 -0
- package/framework/skills/core/views.md +260 -0
- package/framework/skills/core/websockets.md +564 -0
- package/framework/skills/data/advanced-sql.md +1204 -0
- package/framework/skills/data/nosql.md +1141 -0
- package/framework/skills/devops/containers-advanced.md +1237 -0
- package/framework/skills/devops/debugging.md +834 -0
- package/framework/skills/devops/git-workflow.md +752 -0
- package/framework/skills/devops/networking.md +932 -0
- package/framework/skills/devops/shell-scripting.md +1132 -0
- package/framework/sub-agents/architecture-patterns-agent.md +1450 -0
- package/framework/sub-agents/cloud-agent.md +677 -0
- package/framework/sub-agents/data.md +504 -0
- package/framework/sub-agents/debugging-agent.md +554 -0
- package/framework/sub-agents/devops.md +483 -0
- package/framework/sub-agents/docs.md +176 -0
- package/framework/sub-agents/frontend-dev.md +349 -0
- package/framework/sub-agents/git-workflow-agent.md +697 -0
- package/framework/sub-agents/integrations.md +630 -0
- package/framework/sub-agents/native-dev.md +434 -0
- package/framework/sub-agents/qa.md +138 -0
- package/framework/sub-agents/rails-dev.md +375 -0
- package/framework/sub-agents/security.md +526 -0
- package/framework/sub-agents/ui.md +437 -0
- package/framework/sub-agents/ux.md +284 -0
- package/framework/templates/api-spec.md +500 -0
- package/framework/templates/component-spec.md +248 -0
- package/framework/templates/feature.json +13 -0
- package/framework/templates/model-spec.md +318 -0
- package/framework/templates/prd-template.md +80 -0
- package/framework/templates/task-plan.md +122 -0
- package/framework/templates/task-user-story.md +52 -0
- package/framework/templates/technical-spec.md +260 -0
- package/framework/templates/user-story.md +95 -0
- package/package.json +42 -0
- package/project-templates/CLAUDE.md +42 -0
- package/project-templates/contexts/architecture.md +25 -0
- package/project-templates/contexts/conventions.md +46 -0
- package/project-templates/contexts/design-system.md +47 -0
- package/project-templates/contexts/requirements.md +38 -0
- package/project-templates/contexts/stack.md +30 -0
- package/project-templates/history/active/models.md +11 -0
- package/project-templates/history/changelog.md +15 -0
- package/project-templates/workspace/.gitkeep +0 -0
- package/src/cli.js +52 -0
- package/src/init.js +104 -0
- package/src/status.js +75 -0
- package/src/update.js +88 -0
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
# Skill: Background Jobs
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
Implement asynchronous job processing using Solid Queue (Rails 8 default).
|
|
5
|
+
|
|
6
|
+
## Overview
|
|
7
|
+
|
|
8
|
+
Solid Queue is Rails 8's default Active Job backend, using the database for job storage. No Redis required.
|
|
9
|
+
|
|
10
|
+
## Configuration
|
|
11
|
+
|
|
12
|
+
### Database Setup
|
|
13
|
+
```bash
|
|
14
|
+
rails generate solid_queue:install
|
|
15
|
+
rails db:migrate
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### Configure Active Job
|
|
19
|
+
```ruby
|
|
20
|
+
# config/application.rb
|
|
21
|
+
config.active_job.queue_adapter = :solid_queue
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Queue Configuration
|
|
25
|
+
```yaml
|
|
26
|
+
# config/queue.yml
|
|
27
|
+
default: &default
|
|
28
|
+
dispatchers:
|
|
29
|
+
- polling_interval: 1
|
|
30
|
+
batch_size: 500
|
|
31
|
+
workers:
|
|
32
|
+
- queues: "*"
|
|
33
|
+
threads: 3
|
|
34
|
+
processes: 1
|
|
35
|
+
polling_interval: 0.1
|
|
36
|
+
|
|
37
|
+
development:
|
|
38
|
+
<<: *default
|
|
39
|
+
|
|
40
|
+
production:
|
|
41
|
+
<<: *default
|
|
42
|
+
workers:
|
|
43
|
+
- queues: [critical, default, low]
|
|
44
|
+
threads: 5
|
|
45
|
+
processes: 2
|
|
46
|
+
polling_interval: 0.1
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Creating Jobs
|
|
50
|
+
|
|
51
|
+
### Basic Job
|
|
52
|
+
```ruby
|
|
53
|
+
# app/jobs/send_welcome_email_job.rb
|
|
54
|
+
class SendWelcomeEmailJob < ApplicationJob
|
|
55
|
+
queue_as :default
|
|
56
|
+
|
|
57
|
+
def perform(user_id)
|
|
58
|
+
user = User.find(user_id)
|
|
59
|
+
UserMailer.welcome(user).deliver_now
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Job with Options
|
|
65
|
+
```ruby
|
|
66
|
+
# app/jobs/process_payment_job.rb
|
|
67
|
+
class ProcessPaymentJob < ApplicationJob
|
|
68
|
+
queue_as :critical
|
|
69
|
+
|
|
70
|
+
retry_on ActiveRecord::Deadlocked, wait: 5.seconds, attempts: 3
|
|
71
|
+
discard_on ActiveJob::DeserializationError
|
|
72
|
+
|
|
73
|
+
def perform(order)
|
|
74
|
+
PaymentService.process(order)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Job with Callbacks
|
|
80
|
+
```ruby
|
|
81
|
+
# app/jobs/import_data_job.rb
|
|
82
|
+
class ImportDataJob < ApplicationJob
|
|
83
|
+
queue_as :low
|
|
84
|
+
|
|
85
|
+
before_enqueue do |job|
|
|
86
|
+
Rails.logger.info "Enqueueing import for #{job.arguments.first}"
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
around_perform do |job, block|
|
|
90
|
+
start_time = Time.current
|
|
91
|
+
block.call
|
|
92
|
+
duration = Time.current - start_time
|
|
93
|
+
Rails.logger.info "Import completed in #{duration.round(2)}s"
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def perform(file_path, user_id)
|
|
97
|
+
user = User.find(user_id)
|
|
98
|
+
ImportService.new(file_path, user).call
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Enqueueing Jobs
|
|
104
|
+
|
|
105
|
+
### Immediate Execution
|
|
106
|
+
```ruby
|
|
107
|
+
# Enqueue to run as soon as possible
|
|
108
|
+
SendWelcomeEmailJob.perform_later(user.id)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Delayed Execution
|
|
112
|
+
```ruby
|
|
113
|
+
# Run in 1 hour
|
|
114
|
+
SendReminderJob.set(wait: 1.hour).perform_later(user.id)
|
|
115
|
+
|
|
116
|
+
# Run at specific time
|
|
117
|
+
SendReportJob.set(wait_until: Date.tomorrow.noon).perform_later
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Queue Priority
|
|
121
|
+
```ruby
|
|
122
|
+
# Override queue at enqueue time
|
|
123
|
+
ProcessOrderJob.set(queue: :critical).perform_later(order)
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Common Job Patterns
|
|
127
|
+
|
|
128
|
+
### Mailer Job
|
|
129
|
+
```ruby
|
|
130
|
+
# Instead of creating a job, use deliver_later
|
|
131
|
+
UserMailer.welcome(user).deliver_later
|
|
132
|
+
UserMailer.notification(user).deliver_later(wait: 5.minutes)
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Batch Processing
|
|
136
|
+
```ruby
|
|
137
|
+
# app/jobs/batch_process_job.rb
|
|
138
|
+
class BatchProcessJob < ApplicationJob
|
|
139
|
+
queue_as :low
|
|
140
|
+
|
|
141
|
+
def perform(record_ids)
|
|
142
|
+
Record.where(id: record_ids).find_each do |record|
|
|
143
|
+
process_record(record)
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
private
|
|
148
|
+
|
|
149
|
+
def process_record(record)
|
|
150
|
+
# Processing logic
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# Enqueue in batches
|
|
155
|
+
Record.pending.pluck(:id).each_slice(100) do |batch_ids|
|
|
156
|
+
BatchProcessJob.perform_later(batch_ids)
|
|
157
|
+
end
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Webhook Processing
|
|
161
|
+
```ruby
|
|
162
|
+
# app/jobs/process_webhook_job.rb
|
|
163
|
+
class ProcessWebhookJob < ApplicationJob
|
|
164
|
+
queue_as :critical
|
|
165
|
+
|
|
166
|
+
retry_on Net::OpenTimeout, wait: :polynomially_longer, attempts: 5
|
|
167
|
+
|
|
168
|
+
def perform(webhook_data)
|
|
169
|
+
case webhook_data["event"]
|
|
170
|
+
when "payment.completed"
|
|
171
|
+
handle_payment_completed(webhook_data)
|
|
172
|
+
when "subscription.cancelled"
|
|
173
|
+
handle_subscription_cancelled(webhook_data)
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
private
|
|
178
|
+
|
|
179
|
+
def handle_payment_completed(data)
|
|
180
|
+
# Process payment
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def handle_subscription_cancelled(data)
|
|
184
|
+
# Handle cancellation
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Progress Tracking
|
|
190
|
+
```ruby
|
|
191
|
+
# app/jobs/export_job.rb
|
|
192
|
+
class ExportJob < ApplicationJob
|
|
193
|
+
queue_as :default
|
|
194
|
+
|
|
195
|
+
def perform(export_id)
|
|
196
|
+
export = Export.find(export_id)
|
|
197
|
+
export.update!(status: "processing")
|
|
198
|
+
|
|
199
|
+
records = export.user.records
|
|
200
|
+
total = records.count
|
|
201
|
+
|
|
202
|
+
records.find_each.with_index do |record, index|
|
|
203
|
+
process_record(record, export)
|
|
204
|
+
|
|
205
|
+
# Update progress every 100 records
|
|
206
|
+
if (index + 1) % 100 == 0
|
|
207
|
+
progress = ((index + 1).to_f / total * 100).round
|
|
208
|
+
export.update!(progress: progress)
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
export.update!(status: "completed", progress: 100)
|
|
213
|
+
rescue StandardError => e
|
|
214
|
+
export.update!(status: "failed", error_message: e.message)
|
|
215
|
+
raise
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## Recurring Jobs
|
|
221
|
+
|
|
222
|
+
### Using Solid Queue Recurring
|
|
223
|
+
```yaml
|
|
224
|
+
# config/recurring.yml
|
|
225
|
+
production:
|
|
226
|
+
cleanup_old_sessions:
|
|
227
|
+
class: CleanupSessionsJob
|
|
228
|
+
schedule: every day at 3am
|
|
229
|
+
|
|
230
|
+
send_daily_digest:
|
|
231
|
+
class: DailyDigestJob
|
|
232
|
+
schedule: every day at 8am
|
|
233
|
+
|
|
234
|
+
sync_inventory:
|
|
235
|
+
class: SyncInventoryJob
|
|
236
|
+
schedule: every 15 minutes
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### Manual Scheduling
|
|
240
|
+
```ruby
|
|
241
|
+
# app/jobs/schedule_daily_tasks_job.rb
|
|
242
|
+
class ScheduleDailyTasksJob < ApplicationJob
|
|
243
|
+
def perform
|
|
244
|
+
# Schedule tomorrow's run
|
|
245
|
+
ScheduleDailyTasksJob.set(wait_until: Date.tomorrow.midnight).perform_later
|
|
246
|
+
|
|
247
|
+
# Run daily tasks
|
|
248
|
+
CleanupJob.perform_later
|
|
249
|
+
ReportJob.perform_later
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
## Error Handling
|
|
255
|
+
|
|
256
|
+
### Retry Configuration
|
|
257
|
+
```ruby
|
|
258
|
+
class UnreliableApiJob < ApplicationJob
|
|
259
|
+
# Retry with exponential backoff
|
|
260
|
+
retry_on ApiError, wait: :polynomially_longer, attempts: 5
|
|
261
|
+
|
|
262
|
+
# Retry specific errors
|
|
263
|
+
retry_on Timeout::Error, wait: 10.seconds, attempts: 3
|
|
264
|
+
|
|
265
|
+
# Don't retry certain errors
|
|
266
|
+
discard_on InvalidDataError
|
|
267
|
+
|
|
268
|
+
def perform(data)
|
|
269
|
+
ExternalApi.call(data)
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Custom Error Handling
|
|
275
|
+
```ruby
|
|
276
|
+
class ImportJob < ApplicationJob
|
|
277
|
+
def perform(file_path)
|
|
278
|
+
ImportService.new(file_path).call
|
|
279
|
+
rescue ImportService::ValidationError => e
|
|
280
|
+
# Log and notify, but don't retry
|
|
281
|
+
Rails.logger.error "Import validation failed: #{e.message}"
|
|
282
|
+
AdminNotifier.import_failed(e).deliver_later
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
## Testing Jobs
|
|
288
|
+
|
|
289
|
+
```ruby
|
|
290
|
+
# spec/jobs/send_welcome_email_job_spec.rb
|
|
291
|
+
require "rails_helper"
|
|
292
|
+
|
|
293
|
+
RSpec.describe SendWelcomeEmailJob, type: :job do
|
|
294
|
+
let(:user) { create(:user) }
|
|
295
|
+
|
|
296
|
+
describe "#perform" do
|
|
297
|
+
it "sends welcome email" do
|
|
298
|
+
expect {
|
|
299
|
+
described_class.perform_now(user.id)
|
|
300
|
+
}.to change { ActionMailer::Base.deliveries.count }.by(1)
|
|
301
|
+
end
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
describe "enqueueing" do
|
|
305
|
+
it "enqueues job" do
|
|
306
|
+
expect {
|
|
307
|
+
described_class.perform_later(user.id)
|
|
308
|
+
}.to have_enqueued_job(described_class).with(user.id)
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
it "enqueues on correct queue" do
|
|
312
|
+
expect {
|
|
313
|
+
described_class.perform_later(user.id)
|
|
314
|
+
}.to have_enqueued_job.on_queue(:default)
|
|
315
|
+
end
|
|
316
|
+
end
|
|
317
|
+
end
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
## Running Workers
|
|
321
|
+
|
|
322
|
+
```bash
|
|
323
|
+
# Development (auto-started with rails server)
|
|
324
|
+
rails server
|
|
325
|
+
|
|
326
|
+
# Production
|
|
327
|
+
bundle exec rake solid_queue:start
|
|
328
|
+
|
|
329
|
+
# With Procfile
|
|
330
|
+
# Procfile
|
|
331
|
+
web: bundle exec puma -C config/puma.rb
|
|
332
|
+
worker: bundle exec rake solid_queue:start
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
## Best Practices
|
|
336
|
+
|
|
337
|
+
1. **Pass IDs, not objects** - Serialize primitive values
|
|
338
|
+
2. **Keep jobs idempotent** - Safe to run multiple times
|
|
339
|
+
3. **Use appropriate queues** - Separate by priority
|
|
340
|
+
4. **Handle failures gracefully** - Log and notify
|
|
341
|
+
5. **Monitor job performance** - Track duration and failures
|