feat: 增强文档转换失败处理机制
- 新增 FixStuckDocuments 命令用于修复卡住的文档 - 支持批量检测和修复超时的转换任务 - 改进重试按钮,支持 failed/processing/pending 状态 - 在确认对话框中显示当前状态和错误信息 - 提供 dry-run 模式预览修复操作
This commit is contained in:
103
app/Console/Commands/FixStuckDocuments.php
Normal file
103
app/Console/Commands/FixStuckDocuments.php
Normal file
@@ -0,0 +1,103 @@
|
||||
<?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;
|
||||
}
|
||||
}
|
||||
@@ -226,12 +226,20 @@ class DocumentResource extends Resource
|
||||
->label('重试转换')
|
||||
->icon('heroicon-o-arrow-path')
|
||||
->color('warning')
|
||||
->visible(fn (Document $record): bool => $record->conversion_status === 'failed')
|
||||
->visible(fn (Document $record): bool =>
|
||||
in_array($record->conversion_status, ['failed', 'processing', 'pending'])
|
||||
)
|
||||
->requiresConfirmation()
|
||||
->modalHeading('重试文档转换')
|
||||
->modalDescription(fn (Document $record): string =>
|
||||
'确定要重新转换文档 "' . $record->title . '" 吗?' .
|
||||
($record->conversion_error ? "\n\n上次失败原因:" . $record->conversion_error : '')
|
||||
"\n\n当前状态:" . match($record->conversion_status) {
|
||||
'failed' => '转换失败',
|
||||
'processing' => '转换中(可能卡住)',
|
||||
'pending' => '等待转换',
|
||||
default => $record->conversion_status,
|
||||
} .
|
||||
($record->conversion_error ? "\n\n错误信息:" . $record->conversion_error : '')
|
||||
)
|
||||
->modalSubmitActionLabel('确认重试')
|
||||
->action(function (Document $record) {
|
||||
|
||||
Reference in New Issue
Block a user