feat(zoom): index Cloud Recording transcripts from configured meetings - #14482
feat(zoom): index Cloud Recording transcripts from configured meetings#14482Subash-Mohan wants to merge 5 commits into
Conversation
|
Full-stack Preview (frontend + backend)
|
501c955 to
67e22ca
Compare
Greptile SummaryThe PR adds checkpointed discovery and indexing of Zoom Cloud Recording transcripts for configured meeting IDs.
Confidence Score: 5/5The PR appears safe to merge with no outstanding actionable defects identified. The latest changes correctly consolidate transcript readiness checks, preserve diagnostic exceptions without serializing them, and retain checkpoint position for transient HTTP 408 failures. The three previous threads were manually resolved without explanatory replies and therefore do not remain outstanding. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Configured Zoom meeting IDs] --> B[List meeting occurrences]
B --> C{Occurrence in poll window?}
C -- No --> B
C -- Yes --> D[Store occurrence in checkpoint work queue]
D --> E[Fetch transcript metadata]
E --> F{Downloadable?}
F -- Not ready or unavailable --> G[Skip and revisit through overlap window]
F -- Yes --> H[Download and parse VTT]
H --> I[Create occurrence-specific Zoom document]
I --> J[Index searchable transcript]
Reviews (3): Last reviewed commit: "fix(zoom): gate the transcript download ..." | Re-trigger Greptile |
There was a problem hiding this comment.
All reported issues were addressed across 18 files
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
Adds the connector itself on top of the client: an admin lists Zoom meeting ids, and each recorded occurrence of those meetings becomes a searchable document. Registers DocumentSource.ZOOM so the connector is reachable from the indexing pipeline; the admin UI to configure it comes with webinar support. A meeting id is expanded into its past occurrences rather than fetched directly, because a recurring meeting records each run separately and the bare id only reaches the most recent one. Structure follows the two axes that vary. Discovery mechanisms are resumable sources that emit occurrences and own an opaque cursor, so a crash resumes instead of restarting, and host/group discovery can page Zoom's own way later. Meeting-versus-webinar differences sit behind a session-type handler. connector.py holds only checkpoint mechanics. Two limits worth knowing. Zoom's occurrence listing takes no date or page parameters, so a long-running meeting is paged client-side and each page after the first re-lists it; without that cap the checkpoint is rewritten in full on every invocation. And an occurrence is selected by when the meeting ran, while its transcript appears later, so each poll reaches back ZOOM_TRANSCRIPT_LAG_BUFFER_HOURS (default 72) to catch ones that were still processing. Zoom publishes no maximum for that lag. Document ids carry the session type because a targeted reindex is handed ids and nothing else, and changing the scheme after indexing orphans what is already stored. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EBNe54dXPELTXXGdk1uYR6
A ConnectorFailure ends the attempt COMPLETED_WITH_ERRORS, which Onyx counts as successful, so the next run rebuilds the checkpoint over a newer poll window. Rate limits, expired credentials and network errors were all landing there, which permanently dropped any occurrence older than ZOOM_TRANSCRIPT_LAG_BUFFER_HOURS. Targeted reindex cannot recover those either, since it is keyed on document ids and a discovery failure only produces an entity failure. Errors that will hit every remaining occurrence now propagate, so the attempt fails and the next run resumes from its checkpoint on the same work item. Errors specific to one transcript or session still record a ConnectorFailure and move on. Waiting and retrying is left to the client, which already mounts a urllib3 Retry honouring Zoom's Retry-After. Exhausting it raises RetryError rather than HTTPError, so a sustained 429 is classified on the exception type, not on a status code. Also carry the session type in the discovery EntityFailure, since 111 is a legal id for both a meeting and a webinar. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EBNe54dXPELTXXGdk1uYR6
The classifier listed the transport errors it knew about, so a body that stopped mid-transfer raised JSONDecodeError or ChunkedEncodingError and was read as one bad session. Discovery then skipped that meeting, and the next run's poll window no longer reached its history. HTTPError is the only requests error where a response came back to judge, so classify on that and treat every other RequestException as systemic. This also covers whatever requests adds later. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EBNe54dXPELTXXGdk1uYR6
Occurrence timestamps were pinned to January 2026 while the poll window ends at time.time(). Discovery drops anything outside that window, so on a machine whose clock predates the pinned date every result set empties and the count assertions fail for a reason unrelated to what they test. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EBNe54dXPELTXXGdk1uYR6
67e22ca to
d29865f
Compare
|
@Subash-Mohan I have started the AI code review. It will take a few minutes to complete. |
There was a problem hiding this comment.
All reported issues were addressed across 18 files
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
ZoomTranscript.is_downloadable existed but nothing called it, so the download ran whenever a url was present. Zoom returns a url alongside can_download=False or a restriction reason, and each of those cost a download that Zoom then refused. NOT_READY still logs as a retry rather than a warning, since it is the one restriction that clears on its own. Document failures now carry the exception. The runner gates its Sentry report and its threshold re-raise on that field, so both Zoom download failures were invisible there while discovery's were not. Classify HTTP 408 as systemic. The client's Retry covers 429 but not 408, so a timed-out request was reaching the per-occurrence path and skipping that occurrence for good. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EBNe54dXPELTXXGdk1uYR6
|
@Subash-Mohan I have started the AI code review. It will take a few minutes to complete. |
Description
ZOOM_TRANSCRIPT_LAG_BUFFER_HOURS, default 72)How Has This Been Tested?
Unit tests for discovery, processing, checkpointing and session types (60 tests); daily suite scaffolded against the real Zoom API.
Additional Options
Summary by cubic
Adds a Zoom connector that indexes Cloud Recording transcripts from configured meeting IDs, making each recorded occurrence of those meetings a searchable document. The admin UI to configure it isn't included yet, so the connector is reachable from tests but not the product.
New Features
ZOOM_TRANSCRIPT_LAG_BUFFER_HOURS, default 72).Bug Fixes
Written for commit 0c602f8. Summary will update on new commits.