Skip to content

S3 compareAndExchange using conditional writes#139228

Merged
mhl-b merged 9 commits intoelastic:mainfrom
mhl-b:s3-cas
Dec 15, 2025
Merged

S3 compareAndExchange using conditional writes#139228
mhl-b merged 9 commits intoelastic:mainfrom
mhl-b:s3-cas

Conversation

@mhl-b
Copy link
Contributor

@mhl-b mhl-b commented Dec 9, 2025

Add support for S3 compareAndExchange using conditional writes. Also relax constrain on repository analysis using strict check on conditional writes. If unsafely_incompatible_with_s3_conditional_writes is set, repository analysis will use MPU for CAS operations.

Copy link
Contributor

@DaveCTurner DaveCTurner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implementation looks good, just a question around exposing this choice to users.

I think we need another AbstractS3RepositoryAnalysisRestTestCase subclass because there's now 3 valid configurations we should be testing:

  • S3ConsistencyModel.AWS_DEFAULT with MPU dance
  • S3ConsistencyModel.STRONG_MPUS with MPU dance
  • S3ConsistencyModel.AWS_DEFAULT with new conditional PutObject
key,
blobStore.getThreadPool()
).run(expected, updated, ActionListener.releaseBefore(clientReference, listener));
if (blobStore.supportsConditionalWrites(purpose)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need a different config option to explicitly choose between the two implementations. Both are safe (assuming the underlying storage behaves correctly) and we want repo analysis to test the one the user actually uses, but supportsConditionalWrites(REPOSITORY_ANALYSIS) is always true so it'll never run analysis on the MPU dance.

@mhl-b mhl-b added >enhancement :Distributed/Snapshot/Restore Anything directly related to the `_snapshot/*` APIs Team:Distributed Coordination (obsolete) Meta label for Distributed Coordination team. Obsolete. Please do not use. labels Dec 11, 2025
@elasticsearchmachine
Copy link
Collaborator

Hi @mhl-b, I've created a changelog YAML for you.

@mhl-b mhl-b marked this pull request as ready for review December 12, 2025 04:30
@elasticsearchmachine
Copy link
Collaborator

Pinging @elastic/es-distributed-coordination (Team:Distributed Coordination)

@mhl-b mhl-b requested review from DaveCTurner, nicktindall and pxsalehi and removed request for nicktindall and pxsalehi December 12, 2025 16:14
public void testMPUCompareAndExchangeCleanup() throws IOException {
final var repoMetadata = node().injector().getInstance(RepositoriesService.class).repository(TEST_REPO_NAME).getMetadata();
final var useCasMpu = repoMetadata.settings().getAsBoolean("unsafely_incompatible_with_s3_conditional_writes", false);
assumeTrue("repository supports condtional-writes and does not use MPU for CAS", useCasMpu);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes me uneasy - are you sure this test ever runs now? I think we might just be muting this test.

The third-party tests are for running against the real S3, where this no longer makes sense, so maybe we should move this into a test suite that simply uses the fixture.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added random conditionals-support to third-party test. 7ebf258#diff-bc0de3c4b793cf718dd897c7f9a855a1a5f1a890b7f18755b4ed2d7a57ad3de9

testMPUCompareAndExchangeCleanup does not require strong consistency so it's ok to run against S3 and MinIO, as long as unsafely_incompatible_with_s3_conditional_writes is set. But testFailIfAlreadyExists does rely on conditionals, so I updated that test assumption too.

I think it's ok to mark specific test "not-safe" using assumptions. With this change we don't lost coverage, but test frequency.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another approach, I think a better one, to pass optional consistency model to "createRepository" method in every test. Without explicit argument it's random, otherwise fixed.

// if register was deleted, return ABSENT(BytesArray.EMPTY)
return OptionalBytesReference.of(regEtag.registerContents());
} else {
final var condtionalOperaiton = regEtag == RegisterAndEtag.ABSENT
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo nit

Suggested change
final var condtionalOperaiton = regEtag == RegisterAndEtag.ABSENT
final var condtionalOperation = regEtag == RegisterAndEtag.ABSENT
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is another one :) missed "i" after "cond". My French is failing me

@@ -119,7 +121,7 @@ protected Settings repositorySettings() {
// verify we always set the x-purpose header even if disabled for other repository operations
.put(randomBooleanSetting("add_purpose_custom_query_parameter"))
// this parameter is ignored for repo analysis
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: comment no longer applies

Suggested change
// this parameter is ignored for repo analysis
@mhl-b mhl-b requested a review from DaveCTurner December 13, 2025 01:49
Copy link
Contributor

@DaveCTurner DaveCTurner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@mhl-b mhl-b enabled auto-merge (squash) December 15, 2025 17:29
@mhl-b mhl-b merged commit 2074dc4 into elastic:main Dec 15, 2025
35 checks passed
parkertimmins pushed a commit to parkertimmins/elasticsearch that referenced this pull request Dec 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

:Distributed/Snapshot/Restore Anything directly related to the `_snapshot/*` APIs >enhancement Team:Distributed Coordination (obsolete) Meta label for Distributed Coordination team. Obsolete. Please do not use. v9.3.0

3 participants