## Summary This PR reduces duplicate failure noise for audio transcription jobs that fail with permanent HTTP 400 responses, and fixes a file-format edge case causing intermittent 400s. Sentry issue: [CHATWOOT-99E / 6660541334](https://chatwoot-p3.sentry.io/issues/6660541334/) ## Confirmed root cause For some attachments, the stored filename had no extension (example: `speech`, content type `audio/mpeg`). When the temporary transcription upload file was created without an extension, OpenAI returned: `Unrecognized file format` (HTTP 400). ## Scope of changes 1. `Messages::AudioTranscriptionJob` - Keeps `discard_on Faraday::BadRequestError` to avoid retry storms on permanent request errors. - Adds explicit Rails warning logs for discarded jobs with attachment/job/status context. 2. `Messages::AudioTranscriptionService` - Keeps guaranteed temp file cleanup via `ensure`. - Ensures temp upload files include an extension when the original filename has none, derived from blob `content_type`. - This addresses intermittent failures like extensionless `audio/mpeg` files. ## Reproduction Enable audio transcription for an account and process an audio attachment whose stored filename has no extension (for example `speech`) but valid audio content type (`audio/mpeg`). Before this fix, OpenAI transcription could return HTTP 400 `Unrecognized file format` for that attachment while similar attachments with extensions succeeded. ## Testing Ran: `bundle exec rubocop enterprise/app/jobs/messages/audio_transcription_job.rb enterprise/app/services/messages/audio_transcription_service.rb` Result: both modified files pass lint with no offenses.
22 lines
636 B
Ruby
22 lines
636 B
Ruby
class Messages::AudioTranscriptionJob < ApplicationJob
|
|
queue_as :low
|
|
|
|
discard_on Faraday::BadRequestError do |job, error|
|
|
log_context = {
|
|
attachment_id: job.arguments.first,
|
|
job_id: job.job_id,
|
|
status_code: error.response&.dig(:status)
|
|
}
|
|
|
|
Rails.logger.warn("Discarding audio transcription job due to bad request: #{log_context}")
|
|
end
|
|
retry_on ActiveStorage::FileNotFoundError, wait: 2.seconds, attempts: 3
|
|
|
|
def perform(attachment_id)
|
|
attachment = Attachment.find_by(id: attachment_id)
|
|
return if attachment.blank?
|
|
|
|
Messages::AudioTranscriptionService.new(attachment).perform
|
|
end
|
|
end
|