Class: DailyCallRecordTranscriptionWorker
- Inherits:
-
Object
- Object
- DailyCallRecordTranscriptionWorker
- Includes:
- Sidekiq::Job
- Defined in:
- app/workers/daily_call_record_transcription_worker.rb
Overview
the AssemblyAI backfill is OFF by default. The day-to-day coverage gap
is now closed by the cheap Gemini pipeline (CallRecordBulkTranscriptionWorker,
min_age 7d), which sweeps anything older than the recent window. Enable this
backfill only for a deliberate full-feature (diarization + LeMUR) re-run of a
chosen recent window — either by passing args to perform_async or by adding
them to the daily_call_record_transcription cron entry. It uses the expensive
AssemblyAI path, so it is intentionally not the default backlog tool.
Daily catch-up worker for call record transcriptions.
Primary transcription is queued immediately when call records are imported
via CallRecordSwitchvoxImporterFile. This worker serves as a safety net
to catch any records that were missed (e.g., queue issues, worker failures,
records created through other means).
Runs at 6 AM CT daily via sidekiq-cron.
The worker uses the ai_embeddings queue for controlled throughput
and to avoid impacting user-facing operations.
Cost estimate: ~$0.06/call (transcription + LeMUR + embedding)
Constant Summary collapse
- BACKFILL_ENABLED =
Defaults for the optional AssemblyAI backfill (overridable per-run via args).
false- BACKFILL_LIMIT =
Constant.
500- BACKFILL_DAYS_LIMIT =
2 years = 730 days - older calls are not worth the AssemblyAI cost
730- RECONCILE_TOO_SHORT_DAYS =
How far back to give sub-floor
pendingcalls their terminaltoo_short
verdict. They are below the transcription floor so CallRecord.transcription_eligible
permanently skips them; without this they sit inpendingforever and inflate
the daily digest's "in flight" line. A rolling window backfills the recent stuck
ones and keeps each new day clean before the 8 AM digest. 30- RECONCILE_NO_AUDIO_DAYS =
How far back to give upload-less
pendingcalls their terminalno_audio
verdict.CallRecord#created_atis BACKDATED to the call time by the importer,
and both CallRecord.transcription_eligible and CallRecord.transcription_too_short
INNER JOIN:upload— so apendingrecord that never got an audio file (a
voicemail CDR leg with no recording, a missed call) is unreachable by every
reconciler and sits inpendingforever, inflating the digest's "in flight"
line. This is exactly the verdict CallRecordProcessing::TranscriptionService
assigns viaskip_result(:no_audio), which these never reach. Mirrors
#reconcile_too_short: one bounded UPDATE over the recent window. 30- NO_AUDIO_GRACE =
Grace period before an upload-less
pendingcall is declaredno_audio.
Voicemail audio is attached out-of-band (VoicemailsMailbox / webhook) moments
after the record appears; this keeps a just-created record whose audio is still
arriving from being prematurely closed. 2.hours
- RECONCILE_FILELESS_LIMIT =
Per-run cap on #reconcile_fileless_upload. Its siblings only ever see a
day's worth of strays, but this one drains the pre-fix backlog of records
stranded inprocessing(AppSignal #1982), so the first runs could otherwise
be one very large UPDATE. Matches BACKFILL_LIMIT; the remainder is picked up
by the next nightly pass, and the log says when the cap was hit. 500- REQUEUE_ELIGIBLE_DAYS =
How far back the catch-up re-queues stuck eligible (
pending/error) calls.
The previous 24-hour window keyed on the BACKDATEDcreated_atcould never
catch an evening recording imported after that morning's catch-up run — by the
next run its call-timecreated_atis already >24h old, so it fell permanently
outside the net and was never transcribed (always the day's last recording).
A multi-day window closes that hole; re-queues are idempotent (eligible excludes
processing/completed, and the service skips already-transcribed records). 7
Instance Method Summary collapse
Instance Method Details
#perform(options = {}) ⇒ void
This method returns an undefined value.
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'app/workers/daily_call_record_transcription_worker.rb', line 89 def perform( = {}) backfill_enabled = .fetch(:backfill, BACKFILL_ENABLED) backfill_limit = ([:backfill_limit] || BACKFILL_LIMIT).to_i backfill_days = ([:backfill_days] || BACKFILL_DAYS_LIMIT).to_i Rails.logger.info '[DailyCallRecordTranscriptionWorker] Starting catch-up transcription run' new_calls_count = process_new_calls too_short_count = reconcile_too_short no_audio_count = reconcile_no_audio fileless_count = reconcile_fileless_upload backfill_count = backfill_enabled ? backfill_older_calls(backfill_limit, backfill_days) : 0 Rails.logger.info '[DailyCallRecordTranscriptionWorker] Completed: ' \ "#{new_calls_count} stuck/missed calls queued, #{too_short_count} marked too_short, " \ "#{no_audio_count} marked no_audio, #{fileless_count} fileless-upload marked no_audio, " \ "#{backfill_count} backfilled" end |