From 5f49f1c0524c789aa14e919bd69aeda6d1800ec9 Mon Sep 17 00:00:00 2001 From: Sam Date: Mon, 13 Jul 2026 16:51:29 +0200 Subject: [PATCH 1/2] fix: skip summarization for finished empty transcripts to avoid infinite retries --- echo/server/dembrane/api/conversation.py | 7 +++++++ echo/server/dembrane/conversation_utils.py | 3 +++ 2 files changed, 10 insertions(+) diff --git a/echo/server/dembrane/api/conversation.py b/echo/server/dembrane/api/conversation.py index 4342fa876..b7b415ecd 100644 --- a/echo/server/dembrane/api/conversation.py +++ b/echo/server/dembrane/api/conversation.py @@ -674,9 +674,16 @@ async def summarize_conversation( language = conversation_data["project_id"]["language"] if transcript_str == "": + # Update conversation in DB so summary is no longer null, preventing infinite retries by the catch-up scheduler + await run_in_thread_pool( + conversation_service.update, + conversation_id=conversation_id, + summary="empty", + ) return { "status": "success", "message": "Transcript is empty, so no summary was generated", + "summary": "empty", } else: summary = await run_in_thread_pool( diff --git a/echo/server/dembrane/conversation_utils.py b/echo/server/dembrane/conversation_utils.py index fb5efa59f..4d3115c9d 100644 --- a/echo/server/dembrane/conversation_utils.py +++ b/echo/server/dembrane/conversation_utils.py @@ -136,6 +136,9 @@ def collect_unsummarized_conversations(limit: int = 50) -> List[str]: Simple check: is_all_chunks_transcribed = True AND summary = null. The transcribed flag is the source of truth for "ready for summarization". + We also exclude conversations where the summary is set to any special marker + or we determine they shouldn't be retried (like empty ones, though empty ones + usually have summary = "empty" or similar if we skip them cleanly). Args: limit: Maximum number of conversations to return (default 50). From 4dced6ad25c3004610b2d1a495f4e87a23fe66fd Mon Sep 17 00:00:00 2001 From: Sam Date: Mon, 13 Jul 2026 18:14:31 +0200 Subject: [PATCH 2/2] fix: skip summarization for finished empty transcripts via dedicated has_empty_transcript flag --- echo/server/dembrane/api/conversation.py | 5 ++--- echo/server/dembrane/conversation_utils.py | 6 ++---- echo/server/dembrane/service/conversation.py | 3 +++ 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/echo/server/dembrane/api/conversation.py b/echo/server/dembrane/api/conversation.py index b7b415ecd..305804cf9 100644 --- a/echo/server/dembrane/api/conversation.py +++ b/echo/server/dembrane/api/conversation.py @@ -674,16 +674,15 @@ async def summarize_conversation( language = conversation_data["project_id"]["language"] if transcript_str == "": - # Update conversation in DB so summary is no longer null, preventing infinite retries by the catch-up scheduler + # Update conversation in DB so has_empty_transcript is True, preventing infinite retries by the catch-up scheduler await run_in_thread_pool( conversation_service.update, conversation_id=conversation_id, - summary="empty", + has_empty_transcript=True, ) return { "status": "success", "message": "Transcript is empty, so no summary was generated", - "summary": "empty", } else: summary = await run_in_thread_pool( diff --git a/echo/server/dembrane/conversation_utils.py b/echo/server/dembrane/conversation_utils.py index 4d3115c9d..836f95e53 100644 --- a/echo/server/dembrane/conversation_utils.py +++ b/echo/server/dembrane/conversation_utils.py @@ -134,11 +134,8 @@ def collect_unsummarized_conversations(limit: int = 50) -> List[str]: """ Collect conversations that are fully transcribed but missing a summary. - Simple check: is_all_chunks_transcribed = True AND summary = null. + Simple check: is_all_chunks_transcribed = True AND summary = null AND has_empty_transcript != True. The transcribed flag is the source of truth for "ready for summarization". - We also exclude conversations where the summary is set to any special marker - or we determine they shouldn't be retried (like empty ones, though empty ones - usually have summary = "empty" or similar if we skip them cleanly). Args: limit: Maximum number of conversations to return (default 50). @@ -153,6 +150,7 @@ def collect_unsummarized_conversations(limit: int = 50) -> List[str]: "filter": { "is_all_chunks_transcribed": True, "summary": {"_null": True}, + "has_empty_transcript": {"_neq": True}, "deleted_at": {"_null": True}, "created_at": { "_lte": (get_utc_timestamp() - timedelta(minutes=5)).isoformat() diff --git a/echo/server/dembrane/service/conversation.py b/echo/server/dembrane/service/conversation.py index 0d53c4e98..a786eca23 100644 --- a/echo/server/dembrane/service/conversation.py +++ b/echo/server/dembrane/service/conversation.py @@ -330,6 +330,7 @@ def update( is_finished: Any = _UNSET, is_all_chunks_transcribed: Any = _UNSET, is_over_cap: Any = _UNSET, + has_empty_transcript: Any = _UNSET, ) -> dict: update_data: dict[str, Any] = {} if participant_name is not _UNSET: @@ -348,6 +349,8 @@ def update( update_data["is_all_chunks_transcribed"] = is_all_chunks_transcribed if is_over_cap is not _UNSET: update_data["is_over_cap"] = is_over_cap + if has_empty_transcript is not _UNSET: + update_data["has_empty_transcript"] = has_empty_transcript try: with self._client_context() as client: