Upload workflow enhancements: S3 verification, timing, client checksum support (#19)
- Add S3 object verification after upload (size validation before DB commit) - Add cleanup of S3 objects if DB commit fails - Record upload duration_ms and user_agent - Support X-Checksum-SHA256 header for client-side checksum verification - Add already_existed flag to StorageResult for deduplication tracking - Add status, error_message, client_checksum columns to Upload model - Add UploadLock model for future 409 conflict detection - Add consistency-check admin endpoint for detecting orphaned S3 objects - Add migration 005_upload_enhancements.sql
This commit is contained in:
@@ -202,6 +202,9 @@ class StorageResult(NamedTuple):
|
||||
md5: Optional[str] = None
|
||||
sha1: Optional[str] = None
|
||||
s3_etag: Optional[str] = None
|
||||
already_existed: bool = (
|
||||
False # True if artifact was deduplicated (S3 object already existed)
|
||||
)
|
||||
|
||||
|
||||
class S3StorageUnavailableError(StorageError):
|
||||
@@ -354,6 +357,7 @@ class S3Storage:
|
||||
md5=md5_hash,
|
||||
sha1=sha1_hash,
|
||||
s3_etag=s3_etag,
|
||||
already_existed=exists,
|
||||
)
|
||||
|
||||
def _store_multipart(self, file: BinaryIO, content_length: int) -> StorageResult:
|
||||
@@ -433,6 +437,7 @@ class S3Storage:
|
||||
md5=md5_hash,
|
||||
sha1=sha1_hash,
|
||||
s3_etag=s3_etag,
|
||||
already_existed=True,
|
||||
)
|
||||
|
||||
# Seek back to start for upload
|
||||
@@ -486,6 +491,7 @@ class S3Storage:
|
||||
md5=md5_hash,
|
||||
sha1=sha1_hash,
|
||||
s3_etag=s3_etag,
|
||||
already_existed=False,
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
@@ -535,6 +541,7 @@ class S3Storage:
|
||||
md5=md5_hash,
|
||||
sha1=sha1_hash,
|
||||
s3_etag=s3_etag,
|
||||
already_existed=True,
|
||||
)
|
||||
|
||||
# Upload based on size
|
||||
@@ -615,6 +622,7 @@ class S3Storage:
|
||||
md5=md5_hash,
|
||||
sha1=sha1_hash,
|
||||
s3_etag=s3_etag,
|
||||
already_existed=False,
|
||||
)
|
||||
|
||||
def initiate_resumable_upload(self, expected_hash: str) -> Dict[str, Any]:
|
||||
|
||||
Reference in New Issue
Block a user