You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
A download abandoned before its body starts does not close the store's handle promptly #1604
GET /api/v1/files/{file_id}/content streams the bytes. Before it answers, FileService.content reads the first chunk eagerly through _primed in services/files/_service.py, so a blob that is gone or unreadable fails while the failure can still be reported.
Priming starts the store's own generator, which is then suspended inside the adapter's async with on an open file handle. The close is owned by the finally in _primed's inner generator, and that finally only runs once something starts iterating it. If the request is abandoned between the service returning and the response beginning to send, the inner generator is never entered, closing it runs no finally, and the store's handle is not closed there.
It is not a permanent leak. The handle closes when the suspended generator is collected and the event loop's async-generator finalizer runs it, or at loop shutdown. That is the delay the finally exists to avoid, and the comment beside it claims the case is covered. Under sustained abandoned downloads the handles accumulate for as long as collection lags.
Fix
Give the close an owner that does not depend on the body iterator starting. Either:
prime lazily, moving the first read inside the try so the caller's first __anext__ is what raises; or
have the response path close the underlying stream on teardown whether or not iteration began.
An idempotent aclose makes either safe.
Done when
The store's handle is closed when the body iterator is never started.
A test in tests/unit/test_files_streaming.py covers the never-started consumer. The existing tests all start the generator.
Activity