Ship production optimization M1-M12.5A: queues, metrics, HTTP observability, and vector search reliability.
Keep similar-ai from tripping the global circuit on a lone URL 502, clamp Qdrant search to 100, and add Server-Timing plus slow-request logging. Studio shared props, Academy S3 exists caching, heat chunking, and Redis/scheduler hygiene stay in this rollout.
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Support\Redis\OrphanQueueCleanup;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use RuntimeException;
|
||||
|
||||
class RedisCleanupOrphansCommand extends Command
|
||||
{
|
||||
protected $signature = 'skinbase:redis-cleanup-orphans
|
||||
{target : forum-moderation, forum-security, or collections}
|
||||
{--dry-run : Inspect and report without UNLINK}
|
||||
{--execute : UNLINK the waiting queue and notify list}
|
||||
{--force : Allow unexpected sampled job classes}';
|
||||
|
||||
protected $description = 'UNLINK an orphan Redis queue after producer and class checks (operator only)';
|
||||
|
||||
public function handle(OrphanQueueCleanup $cleanup): int
|
||||
{
|
||||
$dryRun = (bool) $this->option('dry-run');
|
||||
$execute = (bool) $this->option('execute');
|
||||
if ($dryRun === $execute) {
|
||||
$this->error('Pass exactly one of --dry-run or --execute.');
|
||||
|
||||
return self::FAILURE;
|
||||
}
|
||||
|
||||
$target = (string) $this->argument('target');
|
||||
$force = (bool) $this->option('force');
|
||||
|
||||
$this->info(sprintf(
|
||||
'[redis-cleanup-orphans] prefix=%s connection=default target=%s force=%s mode=%s',
|
||||
(string) config('database.redis.options.prefix'),
|
||||
$target,
|
||||
$force ? 'yes' : 'no',
|
||||
$dryRun ? 'dry-run' : 'execute'
|
||||
));
|
||||
|
||||
try {
|
||||
$plan = $execute
|
||||
? $cleanup->execute($target, $force)
|
||||
: $cleanup->plan($target, $force);
|
||||
} catch (RuntimeException $e) {
|
||||
$this->error($e->getMessage());
|
||||
Log::warning('[redis-cleanup-orphans] refused', ['target' => $target, 'error' => $e->getMessage()]);
|
||||
|
||||
return self::FAILURE;
|
||||
}
|
||||
|
||||
$this->line('logical_key='.$plan['logical_key']);
|
||||
$this->line('notify_key='.$plan['notify_key']);
|
||||
$this->line('llen='.$plan['llen'].' reserved='.$plan['reserved'].' delayed='.$plan['delayed']);
|
||||
$this->line('sampled='.$plan['sampled'].' est_bytes='.$plan['est_bytes']);
|
||||
$this->line('classes='.json_encode($plan['classes']));
|
||||
if ($plan['unexpected_classes'] !== []) {
|
||||
$this->warn('unexpected_classes='.json_encode($plan['unexpected_classes']));
|
||||
}
|
||||
if ($plan['errors'] !== []) {
|
||||
$this->error('errors='.implode(',', $plan['errors']));
|
||||
}
|
||||
if ($execute) {
|
||||
$this->info('unlinked='.($plan['unlinked'] ?? 0));
|
||||
}
|
||||
|
||||
Log::info('[redis-cleanup-orphans] completed', [
|
||||
'target' => $target,
|
||||
'dry_run' => $dryRun,
|
||||
'llen' => $plan['llen'],
|
||||
'errors' => $plan['errors'],
|
||||
'unlinked' => $plan['unlinked'] ?? 0,
|
||||
]);
|
||||
|
||||
return ($plan['errors'] === [] || $dryRun) ? self::SUCCESS : self::FAILURE;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user