Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/modules/servers/partials/configure/blobstore.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ Unless a special case like storing blobs of deleted messages.
| objectstorage.namespace.read.fallback
| BlobStore fallback bucket name. Allows to fallback to a previous used bucket when blob is missing from the default one.
It can be useful when migrating blobs to a new bucket for example.
This is a read only fallback: James never writes to, nor deletes from, that bucket.
This bucket name is used as is: `objectstorage.bucketPrefix` is not applied to it.
|===

==== SSE-C Configuration
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ cache.sizeThresholdInBytes=16 KiB
objectstorage.namespace=james-${env:JAMES_BUCKET_SUFFIX}

# Fallback bucket name
# Optional, read this bucket when default bukcket reads fails if configured
# Optional, read this bucket when reads on the default bucket fail, if configured.
# This is a read only fallback: blobs are never written to nor deleted from this bucket.
# Note: this name is used as is, `objectstorage.bucketPrefix` is not applied to it.
# objectstorage.namespace.read.fallback=james-fallback

# ========================================= ObjectStorage on S3 =============================================
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,9 @@ cache.enable=false
# objectstorage.namespace=james

# Fallback bucket name
# Optional, read this bucket when default bukcket reads fails if configured
# Optional, read this bucket when reads on the default bucket fail, if configured.
# This is a read only fallback: blobs are never written to nor deleted from this bucket.
# Note: this name is used as is, `objectstorage.bucketPrefix` is not applied to it.
# objectstorage.namespace.read.fallback=james-fallback

# ========================================= ObjectStorage on S3 =============================================
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ cache.enable=false
# objectstorage.namespace=james

# Fallback bucket name
# Optional, read this bucket when default bukcket reads fails if configured
# Optional, read this bucket when reads on the default bucket fail, if configured.
# This is a read only fallback: blobs are never written to nor deleted from this bucket.
# Note: this name is used as is, `objectstorage.bucketPrefix` is not applied to it.
# objectstorage.namespace.read.fallback=james-fallback

# ========================================= ObjectStorage on S3 =============================================
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ encryption.aes.enable=false
# objectstorage.namespace=james

# Fallback bucket name
# Optional, read this bucket when default bukcket reads fails if configured
# Optional, read this bucket when reads on the default bucket fail, if configured.
# This is a read only fallback: blobs are never written to nor deleted from this bucket.
# Note: this name is used as is, `objectstorage.bucketPrefix` is not applied to it.
# objectstorage.namespace.read.fallback=james-fallback

# ========================================= ObjectStorage on S3 =============================================
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,9 @@ cache.enable=false
# objectstorage.namespace=james

# Fallback bucket name
# Optional, read this bucket when default bukcket reads fails if configured
# Optional, read this bucket when reads on the default bucket fail, if configured.
# This is a read only fallback: blobs are never written to nor deleted from this bucket.
# Note: this name is used as is, `objectstorage.bucketPrefix` is not applied to it.
# objectstorage.namespace.read.fallback=james-fallback

# ========================================= ObjectStorage on S3 =============================================
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,7 @@ private Mono<FluxResponse> getObject(BucketName bucketName, BlobId blobId) {
return getObjectFromStore(bucketName, blobId)
.onErrorResume(e -> e instanceof NoSuchKeyException || e instanceof NoSuchBucketException, e -> {
if (fallbackNamespace.isPresent() && bucketNameResolver.isNameSpace(bucketName)) {
BucketName resolvedFallbackBucketName = bucketNameResolver.resolve(fallbackNamespace.get());
return getObjectFromStore(resolvedFallbackBucketName, blobId);
return getObjectFromStore(fallbackNamespace.get(), blobId);
}
return Mono.error(e);
});
Expand Down Expand Up @@ -229,8 +228,7 @@ private Mono<ResponseBytes<GetObjectResponse>> getObjectBytes(BucketName bucketN
return getObjectBytesFromStore(bucketName, blobId)
.onErrorResume(e -> e instanceof NoSuchKeyException || e instanceof NoSuchBucketException, e -> {
if (fallbackNamespace.isPresent() && bucketNameResolver.isNameSpace(bucketName)) {
BucketName resolvedFallbackBucketName = bucketNameResolver.resolve(fallbackNamespace.get());
return getObjectBytesFromStore(resolvedFallbackBucketName, blobId);
return getObjectBytesFromStore(fallbackNamespace.get(), blobId);
}
return Mono.error(e);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,30 @@ void readBytesShouldFallbackToDefinedBucketWhenFailingOnDefaultOne() {
assertThat(bytes).isEqualTo(ELEVEN_KILOBYTES);
}

@Test
void fallbackBucketNameShouldNotBeAffectedByBucketPrefix(DockerAwsS3Container dockerAwsS3) {
S3BlobStoreConfiguration prefixedConfiguration = S3BlobStoreConfiguration.builder()
.authConfiguration(AwsS3AuthConfiguration.builder()
.endpoint(dockerAwsS3.getEndpoint())
.accessKeyId(DockerAwsS3Container.ACCESS_KEY_ID)
.secretKey(DockerAwsS3Container.SECRET_ACCESS_KEY)
.build())
.region(dockerAwsS3.dockerAwsS3().region())
.defaultBucketName(BucketName.DEFAULT)
.bucketPrefix("prefix-")
.fallbackBucketName(Optional.of(fallbackBucket))
.build();
S3BlobStoreDAO prefixedStore = new S3BlobStoreDAO(s3ClientFactory, prefixedConfiguration, new TestBlobId.Factory(), S3RequestOption.DEFAULT);

TestBlobId blobId = new TestBlobId("id");
// Save in the un-prefixed fallback bucket
Mono.from(testee.save(fallbackBucket, blobId, ELEVEN_KILOBYTES)).block();

InputStream read = prefixedStore.read(BucketName.DEFAULT, blobId).payload();

assertThat(read).hasSameContentAs(ELEVEN_KILOBYTES.asInputStream().payload());
}

@Test
void shouldNotReadOnFallbackBucketWhenNotReadingOnDefaultOne() {
BlobStoreDAO store = testee();
Expand Down