prosgarz35 opened a new pull request, #3201:
URL: https://github.com/apache/james-project/pull/3201
### Title:
JAMES-4223 Default S3 If-None-Match to true to prevent silent blob
overwrite
### Summary of Changes:
1. **Change default setting**: Set `ifNoneMatchEnabled` default value to
`true` in both S3BlobStoreConfiguration.Builder and
S3BlobStoreConfigurationReader.
2. **Preserve full backward compatibility**: Deployments where the
underlying S3 provider does not support conditional writes can explicitly opt
out by setting `objectstorage.s3.ifNoneMatch.enable=false`.
3. **Tests**:
- Added unit test to verify `S3BlobStoreConfiguration` defaults
`ifNoneMatchEnabled` to `true`.
- Added unit test to verify `S3BlobStoreConfigurationReader` respects
default (`true`) and explicit opt-out (`false`).
- Added unit test in `S3BlobStoreDAOIfNoneMatchTest` ensuring retries
on `409 ConditionalRequestConflict` work properly for `save(ByteSource)`.
---
### Motivation & Rationale:
#### 1. Why is this critical?
In James, blobs in `BlobStore` are content-addressed by their SHA-256
hash. When conditional writes (`If-None-Match: *`) were disabled by default:
- Concurrent uploads of the same blob (e.g. multi-recipient incoming
emails, shared attachments, or concurrent deduplication jobs) result in
parallel blind `PutObject` calls overwriting the same S3 object.
- If one writer is preempted, times out, or fails halfway, it can
overwrite or truncate a healthy blob written by another process.
- Blind overwriting also creates unnecessary write IOPS, S3 PUT request
costs, and race conditions between concurrent readers/writers.
#### 2. How `If-None-Match: *` solves this:
- When writing a blob that already exists or is being concurrently
written:
- S3 responds with `412 PreconditionFailed` (if the object already
exists), which James cleanly handles as a successful write without payload
upload (`isAlreadyStored`).
- S3 responds with `409 ConditionalRequestConflict` (if another write
is actively in flight), which triggers bounded retry in James until the object
is created and subsequent check returns `412` (success).
- This guarantees idempotency and complete immunity to silent overwrite
races out of the box for standard S3 (AWS S3, Ceph, MinIO, GCP Storage S3 API).
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]