Skip to content

Commit c2e1a31

Browse files
authored
Skip listing MPUs if TTL set to -1 (#127166) (#127205)
Recent versions of MinIO will sometimes leak multi-part uploads under concurrent load, leaving them in the `ListMultipartUploads` output even though they cannot be aborted. Today this causes repository analysis to fail since compare-and-exchange operations will not even start if there are any pre-existing uploads. This commit makes it possible to skip this pre-flight check (and accept the performance consequences) by adjusting the relevant settings. Workaround for minio/minio#21189 Closes #122670
1 parent 1698956 commit c2e1a31

File tree

2 files changed

+14
-6
lines changed

2 files changed

+14
-6
lines changed

modules/repository-s3/src/javaRestTest/java/org/elasticsearch/repositories/s3/RepositoryS3MinioBasicCredentialsRestIT.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121

2222
import java.util.Locale;
2323

24+
import static org.elasticsearch.repositories.s3.S3Service.REPOSITORY_S3_CAS_ANTI_CONTENTION_DELAY_SETTING;
25+
import static org.elasticsearch.repositories.s3.S3Service.REPOSITORY_S3_CAS_TTL_SETTING;
26+
2427
@ThreadLeakFilters(filters = { TestContainersThreadFilter.class })
2528
@ThreadLeakScope(ThreadLeakScope.Scope.NONE) // https://github.com/elastic/elasticsearch/issues/102482
2629
public class RepositoryS3MinioBasicCredentialsRestIT extends AbstractRepositoryS3RestTestCase {
@@ -39,6 +42,10 @@ public class RepositoryS3MinioBasicCredentialsRestIT extends AbstractRepositoryS
3942
.keystore("s3.client." + CLIENT + ".access_key", ACCESS_KEY)
4043
.keystore("s3.client." + CLIENT + ".secret_key", SECRET_KEY)
4144
.setting("s3.client." + CLIENT + ".endpoint", minioFixture::getAddress)
45+
// Skip listing of pre-existing uploads during a CAS because MinIO sometimes leaks them; also reduce the delay before proceeding
46+
// TODO do not set these if running a MinIO version in which https://github.com/minio/minio/issues/21189 is fixed
47+
.setting(REPOSITORY_S3_CAS_TTL_SETTING.getKey(), "-1")
48+
.setting(REPOSITORY_S3_CAS_ANTI_CONTENTION_DELAY_SETTING.getKey(), "100ms")
4249
.build();
4350

4451
@ClassRule

modules/repository-s3/src/main/java/org/elasticsearch/repositories/s3/S3BlobContainer.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,11 @@ void run(BytesReference expected, BytesReference updated, ActionListener<Optiona
686686
* @return {@code true} if there are already ongoing uploads, so we should not proceed with the operation
687687
*/
688688
private boolean hasPreexistingUploads() {
689+
final var timeToLiveMillis = blobStore.getCompareAndExchangeTimeToLive().millis();
690+
if (timeToLiveMillis < 0) {
691+
return false; // proceed always
692+
}
693+
689694
final var uploads = listMultipartUploads();
690695
logUploads("preexisting uploads", uploads);
691696

@@ -694,11 +699,7 @@ private boolean hasPreexistingUploads() {
694699
return false;
695700
}
696701

697-
final var expiryDate = Date.from(
698-
Instant.ofEpochMilli(
699-
blobStore.getThreadPool().absoluteTimeInMillis() - blobStore.getCompareAndExchangeTimeToLive().millis()
700-
)
701-
);
702+
final var expiryDate = Date.from(Instant.ofEpochMilli(blobStore.getThreadPool().absoluteTimeInMillis() - timeToLiveMillis));
702703
if (uploads.stream().anyMatch(upload -> upload.getInitiated().after(expiryDate))) {
703704
logger.trace("[{}] fresh preexisting uploads vs {}", blobKey, expiryDate);
704705
return true;
@@ -773,7 +774,7 @@ private int getUploadIndex(String targetUploadId, List<MultipartUpload> multipar
773774
final var currentTimeMillis = blobStore.getThreadPool().absoluteTimeInMillis();
774775
final var ageMillis = currentTimeMillis - multipartUpload.getInitiated().toInstant().toEpochMilli();
775776
final var expectedAgeRangeMillis = blobStore.getCompareAndExchangeTimeToLive().millis();
776-
if (ageMillis < -expectedAgeRangeMillis || ageMillis > expectedAgeRangeMillis) {
777+
if (0 <= expectedAgeRangeMillis && (ageMillis < -expectedAgeRangeMillis || ageMillis > expectedAgeRangeMillis)) {
777778
logger.warn(
778779
"""
779780
compare-and-exchange of blob [{}:{}] was initiated at [{}={}] \

0 commit comments

Comments
 (0)