feat(s3): add object annotations support - #3324
Conversation
PutObjectAnnotation, GetObjectAnnotation, ListObjectAnnotations, DeleteObjectAnnotation via the ?annotation subresource, with per-version storage, x-amz-annotation-directive on CopyObject, s3:ObjectAnnotation:* notifications, and x-amz-object-if-match.
|
| Filename | Overview |
|---|---|
| src/main/java/io/github/hectorvent/floci/services/s3/S3Service.java | Implements annotation lifecycle, storage, versioning, checksums, copy semantics, cleanup, locking, and event delivery; the latest monitor-resolution fix preserves cross-account copy behavior. |
| src/main/java/io/github/hectorvent/floci/services/s3/S3Controller.java | Adds REST-XML routing, request validation, response generation, authorization, checksum handling, and CloudTrail emission for annotation operations. |
| src/main/java/io/github/hectorvent/floci/services/s3/model/ObjectAnnotation.java | Defines persisted annotation identity, metadata, checksum, encryption, and payload-location fields. |
| compatibility-tests/sdk-test-java/src/test/java/com/floci/test/S3AnnotationsTest.java | Exercises annotation operations through the AWS SDK and now logs tolerated teardown failures with diagnostic context. |
| src/test/java/io/github/hectorvent/floci/services/s3/S3AnnotationsIntegrationTest.java | Covers REST-level annotation behavior and compatibility constraints. |
| src/test/java/io/github/hectorvent/floci/services/s3/S3ServiceAnnotationsTest.java | Covers service-level annotation storage, versioning, copying, cleanup, limits, and concurrency behavior. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart LR
Client[AWS SDK or CLI] --> Controller[S3 REST-XML controller]
Controller --> Auth[IAM authorization]
Auth --> Service[S3 service]
Service --> ObjectStore[Object metadata and body]
Service --> AnnotationStore[Annotation metadata]
Service --> PayloadStore[Annotation payload blobs]
Service --> Events[Notifications and CloudTrail]
ObjectStore --> Copy[CopyObject]
AnnotationStore --> Copy
PayloadStore --> Copy
Reviews (3): Last reviewed commit: "fix(s3): lock cross-account copy buckets..." | Re-trigger Greptile
… payloads on reset
…mpat test cleanup
Summary
Adds S3 Object Annotations: named UTF-8 payloads (1 B to 1 MiB, up to 1,000 per object version) attached to object versions without re-uploading the object, matching the AWS annotations API. Closes #3239.
?annotationsubresource (REST XML), includingx-amz-object-if-match,x-amz-checksum-mode, checksum validation, and pagination with continuation tokensx-amz-annotation-directive: COPY | EXCLUDEs3:ObjectAnnotation:Put/s3:ObjectAnnotation:Deletenotification events and CloudTrail events; IAM actions enforced when auth is enableds3-annotations.jsonstore; payload bytes as.s3annblobs (object-body pattern), keeping payloads out of the single-document serialization of the metadata storesKnown follow-ups (not in this PR): S3 Metadata annotation tables, annotation replication, XXH*/SHA512/MD5 checksum algorithms, O(total-annotations) scan on annotation-heavy stores, and the residual non-atomicity window between annotation cleanup and the replacement metadata publish on overwrite. Note: DeleteObject now takes the bucket monitor, so notification delivery serializes with other writes on the same bucket.
Type of change
fix:)feat:)feat!:orfix!:)AWS Compatibility
Verified against AWS SDK for Java v2 2.52.0 (compat suite,
S3AnnotationsTest, 11/11 passingagainst a running Floci container): SDK round-trips for put/get/list/delete-object-annotation, checksum headers with
checksumMode(ENABLED), aws-chunked/streaming-trailer PUT framing, the modeledNoSuchAnnotationException, versioned-bucket per-version attachment, and thex-amz-object-annotation-directiveCOPY/EXCLUDE directive on CopyObject (the real header name, which this PR also accepts alongside thex-amz-annotation-directivespelling).Verified with AWS CLI 2.36.41: put/get/list/delete-object-annotation round-trip, including
the CRC64NVME default checksum. The existing
S3Testcompat suite still passes.Checklist
./mvnw testpasses locally