Files
KnowledgeBase/app/Console/Commands/FixStuckDocuments.php
lizhuoran 29c209116e feat: 增强文档转换失败处理机制
- 新增 FixStuckDocuments 命令用于修复卡住的文档
- 支持批量检测和修复超时的转换任务
- 改进重试按钮,支持 failed/processing/pending 状态
- 在确认对话框中显示当前状态和错误信息
- 提供 dry-run 模式预览修复操作
2026-03-12 15:58:24 +08:00

104 lines
3.3 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace App\Console\Commands;
use App\Models\Document;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
class FixStuckDocuments extends Command
{
/**
* 命令签名
*
* @var string
*/
protected $signature = 'documents:fix-stuck
{--timeout=30 : 超过多少分钟未完成视为卡住默认30分钟}
{--status=processing : 要修复的状态processing/pending}
{--dry-run : 仅显示将要修复的文档,不实际执行}';
/**
* 命令描述
*
* @var string
*/
protected $description = '修复卡在转换中但实际已失败的文档';
/**
* 执行命令
*/
public function handle(): int
{
$timeout = (int) $this->option('timeout');
$status = $this->option('status');
$dryRun = $this->option('dry-run');
$this->info("正在查找卡住的文档...");
$this->info("状态: {$status}");
$this->info("超时时间: {$timeout} 分钟");
// 查找卡住的文档
$stuckDocuments = Document::where('conversion_status', $status)
->where('updated_at', '<', now()->subMinutes($timeout))
->get();
if ($stuckDocuments->isEmpty()) {
$this->info('✓ 没有发现卡住的文档');
return self::SUCCESS;
}
$this->warn("发现 {$stuckDocuments->count()} 个卡住的文档:");
// 显示文档列表
$tableData = $stuckDocuments->map(function ($doc) {
return [
'ID' => $doc->id,
'标题' => \Illuminate\Support\Str::limit($doc->title, 40),
'状态' => $doc->conversion_status,
'更新时间' => $doc->updated_at->format('Y-m-d H:i:s'),
'卡住时长' => $doc->updated_at->diffForHumans(),
];
})->toArray();
$this->table(
['ID', '标题', '状态', '更新时间', '卡住时长'],
$tableData
);
if ($dryRun) {
$this->info('');
$this->info('这是预览模式,没有实际修改任何数据');
$this->info('移除 --dry-run 选项以执行修复');
return self::SUCCESS;
}
// 确认操作
if (!$this->confirm('是否要将这些文档标记为失败状态?', true)) {
$this->info('操作已取消');
return self::SUCCESS;
}
// 修复文档
$fixed = 0;
foreach ($stuckDocuments as $document) {
try {
$document->update([
'conversion_status' => 'failed',
'conversion_error' => "转换任务超时(卡在 {$status} 状态超过 {$timeout} 分钟)",
]);
$fixed++;
$this->line("✓ 已修复: [{$document->id}] {$document->title}");
} catch (\Exception $e) {
$this->error("✗ 修复失败: [{$document->id}] {$document->title} - {$e->getMessage()}");
}
}
$this->info('');
$this->info("修复完成!共修复 {$fixed} 个文档");
$this->info('现在可以在管理界面使用"重试转换"功能重新处理这些文档');
return self::SUCCESS;
}
}