fix: Add .delta suffix fallback for delete_object()

- delete_object() now tries with .delta suffix if file not found
- Matches the same fallback logic as download/get_object
- Fixes deletion of files uploaded as .delta when user provides original name
- Add test for delta suffix fallback in deletion

This fixes the critical bug where delete_object(Key='file.zip') would fail
with NotFoundError when the actual file was stored as 'file.zip.delta'.

Now delete_object() works consistently with get_object():
- Try with key as provided
- If NotFoundError and no .delta suffix, try with .delta appended
- Raises NotFoundError only if both attempts fail

🤖 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 23:05:51 +02:00
parent 9c1659a1f1
commit 0064d7e74b
2 changed files with 30 additions and 3 deletions

View File

@@ -8,6 +8,7 @@ from typing import Any
from .adapters.storage_s3 import S3StorageAdapter
from .core import DeltaService, DeltaSpace, ObjectKey
from .core.errors import NotFoundError
@dataclass
@@ -427,15 +428,23 @@ class DeltaGliderClient:
Args:
Bucket: S3 bucket name
Key: Object key
Key: Object key (can be with or without .delta suffix)
**kwargs: Additional parameters
Returns:
Response dict with deletion details
"""
# Use core service's delta-aware delete
# Try to delete with the key as provided
object_key = ObjectKey(bucket=Bucket, key=Key)
delete_result = self.service.delete(object_key)
try:
delete_result = self.service.delete(object_key)
except NotFoundError:
# Try with .delta suffix if not already present
if not Key.endswith(".delta"):
object_key = ObjectKey(bucket=Bucket, key=Key + ".delta")
delete_result = self.service.delete(object_key)
else:
raise
response = {
"DeleteMarker": False,

View File

@@ -311,6 +311,24 @@ class TestBoto3Compatibility:
assert response["ResponseMetadata"]["HTTPStatusCode"] == 204
assert "test-bucket/to-delete.txt" not in client.service.storage.objects
def test_delete_object_with_delta_suffix_fallback(self, client):
"""Test delete_object with automatic .delta suffix fallback."""
# Add object with .delta suffix (as DeltaGlider stores it)
client.service.storage.objects["test-bucket/file.zip.delta"] = {
"size": 100,
"metadata": {
"original_name": "file.zip",
"compression": "delta",
},
}
# Delete using original name (without .delta)
response = client.delete_object(Bucket="test-bucket", Key="file.zip")
assert response["ResponseMetadata"]["HTTPStatusCode"] == 204
assert response["DeltaGliderInfo"]["Deleted"] is True
assert "test-bucket/file.zip.delta" not in client.service.storage.objects
def test_delete_objects(self, client):
"""Test batch delete."""
# Add objects