deer-flow/backend/app/channels/sandbox_files.py
Bxl 41e8e75f56
fix: balance temporary sandbox leases for uploads (#3261)
* fix: balance temporary sandbox leases for uploads

* fix: address sandbox upload review feedback

---------

Co-authored-by: Bxl <188532127+BXL1015@users.noreply.github.com>
Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-09-26 16:22:20 +08:00

53 lines
1.7 KiB
Python

"""Shared lifecycle-safe synchronization for inbound channel attachments."""
from __future__ import annotations
import logging
from deerflow.sandbox.lease import acquire_sandbox_client_lease
logger = logging.getLogger(__name__)
async def sync_file_to_thread_sandbox(
sandbox_provider,
*,
thread_id: str,
user_id: str,
virtual_path: str,
content: bytes,
owner_prefix: str,
release_on_last: bool = False,
) -> bool:
"""Copy one attachment while holding a sandbox client lease.
Thread-data mount providers already see the persisted upload. Other
providers need a unique holder so a parallel run cannot close their client
during ``update_file``. The blocking transport worker is drained even when
the channel handler is repeatedly cancelled, and only then is the holder
released. ``release_on_last=True`` also parks a standalone temporary
sandbox once all execution holders have finished.
"""
if getattr(sandbox_provider, "uses_thread_data_mounts", False):
return True
lease = await acquire_sandbox_client_lease(
sandbox_provider,
thread_id,
user_id=user_id,
owner_prefix=owner_prefix,
release_on_last=release_on_last,
)
try:
if lease.sandbox_id == "local" or lease.sandbox_id.startswith("local:"):
return True
if lease.sandbox is None:
return False
await lease.run_sync(lease.sandbox.update_file, virtual_path, content)
return True
finally:
try:
await lease.release()
except Exception:
logger.warning("Failed to release sandbox %s after file sync", lease.sandbox_id, exc_info=True)