call_start overwrites the call doc (merge=False) and can erase audio_gcs_uri when it lands after /upload #303

Open
opened 2026-10-27 20:38:15 -04:00 by logan · 0 comments
Owner

Found 2026-10-27 by drb-audio-review on node-26#45 (branch feat/45-trunk-recorder, not pushed).

What. mqtt_handler._on_call_start writes the call doc with doc_set(..., merge=False) (mqtt_handler.py ~L280). Any field already on the doc is erased: audio_gcs_uri (written by /upload), transcript, incident_id. So if call_start is handled AFTER /upload lands, the call loses its audio link and comes out of the AI pipeline untranscribed.

When it happens.

  • Trunk Recorder backend (node-26#45): the node publishes call_start right before uploading. It waits 1 s first (CALL_START_LEAD_SECONDS) to work around this, which is a heuristic. A backlog drain with 4 calls at once, or slow talkgroup resolution on C2, can still lose the race.
  • OP25 backend, today: a late-attributed call replays call_start in main.on_call_end, and that runs AFTER upload_recording. Same erase.

Fix shape. Make _on_call_start create-only (skip if the doc exists), or merge while keeping audio_gcs_uri/transcript/incident_id. Then the node-side 1 s lead can go.

Found 2026-10-27 by drb-audio-review on node-26#45 (branch feat/45-trunk-recorder, not pushed). **What.** `mqtt_handler._on_call_start` writes the call doc with `doc_set(..., merge=False)` (`mqtt_handler.py` ~L280). Any field already on the doc is erased: `audio_gcs_uri` (written by `/upload`), `transcript`, `incident_id`. So if `call_start` is handled AFTER `/upload` lands, the call loses its audio link and comes out of the AI pipeline untranscribed. **When it happens.** - Trunk Recorder backend (node-26#45): the node publishes `call_start` right before uploading. It waits 1 s first (`CALL_START_LEAD_SECONDS`) to work around this, which is a heuristic. A backlog drain with 4 calls at once, or slow talkgroup resolution on C2, can still lose the race. - OP25 backend, today: a late-attributed call replays `call_start` in `main.on_call_end`, and that runs AFTER `upload_recording`. Same erase. **Fix shape.** Make `_on_call_start` create-only (skip if the doc exists), or merge while keeping `audio_gcs_uri`/`transcript`/`incident_id`. Then the node-side 1 s lead can go.
logan added the
type
bug
area/recording-audioarea/mqtt
priority
p2
kind
behavior-bug
labels 2026-10-27 20:38:15 -04:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: logan/server-26#303