Harden stuck Whisper recovery and record transcription duration.

Fail jobs on timeout, treat stale reserved queue rows as orphans, skip migrate/seed on queue/reverb boot, and store how long each successful run took.
This commit is contained in:
ben
2026-08-13 00:12:06 +02:00
parent 2b126ee4e6
commit f42d124593
7 changed files with 230 additions and 67 deletions
+11 -21
View File
@@ -6,9 +6,11 @@ use App\Models\Recording;
use App\Services\TranscriptionService;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Queue\Attributes\FailOnTimeout;
use Illuminate\Support\Facades\Log;
use Throwable;
#[FailOnTimeout]
class TranscribeRecording implements ShouldQueue
{
use Queueable;
@@ -20,6 +22,9 @@ class TranscribeRecording implements ShouldQueue
/**
* The number of seconds the job can run before timing out.
*
* Covers a hung Whisper HTTP call: the worker is killed, failed() runs,
* and the recording is marked failed so the UI can restart.
*/
public int $timeout;
@@ -134,16 +139,7 @@ class TranscribeRecording implements ShouldQueue
}
if ($this->recording->ownsTranscriptionRun($this->runStartedAt)) {
$this->recording->forceFill([
'transcript' => $text,
'transcription_status' => 'done',
'transcription_progress' => 'Transcription complete',
'transcription_percent' => 100,
'transcription_error' => null,
'transcribed_at' => now(),
])->save();
$this->recording->broadcastTranscriptionUpdated();
$this->recording->markTranscriptionComplete($text);
return true;
}
@@ -152,22 +148,16 @@ class TranscribeRecording implements ShouldQueue
if (
$this->recording->transcription_status === 'failed'
&& $this->recording->matchesTranscriptionRun($this->runStartedAt)
&& str_contains((string) $this->recording->transcription_error, 'worker stopped')
&& (
str_contains((string) $this->recording->transcription_error, 'worker stopped')
|| str_contains((string) $this->recording->transcription_error, 'timed out')
)
) {
Log::warning('Recovering transcript after false orphan failure', [
'recording_id' => $this->recording->id,
]);
$this->recording->forceFill([
'transcript' => $text,
'transcription_status' => 'done',
'transcription_progress' => 'Transcription complete',
'transcription_percent' => 100,
'transcription_error' => null,
'transcribed_at' => now(),
])->save();
$this->recording->broadcastTranscriptionUpdated();
$this->recording->markTranscriptionComplete($text);
return true;
}