Skip to content

Commit 96f32bc

Browse files
authored
Skip listing MPUs if TTL set to -1 (#127166) (#127206)
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 5ab5426 commit 96f32bc

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
@@ -701,6 +701,11 @@ void run(BytesReference expected, BytesReference updated, ActionListener<Optiona
701701
* @return {@code true} if there are already ongoing uploads, so we should not proceed with the operation
702702
*/
703703
private boolean hasPreexistingUploads() {
704+
final var timeToLiveMillis = blobStore.getCompareAndExchangeTimeToLive().millis();
705+
if (timeToLiveMillis < 0) {
706+
return false; // proceed always
707+
}
708+
704709
final var uploads = listMultipartUploads();
705710
logUploads("preexisting uploads", uploads);
706711

@@ -709,11 +714,7 @@ private boolean hasPreexistingUploads() {
709714
return false;
710715
}
711716

712-
final var expiryDate = Date.from(
713-
Instant.ofEpochMilli(
714-
blobStore.getThreadPool().absoluteTimeInMillis() - blobStore.getCompareAndExchangeTimeToLive().millis()
715-
)
716-
);
717+
final var expiryDate = Date.from(Instant.ofEpochMilli(blobStore.getThreadPool().absoluteTimeInMillis() - timeToLiveMillis));
717718
if (uploads.stream().anyMatch(upload -> upload.getInitiated().after(expiryDate))) {
718719
logger.trace("[{}] fresh preexisting uploads vs {}", blobKey, expiryDate);
719720
return true;
@@ -788,7 +789,7 @@ private int getUploadIndex(String targetUploadId, List<MultipartUpload> multipar
788789
final var currentTimeMillis = blobStore.getThreadPool().absoluteTimeInMillis();
789790
final var ageMillis = currentTimeMillis - multipartUpload.getInitiated().toInstant().toEpochMilli();
790791
final var expectedAgeRangeMillis = blobStore.getCompareAndExchangeTimeToLive().millis();
791-
if (ageMillis < -expectedAgeRangeMillis || ageMillis > expectedAgeRangeMillis) {
792+
if (0 <= expectedAgeRangeMillis && (ageMillis < -expectedAgeRangeMillis || ageMillis > expectedAgeRangeMillis)) {
792793
logger.warn(
793794
"""
794795
compare-and-exchange of blob [{}:{}] was initiated at [{}={}] \

0 commit comments

Comments
 (0)