ProcessQuestionDifficultyCalibrationJob.php 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. <?php
  2. namespace App\Jobs;
  3. use App\Services\Analytics\QuestionDifficultyCalibrationService;
  4. use Illuminate\Bus\Queueable;
  5. use Illuminate\Contracts\Queue\ShouldQueue;
  6. use Illuminate\Foundation\Bus\Dispatchable;
  7. use Illuminate\Queue\InteractsWithQueue;
  8. use Illuminate\Queue\SerializesModels;
  9. use Illuminate\Support\Facades\Log;
  10. use Throwable;
  11. class ProcessQuestionDifficultyCalibrationJob implements ShouldQueue
  12. {
  13. use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
  14. public int $tries = 1;
  15. public int $timeout = 300;
  16. /**
  17. * @param list<array<string,mixed>> $questions
  18. */
  19. public function __construct(
  20. public string $paperId,
  21. public string $studentId,
  22. public array $questions
  23. ) {
  24. $this->questions = $this->compactQuestions($questions);
  25. // 放在 pdf 队列,且由调用方在 PDF Job 之后入队,保证报告优先生成。
  26. $this->onQueue('pdf');
  27. $this->afterCommit();
  28. }
  29. public function handle(QuestionDifficultyCalibrationService $calibrationService): void
  30. {
  31. Log::warning('QuestionDifficultyCalibrationJob: 开始异步在线难度校准', [
  32. 'paper_id' => $this->paperId,
  33. 'student_id' => $this->studentId,
  34. 'question_count' => count($this->questions),
  35. 'attempt' => $this->attempts(),
  36. 'memory_mb' => round(memory_get_usage(true) / 1024 / 1024, 2),
  37. ]);
  38. $updatedQuestions = $calibrationService->updateOnlineFromPaper($this->paperId, $this->questions);
  39. Log::warning('QuestionDifficultyCalibrationJob: 异步在线难度校准完成', [
  40. 'paper_id' => $this->paperId,
  41. 'student_id' => $this->studentId,
  42. 'updated_questions' => $updatedQuestions,
  43. 'memory_peak_mb' => round(memory_get_peak_usage(true) / 1024 / 1024, 2),
  44. ]);
  45. }
  46. public function failed(Throwable $exception): void
  47. {
  48. Log::error('QuestionDifficultyCalibrationJob: 异步在线难度校准最终失败', [
  49. 'paper_id' => $this->paperId,
  50. 'student_id' => $this->studentId,
  51. 'question_count' => count($this->questions),
  52. 'error' => $exception->getMessage(),
  53. 'exception' => get_class($exception),
  54. 'memory_peak_mb' => round(memory_get_peak_usage(true) / 1024 / 1024, 2),
  55. ]);
  56. }
  57. /**
  58. * @param list<array<string,mixed>> $questions
  59. * @return list<array<string,mixed>>
  60. */
  61. private function compactQuestions(array $questions): array
  62. {
  63. $compact = [];
  64. foreach ($questions as $question) {
  65. if (! is_array($question)) {
  66. continue;
  67. }
  68. $questionId = $question['question_id'] ?? $question['question_bank_id'] ?? null;
  69. if ($questionId === null || $questionId === '') {
  70. continue;
  71. }
  72. $compact[] = [
  73. 'question_id' => $questionId,
  74. 'is_correct' => $question['is_correct'] ?? [],
  75. ];
  76. }
  77. return $compact;
  78. }
  79. }