4242from ai .backend .common .metrics .http import build_api_metric_middleware
4343from ai .backend .common .middlewares .exception import general_exception_middleware
4444from ai .backend .common .typed_validators import PydanticJWTValidator
45- from ai .backend .common .types import BinarySize , VFolderID
45+ from ai .backend .common .types import BinarySize , TusSessionId , VFolderID
4646from ai .backend .logging import BraceStyleAdapter
4747from ai .backend .storage import __version__
4848from ai .backend .storage .dto .context import StorageRootCtx
49- from ai .backend .storage .errors import InvalidAPIParameters , UploadOffsetMismatchError
49+ from ai .backend .storage .errors import (
50+ InvalidAPIParameters ,
51+ UploadChunkExceedsTotalSizeError ,
52+ UploadOffsetMismatchError ,
53+ )
5054from ai .backend .storage .services .file_stream .zip import (
5155 ZipArchiveStreamReader ,
5256)
@@ -99,7 +103,7 @@ class UploadTokenData(TypedDict):
99103 volume : str
100104 vfid : VFolderID
101105 relpath : str
102- session : str
106+ session : TusSessionId
103107 size : int
104108
105109
@@ -349,10 +353,11 @@ class Params(TypedDict):
349353 session_id = token_data ["session" ],
350354 total_size = int (token_data ["size" ]),
351355 valkey_client = ctx .valkey_tus_client ,
356+ lock_factory = ctx .tus_lock_factory ,
352357 )
353358 )
354359 state = await session .read_state ()
355- headers = _tus_response_headers (
360+ headers = _prepare_tus_session_headers (
356361 upload_offset = state .committed_offset ,
357362 upload_length = int (token_data ["size" ]),
358363 )
@@ -428,31 +433,30 @@ class Params(TypedDict):
428433 session_id = token_data ["session" ],
429434 total_size = total_size ,
430435 valkey_client = ctx .valkey_tus_client ,
436+ lock_factory = ctx .tus_lock_factory ,
431437 )
432438 )
433439 await session .ensure_initialized ()
434440
435441 upload_stream = TusChunkUploadStreamReader (
436442 request .content , request .content_type , DEFAULT_CHUNK_SIZE
437443 )
438- temp_chunk , length , sha256 = await session .write_temp_chunk (
439- client_offset , upload_stream
440- )
444+ written = await session .write_temp_chunk (client_offset , upload_stream )
441445 try :
442- if client_offset + length > total_size :
443- raise UploadOffsetMismatchError (
444- f"Chunk at offset { client_offset } with length { length } "
446+ if client_offset + written . length > total_size :
447+ raise UploadChunkExceedsTotalSizeError (
448+ f"Chunk at offset { client_offset } with length { written . length } "
445449 f"exceeds declared size { total_size } "
446450 )
447451 acceptance = await session .commit_chunk (
448452 offset = client_offset ,
449- chunk_path = temp_chunk .path ,
450- length = length ,
451- sha256 = sha256 ,
453+ chunk_path = written .path ,
454+ length = written . length ,
455+ sha256 = written . sha256 ,
452456 )
453457 except BaseException :
454- if temp_chunk .path .exists ():
455- await asyncio .to_thread (temp_chunk .path .unlink )
458+ if written .path .exists ():
459+ await asyncio .to_thread (written .path .unlink )
456460 raise
457461
458462 state = acceptance .state
@@ -464,7 +468,7 @@ class Params(TypedDict):
464468 await session .assemble (target_path )
465469 await session .cleanup ()
466470
467- headers = _tus_response_headers (
471+ headers = _prepare_tus_session_headers (
468472 upload_offset = state .committed_offset ,
469473 upload_length = total_size ,
470474 )
@@ -478,7 +482,7 @@ def _resolve_tus_upload_session_dir(volume: AbstractVolume, token_data: UploadTo
478482_TUS_HEADER_LIST = "Tus-Resumable, Upload-Length, Upload-Metadata, Upload-Offset, Content-Type"
479483
480484
481- def _tus_response_headers (* , upload_offset : int , upload_length : int ) -> dict [str , str ]:
485+ def _prepare_tus_session_headers (* , upload_offset : int , upload_length : int ) -> dict [str , str ]:
482486 return {
483487 "Access-Control-Allow-Origin" : "*" ,
484488 "Access-Control-Allow-Headers" : _TUS_HEADER_LIST ,
0 commit comments