Skip to content

Commit 2181360

Browse files
authored
Skip listing MPUs if TTL set to -1 (elastic#127166)
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 elastic#122670
1 parent 874a697 commit 2181360

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

+7
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

+7-6
Original file line numberDiff line numberDiff line change
@@ -842,6 +842,11 @@ void run(BytesReference expected, BytesReference updated, ActionListener<Optiona
842842
* @return {@code true} if there are already ongoing uploads, so we should not proceed with the operation
843843
*/
844844
private boolean hasPreexistingUploads() {
845+
final var timeToLiveMillis = blobStore.getCompareAndExchangeTimeToLive().millis();
846+
if (timeToLiveMillis < 0) {
847+
return false; // proceed always
848+
}
849+
845850
final var uploads = listMultipartUploads();
846851
logUploads("preexisting uploads", uploads);
847852

@@ -850,11 +855,7 @@ private boolean hasPreexistingUploads() {
850855
return false;
851856
}
852857

853-
final var expiryDate = Date.from(
854-
Instant.ofEpochMilli(
855-
blobStore.getThreadPool().absoluteTimeInMillis() - blobStore.getCompareAndExchangeTimeToLive().millis()
856-
)
857-
);
858+
final var expiryDate = Date.from(Instant.ofEpochMilli(blobStore.getThreadPool().absoluteTimeInMillis() - timeToLiveMillis));
858859
if (uploads.stream().anyMatch(upload -> upload.getInitiated().after(expiryDate))) {
859860
logger.trace("[{}] fresh preexisting uploads vs {}", blobKey, expiryDate);
860861
return true;
@@ -929,7 +930,7 @@ private int getUploadIndex(String targetUploadId, List<MultipartUpload> multipar
929930
final var currentTimeMillis = blobStore.getThreadPool().absoluteTimeInMillis();
930931
final var ageMillis = currentTimeMillis - multipartUpload.getInitiated().toInstant().toEpochMilli();
931932
final var expectedAgeRangeMillis = blobStore.getCompareAndExchangeTimeToLive().millis();
932-
if (ageMillis < -expectedAgeRangeMillis || ageMillis > expectedAgeRangeMillis) {
933+
if (0 <= expectedAgeRangeMillis && (ageMillis < -expectedAgeRangeMillis || ageMillis > expectedAgeRangeMillis)) {
933934
logger.warn(
934935
"""
935936
compare-and-exchange of blob [{}:{}] was initiated at [{}={}] \

0 commit comments

Comments
 (0)