| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- <?php
- namespace App\Jobs;
- use App\Models\MarkdownImport;
- use App\Models\PreQuestionCandidate;
- use App\Services\MarkdownQuestionParser;
- use Illuminate\Bus\Queueable;
- use Illuminate\Contracts\Queue\ShouldQueue;
- use Illuminate\Foundation\Bus\Dispatchable;
- use Illuminate\Queue\InteractsWithQueue;
- use Illuminate\Queue\SerializesModels;
- use Illuminate\Support\Facades\DB;
- use Illuminate\Support\Facades\Log;
- class ProcessMarkdownCandidateBatch implements ShouldQueue
- {
- use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
- public int $timeout = 300; // 5分钟超时
- public int $tries = 3;
- public function __construct(
- public int $markdownImportId,
- public int $sequenceStart,
- public int $sequenceEnd
- ) {
- //
- }
- public function handle(MarkdownQuestionParser $parser): void
- {
- $import = MarkdownImport::find($this->markdownImportId);
- if (!$import) {
- Log::error('MarkdownImport not found for batch', [
- 'id' => $this->markdownImportId,
- 'sequence_start' => $this->sequenceStart,
- 'sequence_end' => $this->sequenceEnd,
- ]);
- return;
- }
- Log::info('Markdown batch started', [
- 'import_id' => $this->markdownImportId,
- 'sequence_start' => $this->sequenceStart,
- 'sequence_end' => $this->sequenceEnd,
- ]);
- $records = PreQuestionCandidate::query()
- ->where('import_id', $this->markdownImportId)
- ->whereBetween('sequence', [$this->sequenceStart, $this->sequenceEnd])
- ->orderBy('sequence')
- ->get();
- $processed = 0;
- $failed = 0;
- foreach ($records as $record) {
- try {
- // 已经处理过的不重复处理
- if (in_array($record->status, ['pending', 'reviewed', 'accepted', 'rejected'], true) && $record->stem !== null) {
- continue;
- }
- $parsed = $parser->parseRawMarkdown((string) $record->raw_markdown, (int) $record->index);
- $record->update([
- 'stem' => $parsed['stem'] ?? null,
- 'options' => $parsed['options'] ?? null,
- 'images' => $parsed['images'] ?? [],
- 'tables' => $parsed['tables'] ?? [],
- 'is_question_candidate' => (bool) ($parsed['is_question_candidate'] ?? false),
- 'ai_confidence' => $parsed['ai_confidence'] ?? null,
- 'status' => 'pending',
- ]);
- $processed++;
- } catch (\Throwable $e) {
- $failed++;
- Log::warning('Markdown batch item failed', [
- 'import_id' => $this->markdownImportId,
- 'candidate_id' => $record->id,
- 'sequence' => $record->sequence,
- 'index' => $record->index,
- 'error' => $e->getMessage(),
- ]);
- }
- }
- if ($processed > 0) {
- DB::table('markdown_imports')
- ->where('id', $this->markdownImportId)
- ->update([
- 'progress_current' => DB::raw('progress_current + ' . (int) $processed),
- 'progress_updated_at' => now(),
- 'progress_stage' => MarkdownImport::STAGE_AI_PARSING,
- 'progress_message' => 'AI 解析中…',
- ]);
- }
- Log::info('Markdown batch finished', [
- 'import_id' => $this->markdownImportId,
- 'sequence_start' => $this->sequenceStart,
- 'sequence_end' => $this->sequenceEnd,
- 'processed' => $processed,
- 'failed' => $failed,
- ]);
- $this->finalizeIfDone();
- }
- private function finalizeIfDone(): void
- {
- $import = MarkdownImport::find($this->markdownImportId);
- if (!$import) {
- return;
- }
- $total = (int) ($import->progress_total ?? 0);
- $current = (int) ($import->progress_current ?? 0);
- if ($total <= 0 || $current < $total) {
- return;
- }
- // 只要有一个 batch 到达“完成条件”,就尝试做一次幂等的最终状态更新
- $updated = DB::table('markdown_imports')
- ->where('id', $this->markdownImportId)
- ->where('status', 'processing')
- ->update([
- 'status' => 'parsed',
- 'progress_stage' => MarkdownImport::STAGE_PARSED,
- 'progress_message' => '解析完成,等待人工校对',
- 'progress_updated_at' => now(),
- 'processing_finished_at' => now(),
- ]);
- if ($updated) {
- Log::info('Markdown import finalized', [
- 'import_id' => $this->markdownImportId,
- 'progress_total' => $total,
- 'progress_current' => $current,
- ]);
- }
- }
- }
|