fix(compile): shield the sync endpoint from client disconnects

nginx 504s a cold ESP-IDF build long before it finishes; Starlette then
cancels the handler and the cancellation killed the build subprocess
MID-WRITE, leaving truncated .obj files in the persistent per-target
build cache - every later build of that target failed with
'ranlib: file truncated' until the cache was wiped (bitten twice on
staging the day the P4 lane landed). asyncio.shield lets the build run
to completion with a consistent cache; only the response is lost, and
the async /start + /status flow remains the right path for long builds.
This commit is contained in:
David Montero Crespo 2026-08-19 07:29:26 +02:00
parent 010a112bc8
commit 2656376cd5
1 changed files with 12 additions and 1 deletions

View File

@ -617,7 +617,18 @@ async def compile_sketch(
files = _resolve_files(request)
started = time.monotonic()
try:
response = await _run_compile(request, files, requester_id=user_id)
# Shielded: when the client (or a proxy timeout - nginx 504s a cold
# ESP-IDF build well before it finishes) drops the connection,
# Starlette cancels this handler. Without the shield the cancellation
# killed the build subprocess MID-WRITE and left truncated .obj files
# in the persistent per-target build cache, poisoning every LATER
# build of that target ("ranlib: file truncated", seen twice on
# staging the day the P4 lane landed). The shield lets the build run
# to completion and keep the cache consistent; only the response is
# lost.
response = await asyncio.shield(
asyncio.ensure_future(_run_compile(request, files, requester_id=user_id))
)
except Exception as e:
await record_compile(
user_id=user_id,