billowy-hairdresser-80384
05/14/2026, 5:08 PMtall-airline-16756
05/14/2026, 5:08 PMtall-airline-16756
05/14/2026, 5:08 PMegress_ended event arriving promptly, or do they show retries/delays? If available, share timestamps for when egress finished vs. when your endpoint received the event.
• Are you validating webhook signatures using the raw request body? (Signatures are HMAC-SHA256 of the raw payload.)
• Does your endpoint return a 2xx response quickly and defer heavy work (file processing, DB writes, downstream uploads) to a background job?
• Do you see duplicate deliveries or retry headers on the webhook requests?
What typically causes this and what to try now:
• Webhooks are retried on transient failures; if your endpoint is slow or returns non-2xx, events can be delayed. Ensure fast 2xx responses and async processing.
• Larger audio files can delay finalization before the egress_ended event is emitted; check egress server logs for finalization timing.
• If your receiver sometimes fails signature validation (e.g., using parsed JSON instead of raw body), events will be retried and delivered later.
If you can share:
• One example: egress end time, webhook receive time, and any webhook response codes from your server logs for that run.
• Whether you return 2xx immediately or perform synchronous upload/processing in the webhook handler.
With those details I’ll suggest the next concrete steps (specific log fields to check, header fields to inspect, and code patterns to change to avoid delays).
, with interactive elementsbillowy-hairdresser-80384
05/14/2026, 5:09 PMtall-airline-16756
05/14/2026, 5:10 PMbackupStorageUsed: true).
Sources: Backup Egress Recordings, with interactive elementsbillowy-hairdresser-80384
05/14/2026, 5:10 PMtall-airline-16756
05/14/2026, 5:10 PMegress_ended (or EGRESS_COMPLETE) webhook payload: it indicates the recording was finalized and upload attempts completed. The payload includes upload status fields and will contain backupStorageUsed: true if primary upload failed and a backup was used.
• Inspect the egress job status via your egress API or admin logs: the job moves to a completed/ended state when writing and upload attempts are finished.
• Verify the file directly in the destination storage (e.g., S3, GCS, or your configured output): confirm the file exists, size matches expectation, and any expected metadata or checksum is present.
• If you rely on webhooks, ensure your receiver logs show a prompt egress_ended delivery with a 2xx response. Retries or non-2xx responses indicate the event wasn’t acknowledged and may mean upload/finalization wasn’t confirmed to you yet.
If you want, share an example egress_ended payload or the storage provider you use and I’ll point to the exact fields and checks to confirm upload success.
, with interactive elementsbillowy-hairdresser-80384
05/14/2026, 5:22 PMtall-airline-16756
05/14/2026, 5:22 PMlocation in file_results.
Short answer: To reliably know the file upload finished you need BOTH a completed egress status (EGRESS_COMPLETE) and an authoritative upload location (the `file_results[0].location`/blob URL). If location is missing, the upload did not succeed even if the status string reports complete.
What to check next (quick checklist):
• Inspect the full egress_ended payload/webhook for error fields and for file_results entries — there may be an error reason or backupStorageUsed flag.
• Confirm your egress destination config (Azure/S3/GCS): correct container/bucket, credentials, and write permissions for the LiveKit egress service.
• Check egress service logs for that job: look for upload errors, timeouts, or fallback-to-backup messages around the same timestamp.
• Verify your get_egress_info mapping returns the raw FileInfo fields (size, duration, location) without modification; log the raw egress_info when location is missing to capture full context.
• Ensure you’re treating EGRESS_COMPLETE as meaning “recording finalized and upload attempts finished” — but upload can still fail; presence of location is the authoritative proof of a successful upload.
Recommended code change (minimal):
• Keep your gate that requires BOTH is_complete AND audio_blob_url. But change the elif is_complete: branch to mark upload as FAILED/UNKNOWN (not confirmed) and record the egress job ID and any error details for retry or manual handling.
Example flow to implement:
1. If is_complete and audio_blob_url → treat as uploaded (normal success).
2. If is_complete and NO audio_blob_url → mark as upload failed/needs investigation; surface egress job id and egress_info into a retry/alert queue.
3. If not complete → wait/retry checking get_egress_info or rely on webhook retries.
If you share one raw egress_ended payload (with sensitive tokens redacted) where location is missing, I can point to the exact fields to inspect and suggest targeted fixes.
, with interactive elementsbillowy-hairdresser-80384
05/14/2026, 5:23 PMtall-airline-16756
05/14/2026, 5:23 PMegress_info (full payload) when location is missing — capture the exact status, any error fields, backupStorageUsed, and file_results contents.
• Compare timestamps: check when the file appears in storage vs when get_egress_info (or webhook) returned the status. This shows whether status lags finalization.
• Confirm you are reading the authoritative field: file_results[0].location is the definitive upload URL. If that exists in the raw payload, treat upload as complete.
• If the file is present in storage but location is missing:
◦ Inspect egress service logs for upload completion vs. upload-to-metadata-write timing; metadata (location) write may be delayed.
◦ Check for transient upload errors or fallback behavior (backupStorageUsed: true) in the payload.
• Ensure your webhook polling/handler uses the raw response and not a cached/older egress_info. If you poll get_egress_info, retry with backoff for a short window after egress reports complete.
• Update your code gate: leave the gate requiring BOTH EGRESS_COMPLETE and location, but treat the case "complete but no location" as needs-investigation (enqueue for re-check and alert) rather than confirmed success.
If you want, paste one raw egress_info where storage contains the file but file_results[0].location is empty (redact keys). I’ll point to the exact fields and a minimal retry/alert logic you can add.
, with interactive elementsbillowy-hairdresser-80384
05/14/2026, 5:29 PMtall-airline-16756
05/14/2026, 5:29 PMlist_egress() call is the right move. It separates transient network/API errors from “still processing” state and preserves your 10‑minute budget for actual status polling.
Recommended changes (concise):
• Wrap only the list_egress() call with a retry policy (e.g., 3 attempts, exponential backoff) so transient failures are retried quickly without using the main loop retries.
• Keep the outer polling loop for status checks (5s interval), but:
◦ Add logging when egress_response.items is empty and increment a small counter to bail early if it remains empty for N consecutive polls.
◦ Use exponential backoff on consecutive API failures and a separate consecutive-error limit to abort early (avoid burning the full 600s).
◦ Treat "is_complete but no location" as FAILED/UNKNOWN: enqueue for re-check and alert rather than marking success.
• Add short re-check window after EGRESS_COMPLETE (e.g., poll file_results for another 30–60s with backoff) to catch delayed metadata writes.
Minimal tenacity example (conceptual):
1. Add retry decorator around `list_egress()`:
◦ stop after 3 attempts
◦ wait exponential (initial=0.5s, max=4s)
◦ retry on network/HTTP exceptions
1. In loop:
◦ call retried list_egress()
◦ if empty items → log + increment empty counter, if counter > 3 → warn and break
◦ if API exception after retries → increment error counter, if error counter > 5 → abort/publish alert
◦ if is_complete and no location → enqueue re-check job with the egress_id + timestamp
If you want, I can:
• Provide the exact patch/diff to insert tenacity and the empty/error counters into your shown function, or
• Produce the concrete Python snippet to paste into livekit_service.py.
Which would you prefer?
, with interactive elements