Details
-
Improvement
-
Resolution: Unresolved
-
Major
-
None
-
17.10.0
-
None
-
Unknown
-
Description
Problem
XCOMMONS-3823 lets the S3 blob store work with S3-compatible services that don't support some conditional requests, through two configuration properties, store.s3.conditionalWrites (the conditions of uploads and multipart copies) and store.s3.conditionalCopies (the condition of the single-request copy), both true by default. The administrator has to know which conditions the service supports, and finds out through a "501 Not Implemented" error. A service that silently ignores If-None-Match gives no signal at all: with the defaults, BlobWriteMode.CREATE_NEW then relies only on the existence check that precedes the write, which is not atomic.
Proposal
Accept auto as a value of these properties and probe the service once per store (bucket and key prefix), lazily at the first CREATE_NEW write or when the store is created:
- PUT a random key under a dedicated prefix (for example <prefix>/.xwiki-conditional-probe/<uuid>) with If-None-Match: *: expect 200.
- PUT the same key again with the same condition: expect 412. Anything else means that the condition is not supported or is ignored.
- Copy it with a single CopyObject request to a second random key with If-None-Match: *: 200 means supported, 501 means not supported.
- Optionally: CreateMultipartUpload, UploadPartCopy with a wrong x-amz-copy-source-if-match (expect 412), then AbortMultipartUpload.
- Delete both keys.
This is about 5 to 8 requests per store and node start. A probe limited to PutObject is not enough: some services support conditions on uploads and reject them on CopyObject. Measured on OVHcloud Object Storage (eu-west-par) on 2026-10-12:
| Operation | Condition | Answer |
|---|---|---|
| PutObject | If-None-Match: *, key absent / present | 200 / 412 (also exactly one success out of 8 concurrent PUTs of the same new key, three runs) |
| CompleteMultipartUpload | If-None-Match: *, key present / absent | 412 / 200 |
| UploadPartCopy | x-amz-copy-source-if-match, right / wrong ETag | 200 / 412 |
| CopyObject | x-amz-copy-source-if-match, x-amz-copy-source-if-none-match or If-None-Match | 501 Not Implemented |
| CopyObject | no condition | 200 |
Limits to handle
- Transient errors (5xx, SlowDown, network) give no answer: retry, then keep the configured value and log it. Never fall back silently to the non-atomic mode.
- A node that stops between the PUT and the DELETE leaves small objects under the probe prefix (a lifecycle rule can remove them).
- Versioned or object-lock buckets keep versions or delete markers of the probe objects.
- A change of the service's behaviour (upgrade) is only seen at the next start.
- The probe proves that a condition is evaluated, not that it is enforced atomically under concurrency.
Configuration
The xwiki.properties values become true, false or auto, while S3BlobStoreProperties keeps booleans resolved by the factory, so no API change is needed. Whether auto should become the default is to be decided here.
Related ideas
- Cheaper, partial alternative for copies: when a conditional CopyObject is answered with 501 (which guarantees that nothing was written), retry it once without the condition and remember the answer for the store.
- Atomic CREATE_NEW copies on services that reject conditions on CopyObject but support them on multipart uploads: perform such copies as a one-part multipart copy (CreateMultipartUpload, UploadPartCopy with the source ETag precondition, CompleteMultipartUpload with If-None-Match: *). This was measured to work on OVHcloud Object Storage (one part of a small object, and two ranged parts of a 6 MiB object). It costs two more requests per copy and move.
Suggested during the review of the pull request of XCOMMONS-3823.
Attachments
Issue Links
- relates to
-
XCOMMONS-3823 Allow using the S3 blob store with services that don't support conditional writes
-
- Closed
-