fix: Handle regular S3 objects without DeltaGlider metadata

- get_object() now transparently downloads regular S3 objects
- Falls back to direct download when file_sha256 metadata is missing
- Enables DeltaGlider to work with existing S3 buckets
- Add test for downloading regular S3 files

Fixes issue where get_object() would fail with NotFoundError when
trying to download objects uploaded outside of DeltaGlider.

This allows users to:
- Browse existing S3 buckets with non-DeltaGlider objects
- Download any S3 object regardless of upload method
- Use DeltaGlider as a drop-in S3 client replacement

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Simone Scarduzio
2025-10-06 14:44:25 +02:00
parent 34c871b0d7
commit 9c1659a1f1
3 changed files with 61 additions and 10 deletions

View File

@@ -21,7 +21,6 @@ from .errors import (
IntegrityMismatchError,
NotFoundError,
PolicyViolationWarning,
StorageIOError,
)
from .models import (
DeltaMeta,
@@ -171,10 +170,28 @@ class DeltaService:
if obj_head is None:
raise NotFoundError(f"Object not found: {object_key.key}")
# Check if this is a regular S3 object (not uploaded via DeltaGlider)
# Regular S3 objects won't have DeltaGlider metadata
if "file_sha256" not in obj_head.metadata:
raise StorageIOError(f"Missing metadata on {object_key.key}")
# This is a regular S3 object, download it directly
self.logger.info(
"Downloading regular S3 object (no DeltaGlider metadata)",
key=object_key.key,
)
self._get_direct(object_key, obj_head, out)
duration = (self.clock.now() - start_time).total_seconds()
self.logger.log_operation(
op="get",
key=object_key.key,
deltaspace=f"{object_key.bucket}",
sizes={"file": obj_head.size},
durations={"total": duration},
cache_hit=False,
)
self.metrics.timing("deltaglider.get.duration", duration)
return
# Check if this is a direct upload (non-delta)
# Check if this is a direct upload (non-delta) uploaded via DeltaGlider
if obj_head.metadata.get("compression") == "none":
# Direct download without delta processing
self._get_direct(object_key, obj_head, out)