cc-codeconductor 0.2.10 → 0.3.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/README.md +5 -4
- package/dist/index.js +1636 -1078
- package/package.json +1 -1
- package/presets/agy/AGENTS.md +46 -2
- package/presets/claude/CLAUDE.md +62 -2
- package/presets/claude/skills/android/SKILL.md +119 -0
- package/presets/claude/skills/laravel-specialist/SKILL.md +264 -0
- package/presets/claude/skills/laravel-specialist/references/eloquent.md +351 -0
- package/presets/claude/skills/laravel-specialist/references/livewire.md +512 -0
- package/presets/claude/skills/laravel-specialist/references/queues.md +423 -0
- package/presets/claude/skills/laravel-specialist/references/routing.md +362 -0
- package/presets/claude/skills/laravel-specialist/references/testing.md +522 -0
- package/presets/claude/skills/php-pro/SKILL.md +208 -0
- package/presets/claude/skills/php-pro/references/async-patterns.md +412 -0
- package/presets/claude/skills/php-pro/references/laravel-patterns.md +377 -0
- package/presets/claude/skills/php-pro/references/modern-php-features.md +323 -0
- package/presets/claude/skills/php-pro/references/symfony-patterns.md +466 -0
- package/presets/claude/skills/php-pro/references/testing-quality.md +466 -0
- package/presets/codex/AGENTS.md +47 -2
- package/presets/codex/skills/android/SKILL.md +119 -0
- package/presets/codex/skills/laravel-specialist/SKILL.md +264 -0
- package/presets/codex/skills/laravel-specialist/references/eloquent.md +351 -0
- package/presets/codex/skills/laravel-specialist/references/livewire.md +512 -0
- package/presets/codex/skills/laravel-specialist/references/queues.md +423 -0
- package/presets/codex/skills/laravel-specialist/references/routing.md +362 -0
- package/presets/codex/skills/laravel-specialist/references/testing.md +522 -0
- package/presets/codex/skills/php-pro/SKILL.md +208 -0
- package/presets/codex/skills/php-pro/references/async-patterns.md +412 -0
- package/presets/codex/skills/php-pro/references/laravel-patterns.md +377 -0
- package/presets/codex/skills/php-pro/references/modern-php-features.md +323 -0
- package/presets/codex/skills/php-pro/references/symfony-patterns.md +466 -0
- package/presets/codex/skills/php-pro/references/testing-quality.md +466 -0
- package/presets/opencode/agents/implementer.md +2 -2
- package/presets/opencode/agents/orchestrator.md +132 -5
- package/presets/opencode/agents/reviewer.md +33 -0
- package/presets/opencode/prompts/v0.3.0/architect.md +221 -0
- package/presets/opencode/prompts/v0.3.0/docs.md +189 -0
- package/presets/opencode/prompts/v0.3.0/implementer.md +162 -0
- package/presets/opencode/prompts/v0.3.0/orchestrator.md +360 -0
- package/presets/opencode/prompts/v0.3.0/repo-explorer.md +110 -0
- package/presets/opencode/prompts/v0.3.0/reviewer.md +225 -0
- package/presets/opencode/prompts/v0.3.0/task-coach.md +155 -0
- package/presets/opencode/prompts/v0.3.0/tester.md +251 -0
- package/presets/opencode/skills/android/SKILL.md +119 -0
- package/presets/opencode/skills/laravel-specialist/SKILL.md +264 -0
- package/presets/opencode/skills/laravel-specialist/references/eloquent.md +351 -0
- package/presets/opencode/skills/laravel-specialist/references/livewire.md +512 -0
- package/presets/opencode/skills/laravel-specialist/references/queues.md +423 -0
- package/presets/opencode/skills/laravel-specialist/references/routing.md +362 -0
- package/presets/opencode/skills/laravel-specialist/references/testing.md +522 -0
- package/presets/opencode/skills/php-pro/SKILL.md +208 -0
- package/presets/opencode/skills/php-pro/references/async-patterns.md +412 -0
- package/presets/opencode/skills/php-pro/references/laravel-patterns.md +377 -0
- package/presets/opencode/skills/php-pro/references/modern-php-features.md +323 -0
- package/presets/opencode/skills/php-pro/references/symfony-patterns.md +466 -0
- package/presets/opencode/skills/php-pro/references/testing-quality.md +466 -0
- package/src/presets/manifests/agy.yml +3 -2
- package/src/presets/manifests/claude.yml +3 -2
- package/src/presets/manifests/codex.yml +3 -2
- package/src/presets/manifests/cursor.yml +3 -2
- package/src/presets/manifests/gemini.yml +3 -2
- package/src/presets/manifests/opencode.yml +3 -2
- package/src/presets/models/opencode.yml +6 -6
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
# Queue System
|
|
2
|
+
|
|
3
|
+
## Job Patterns
|
|
4
|
+
|
|
5
|
+
```php
|
|
6
|
+
namespace App\Jobs;
|
|
7
|
+
|
|
8
|
+
use App\Models\Post;
|
|
9
|
+
use App\Models\User;
|
|
10
|
+
use Illuminate\Bus\Queueable;
|
|
11
|
+
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
12
|
+
use Illuminate\Foundation\Bus\Dispatchable;
|
|
13
|
+
use Illuminate\Queue\InteractsWithQueue;
|
|
14
|
+
use Illuminate\Queue\SerializesModels;
|
|
15
|
+
|
|
16
|
+
class ProcessPost implements ShouldQueue
|
|
17
|
+
{
|
|
18
|
+
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
|
19
|
+
|
|
20
|
+
public $tries = 3;
|
|
21
|
+
public $timeout = 120;
|
|
22
|
+
public $maxExceptions = 3;
|
|
23
|
+
public $backoff = [60, 120, 300]; // Exponential backoff
|
|
24
|
+
|
|
25
|
+
public function __construct(
|
|
26
|
+
public Post $post,
|
|
27
|
+
public ?User $user = null,
|
|
28
|
+
) {}
|
|
29
|
+
|
|
30
|
+
public function handle(): void
|
|
31
|
+
{
|
|
32
|
+
// Process the post
|
|
33
|
+
$this->post->update(['processed' => true]);
|
|
34
|
+
|
|
35
|
+
// Can access injected dependencies
|
|
36
|
+
$analytics = app(AnalyticsService::class);
|
|
37
|
+
$analytics->trackPostProcessed($this->post);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public function failed(\Throwable $exception): void
|
|
41
|
+
{
|
|
42
|
+
// Handle job failure
|
|
43
|
+
\Log::error('Post processing failed', [
|
|
44
|
+
'post_id' => $this->post->id,
|
|
45
|
+
'error' => $exception->getMessage(),
|
|
46
|
+
]);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Dispatching Jobs
|
|
52
|
+
|
|
53
|
+
```php
|
|
54
|
+
use App\Jobs\ProcessPost;
|
|
55
|
+
|
|
56
|
+
// Dispatch immediately
|
|
57
|
+
ProcessPost::dispatch($post);
|
|
58
|
+
|
|
59
|
+
// Dispatch to specific queue
|
|
60
|
+
ProcessPost::dispatch($post)->onQueue('processing');
|
|
61
|
+
|
|
62
|
+
// Delayed dispatch
|
|
63
|
+
ProcessPost::dispatch($post)->delay(now()->addMinutes(10));
|
|
64
|
+
|
|
65
|
+
// Dispatch after database commit
|
|
66
|
+
ProcessPost::dispatch($post)->afterCommit();
|
|
67
|
+
|
|
68
|
+
// Dispatch conditionally
|
|
69
|
+
ProcessPost::dispatchIf($condition, $post);
|
|
70
|
+
ProcessPost::dispatchUnless($condition, $post);
|
|
71
|
+
|
|
72
|
+
// Synchronous dispatch (no queue)
|
|
73
|
+
ProcessPost::dispatchSync($post);
|
|
74
|
+
|
|
75
|
+
// Dispatch after response
|
|
76
|
+
ProcessPost::dispatchAfterResponse($post);
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Job Chaining
|
|
80
|
+
|
|
81
|
+
```php
|
|
82
|
+
use App\Jobs\{OptimizeImage, GenerateThumbnail, PublishPost};
|
|
83
|
+
|
|
84
|
+
// Chain jobs
|
|
85
|
+
OptimizeImage::withChain([
|
|
86
|
+
new GenerateThumbnail($post),
|
|
87
|
+
new PublishPost($post),
|
|
88
|
+
])->dispatch($post);
|
|
89
|
+
|
|
90
|
+
// Catch failures in chain
|
|
91
|
+
Bus::chain([
|
|
92
|
+
new ProcessPost($post),
|
|
93
|
+
new NotifyUser($user),
|
|
94
|
+
])->catch(function (\Throwable $e) {
|
|
95
|
+
// Handle failure
|
|
96
|
+
})->dispatch();
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Job Batching
|
|
100
|
+
|
|
101
|
+
```php
|
|
102
|
+
use Illuminate\Bus\Batch;
|
|
103
|
+
use Illuminate\Support\Facades\Bus;
|
|
104
|
+
|
|
105
|
+
$batch = Bus::batch([
|
|
106
|
+
new ProcessPost($post1),
|
|
107
|
+
new ProcessPost($post2),
|
|
108
|
+
new ProcessPost($post3),
|
|
109
|
+
])->then(function (Batch $batch) {
|
|
110
|
+
// All jobs completed successfully
|
|
111
|
+
})->catch(function (Batch $batch, \Throwable $e) {
|
|
112
|
+
// First batch job failure detected
|
|
113
|
+
})->finally(function (Batch $batch) {
|
|
114
|
+
// The batch has finished executing
|
|
115
|
+
})->name('Process Posts')
|
|
116
|
+
->allowFailures()
|
|
117
|
+
->dispatch();
|
|
118
|
+
|
|
119
|
+
// Check batch status
|
|
120
|
+
$batch = Bus::findBatch($batchId);
|
|
121
|
+
if ($batch->finished()) {
|
|
122
|
+
// Batch is complete
|
|
123
|
+
}
|
|
124
|
+
if ($batch->cancelled()) {
|
|
125
|
+
// Batch was cancelled
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Add jobs to existing batch
|
|
129
|
+
$batch->add([
|
|
130
|
+
new ProcessPost($post4),
|
|
131
|
+
]);
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Rate Limiting
|
|
135
|
+
|
|
136
|
+
```php
|
|
137
|
+
use Illuminate\Support\Facades\Redis;
|
|
138
|
+
|
|
139
|
+
class ProcessPost implements ShouldQueue
|
|
140
|
+
{
|
|
141
|
+
public function handle(): void
|
|
142
|
+
{
|
|
143
|
+
Redis::throttle('process-posts')
|
|
144
|
+
->block(0)
|
|
145
|
+
->allow(10)
|
|
146
|
+
->every(60)
|
|
147
|
+
->then(function () {
|
|
148
|
+
// Lock acquired, process job
|
|
149
|
+
}, function () {
|
|
150
|
+
// Could not acquire lock, release job back
|
|
151
|
+
$this->release(10);
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Or using middleware
|
|
157
|
+
use Illuminate\Queue\Middleware\RateLimited;
|
|
158
|
+
|
|
159
|
+
public function middleware(): array
|
|
160
|
+
{
|
|
161
|
+
return [new RateLimited('process-posts')];
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Job Middleware
|
|
166
|
+
|
|
167
|
+
```php
|
|
168
|
+
namespace App\Jobs\Middleware;
|
|
169
|
+
|
|
170
|
+
class RateLimitedByUser
|
|
171
|
+
{
|
|
172
|
+
public function handle($job, $next): void
|
|
173
|
+
{
|
|
174
|
+
Redis::throttle("user:{$job->user->id}")
|
|
175
|
+
->allow(10)
|
|
176
|
+
->every(60)
|
|
177
|
+
->then(function () use ($job, $next) {
|
|
178
|
+
$next($job);
|
|
179
|
+
}, function () use ($job) {
|
|
180
|
+
$job->release(10);
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Use in job
|
|
186
|
+
use App\Jobs\Middleware\RateLimitedByUser;
|
|
187
|
+
|
|
188
|
+
public function middleware(): array
|
|
189
|
+
{
|
|
190
|
+
return [new RateLimitedByUser];
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Skip middleware
|
|
194
|
+
use Illuminate\Queue\Middleware\WithoutOverlapping;
|
|
195
|
+
|
|
196
|
+
public function middleware(): array
|
|
197
|
+
{
|
|
198
|
+
return [
|
|
199
|
+
(new WithoutOverlapping($this->user->id))->expireAfter(180),
|
|
200
|
+
];
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Unique Jobs
|
|
205
|
+
|
|
206
|
+
```php
|
|
207
|
+
use Illuminate\Contracts\Queue\ShouldBeUnique;
|
|
208
|
+
|
|
209
|
+
class ProcessPost implements ShouldQueue, ShouldBeUnique
|
|
210
|
+
{
|
|
211
|
+
public int $uniqueFor = 3600;
|
|
212
|
+
|
|
213
|
+
public function __construct(
|
|
214
|
+
public Post $post,
|
|
215
|
+
) {}
|
|
216
|
+
|
|
217
|
+
public function uniqueId(): string
|
|
218
|
+
{
|
|
219
|
+
return $this->post->id;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Or use unique until processing
|
|
224
|
+
use Illuminate\Contracts\Queue\ShouldBeUniqueUntilProcessing;
|
|
225
|
+
|
|
226
|
+
class ProcessPost implements ShouldQueue, ShouldBeUniqueUntilProcessing
|
|
227
|
+
{
|
|
228
|
+
// ...
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## Failed Jobs
|
|
233
|
+
|
|
234
|
+
```php
|
|
235
|
+
// Retry failed job
|
|
236
|
+
php artisan queue:retry <job-id>
|
|
237
|
+
|
|
238
|
+
// Retry all failed jobs
|
|
239
|
+
php artisan queue:retry all
|
|
240
|
+
|
|
241
|
+
// Flush failed jobs
|
|
242
|
+
php artisan queue:flush
|
|
243
|
+
|
|
244
|
+
// Prune failed jobs
|
|
245
|
+
php artisan queue:prune-failed --hours=48
|
|
246
|
+
|
|
247
|
+
// Handle in code
|
|
248
|
+
use Illuminate\Support\Facades\Queue;
|
|
249
|
+
|
|
250
|
+
Queue::failing(function (JobFailed $event) {
|
|
251
|
+
\Log::error('Job failed', [
|
|
252
|
+
'connection' => $event->connectionName,
|
|
253
|
+
'queue' => $event->job->getQueue(),
|
|
254
|
+
'exception' => $event->exception->getMessage(),
|
|
255
|
+
]);
|
|
256
|
+
});
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
## Queue Workers
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
# Start worker
|
|
263
|
+
php artisan queue:work
|
|
264
|
+
|
|
265
|
+
# Process specific queue
|
|
266
|
+
php artisan queue:work --queue=high,default
|
|
267
|
+
|
|
268
|
+
# Process one job
|
|
269
|
+
php artisan queue:work --once
|
|
270
|
+
|
|
271
|
+
# Stop worker gracefully
|
|
272
|
+
php artisan queue:restart
|
|
273
|
+
|
|
274
|
+
# Timeout settings
|
|
275
|
+
php artisan queue:work --timeout=60
|
|
276
|
+
|
|
277
|
+
# Memory limit
|
|
278
|
+
php artisan queue:work --memory=512
|
|
279
|
+
|
|
280
|
+
# Max jobs before restart
|
|
281
|
+
php artisan queue:work --max-jobs=1000
|
|
282
|
+
|
|
283
|
+
# Max time before restart
|
|
284
|
+
php artisan queue:work --max-time=3600
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
## Horizon Setup
|
|
288
|
+
|
|
289
|
+
```php
|
|
290
|
+
// config/horizon.php
|
|
291
|
+
return [
|
|
292
|
+
'environments' => [
|
|
293
|
+
'production' => [
|
|
294
|
+
'supervisor-1' => [
|
|
295
|
+
'connection' => 'redis',
|
|
296
|
+
'queue' => ['default'],
|
|
297
|
+
'balance' => 'auto',
|
|
298
|
+
'maxProcesses' => 10,
|
|
299
|
+
'maxTime' => 0,
|
|
300
|
+
'maxJobs' => 0,
|
|
301
|
+
'memory' => 512,
|
|
302
|
+
'tries' => 3,
|
|
303
|
+
'timeout' => 60,
|
|
304
|
+
'nice' => 0,
|
|
305
|
+
],
|
|
306
|
+
'supervisor-2' => [
|
|
307
|
+
'connection' => 'redis',
|
|
308
|
+
'queue' => ['high', 'default'],
|
|
309
|
+
'balance' => 'auto',
|
|
310
|
+
'maxProcesses' => 5,
|
|
311
|
+
'tries' => 3,
|
|
312
|
+
],
|
|
313
|
+
],
|
|
314
|
+
],
|
|
315
|
+
];
|
|
316
|
+
|
|
317
|
+
// Start Horizon
|
|
318
|
+
php artisan horizon
|
|
319
|
+
|
|
320
|
+
// Terminate Horizon
|
|
321
|
+
php artisan horizon:terminate
|
|
322
|
+
|
|
323
|
+
// Pause workers
|
|
324
|
+
php artisan horizon:pause
|
|
325
|
+
|
|
326
|
+
// Continue workers
|
|
327
|
+
php artisan horizon:continue
|
|
328
|
+
|
|
329
|
+
// Check status
|
|
330
|
+
php artisan horizon:status
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
## Monitoring
|
|
334
|
+
|
|
335
|
+
```php
|
|
336
|
+
use Illuminate\Queue\Events\JobProcessed;
|
|
337
|
+
use Illuminate\Queue\Events\JobFailed;
|
|
338
|
+
use Illuminate\Support\Facades\Queue;
|
|
339
|
+
|
|
340
|
+
// In AppServiceProvider
|
|
341
|
+
public function boot(): void
|
|
342
|
+
{
|
|
343
|
+
Queue::before(function (JobProcessing $event) {
|
|
344
|
+
// Called before job is processed
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
Queue::after(function (JobProcessed $event) {
|
|
348
|
+
// Called after job is processed
|
|
349
|
+
\Log::info('Job processed', [
|
|
350
|
+
'job' => $event->job->resolveName(),
|
|
351
|
+
'time' => $event->job->processingTime(),
|
|
352
|
+
]);
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
Queue::failing(function (JobFailed $event) {
|
|
356
|
+
// Called when job fails
|
|
357
|
+
\Log::error('Job failed', [
|
|
358
|
+
'job' => $event->job->resolveName(),
|
|
359
|
+
'exception' => $event->exception,
|
|
360
|
+
]);
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
## Queue Configuration
|
|
366
|
+
|
|
367
|
+
```php
|
|
368
|
+
// config/queue.php
|
|
369
|
+
return [
|
|
370
|
+
'default' => env('QUEUE_CONNECTION', 'sync'),
|
|
371
|
+
|
|
372
|
+
'connections' => [
|
|
373
|
+
'sync' => [
|
|
374
|
+
'driver' => 'sync',
|
|
375
|
+
],
|
|
376
|
+
|
|
377
|
+
'database' => [
|
|
378
|
+
'driver' => 'database',
|
|
379
|
+
'table' => 'jobs',
|
|
380
|
+
'queue' => 'default',
|
|
381
|
+
'retry_after' => 90,
|
|
382
|
+
'after_commit' => false,
|
|
383
|
+
],
|
|
384
|
+
|
|
385
|
+
'redis' => [
|
|
386
|
+
'driver' => 'redis',
|
|
387
|
+
'connection' => 'default',
|
|
388
|
+
'queue' => env('REDIS_QUEUE', 'default'),
|
|
389
|
+
'retry_after' => 90,
|
|
390
|
+
'block_for' => null,
|
|
391
|
+
'after_commit' => false,
|
|
392
|
+
],
|
|
393
|
+
|
|
394
|
+
'sqs' => [
|
|
395
|
+
'driver' => 'sqs',
|
|
396
|
+
'key' => env('AWS_ACCESS_KEY_ID'),
|
|
397
|
+
'secret' => env('AWS_SECRET_ACCESS_KEY'),
|
|
398
|
+
'prefix' => env('SQS_PREFIX'),
|
|
399
|
+
'queue' => env('SQS_QUEUE'),
|
|
400
|
+
'region' => env('AWS_DEFAULT_REGION'),
|
|
401
|
+
],
|
|
402
|
+
],
|
|
403
|
+
|
|
404
|
+
'failed' => [
|
|
405
|
+
'driver' => env('QUEUE_FAILED_DRIVER', 'database-uuids'),
|
|
406
|
+
'database' => env('DB_CONNECTION', 'mysql'),
|
|
407
|
+
'table' => 'failed_jobs',
|
|
408
|
+
],
|
|
409
|
+
];
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
## Best Practices
|
|
413
|
+
|
|
414
|
+
1. **Keep jobs small and focused** - Single responsibility
|
|
415
|
+
2. **Make jobs idempotent** - Safe to run multiple times
|
|
416
|
+
3. **Use type hints** - Better error detection
|
|
417
|
+
4. **Set reasonable timeouts** - Prevent hanging jobs
|
|
418
|
+
5. **Monitor failed jobs** - Set up alerts
|
|
419
|
+
6. **Use batching for bulk operations** - Better performance
|
|
420
|
+
7. **Implement proper error handling** - Use failed() method
|
|
421
|
+
8. **Use unique jobs** - Prevent duplicate processing
|
|
422
|
+
9. **Queue long-running tasks** - Don't block requests
|
|
423
|
+
10. **Use Horizon for Redis queues** - Better monitoring
|