Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions surfsense_backend/app/agents/video_presentation/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from app.services.kokoro_tts_service import get_kokoro_tts_service
from app.services.llm_service import get_agent_llm
from app.utils.content_utils import extract_text_content, strip_markdown_fences
from app.utils.file_io import write_bytes

from .configuration import Configuration
from .prompts import (
Expand Down Expand Up @@ -137,8 +138,7 @@ async def _generate_tts_chunk(text: str, chunk_path: str) -> str:
kwargs["api_base"] = app_config.TTS_SERVICE_API_BASE

response = await aspeech(**kwargs)
with open(chunk_path, "wb") as f:
f.write(response.content)
await write_bytes(chunk_path, response.content)

return chunk_path

Expand Down
7 changes: 7 additions & 0 deletions surfsense_backend/app/utils/file_io.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import asyncio
from pathlib import Path


async def write_bytes(path: str, content: bytes) -> None:
"""Write bytes without blocking the event loop."""
await asyncio.to_thread(Path(path).write_bytes, content)
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import asyncio
import threading

import pytest

from app.utils.file_io import write_bytes

pytestmark = pytest.mark.unit


@pytest.mark.asyncio
async def test_write_bytes_does_not_block_event_loop(monkeypatch, tmp_path):
write_started = threading.Event()
release_write = threading.Event()

def blocking_write(_path, _content):
write_started.set()
release_write.wait(timeout=1)
return 5

monkeypatch.setattr("pathlib.Path.write_bytes", blocking_write)

task = asyncio.create_task(write_bytes(str(tmp_path / "audio.mp3"), b"audio"))
while not write_started.is_set():
await asyncio.sleep(0)

assert not task.done()
release_write.set()
await task