Skip to content

Dua rumpun kegagalan transcribe yang akhirnya saya pisah

Adityo Guni Waluyo

Pipeline transkripsi saya mati diam-diam di tengah window. Ternyata hang itu exception yang harus ditangkap, dan tiap kegagalan punya pemiliknya sendiri.

Ringkasan

Proses transkrip yang hang itu ternyata nggak mati diam, cuma exception TimeoutExpired yang luput ditangkap. Kegagalannya dipetakan jadi dua rumpun: infrastruktur (exit 5, cukup retry) dan file rusak (exit 6, dicatat terus attempt-nya dinaikkan). File rusak dicoba max 3 kali lalu di-skip, tapi statusnya non-state jadi tetap ngeblok pipeline sampai manusia yang memutuskan.

# Dua rumpun kegagalan transcribe yang akhirnya saya pisah

Malam itu saya menemukan sebuah proses transkripsi panjang mati mendadak di tengah window. Prosesnya hilang, nggak ada event apa pun yang tertulis, dan satu baris pekerjaan cuma diam di situ. Tebakan pertama saya: prosesnya mati diam-diam, hilang tanpa jejak. Tebakan itu salah total. [3] Python sebenarnya membunuh child process saat timeout dan melempar exception TimeoutExpired ke pemanggil. Nggak ada yang mati diam-diam; yang salah ada di kode saya yang nggak pernah menangkap exception itu. Semua kegagalan dulu saya perlakukan sebagai satu bentuk yang sama, dan di situlah letak kesalahannya.

Dua rumpun: siapa yang harus memperbaiki

Setelah kejadian itu saya membagi semua kegagalan pipeline media menjadi dua keluarga besar, dilihat dari siapa pemilik perbaikannya. Rumpun pertama: kegagalan infrastruktur. Binary [1] whisper-cli mati atau menggantung sampai timeout, ffprobe nggak jalan, mesin kehabisan memori. Ini urusan mesin, bukan urusan file. Rumpun ini saya petakan ke exit 5: nggak ada event yang ditulis, cukup dicoba ulang. Rumpun kedua: kegagalan konten. File-nya sendiri yang bermasalah, misalnya container rusak sampai ffmpeg nggak bisa membaca window-nya. Rumpun ini saya petakan ke exit 6: sistem menulis event `transcribe-failed` dan menaikkan counter attempts satu angka.

Pembagian ini bukan sekadar kerapian katalog error. Exit code itu sebuah API untuk pemanggil. Kalau setiap mode kegagalan nggak dipetakan ke pemiliknya sebelum logika retry ditulis, loop retry justru bakal memperkuat kegagalan yang memang nggak akan pernah berhasil. File rusak dicoba lagi, gagal lagi, dicoba lagi, tanpa ujung.

Tangga percobaan supaya gagal itu konvergen

Rumpun konten butuh aturan berhenti. Solusinya sebuah tangga percobaan: selama attempts masih di bawah 3, sistem mencoba ulang otomatis; begitu menyentuh 3, file dilewati dengan status skip. Yang penting dari skip ini: sifatnya non-state. Baris pekerjaan tetap dihitung sebagai celah yang belum selesai dan tetap memblokir penutupan pipeline. File bermasalah nggak boleh diam-diam dianggap beres hanya karena retry-nya sudah habis; ia harus tetap kelihatan sampai ada keputusan manusia.

Sisa kekhawatiran saya tinggal satu: window di batas akhir file. [2] Dokumentasi ffmpeg bilang pencarian posisi dengan -ss nggak pernah presisi, cuma sampai seek point terdekat sebelum posisi yang diminta. Ternyata window terakhir yang pendek itu output normal, bukan error: -t sebagai input option cuma membatasi data yang dibaca, dan di akhir file artinya membaca lebih sedikit. Nggak perlu penanganan khusus.

Timeout itu exception, bukan kematian

Pelajaran paling mahal dari kejadian malam itu: hang nggak pernah terjadi tanpa suara. [3] Saat timeout habis, child process dibunuh dan exception TimeoutExpired dilempar ulang setelah prosesnya selesai dibersihkan. Bug aslinya sama sekali bukan di timeout-nya, tapi di nggak adanya kode yang menangkap exception itu. Setelah saya tangkap dan petakan ke exit 5, baris pekerjaan berhenti menggantung di limbo. Suite pengujian internal sekarang hijau penuh, dan pipeline saya berhenti menyalahkan jaringan atau mesin untuk file yang memang rusak.

Exit code yang dipetakan dengan benar itu murah dibuat, mahal ditunda. Rumpun kegagalan yang jelas menyelamatkan saya dari loop retry yang sia-sia, dan tangga percobaan memastikan setiap kegagalan berakhir di keputusan yang terdokumentasi, bukan di kebisingan.

Sumber

  1. whisper.cpp
  2. FFmpeg Documentation
  3. subprocess — Python documentation

Artikel terkait