Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PERF] Optimize PublicAsset create by using S3 copy object api #1128

Open
vttranlina opened this issue Jul 16, 2024 · 3 comments
Open

[PERF] Optimize PublicAsset create by using S3 copy object api #1128

vttranlina opened this issue Jul 16, 2024 · 3 comments

Comments

@vttranlina
Copy link
Member

Why?

ref: #1061

Requirement

linagora/james-project#5222

How

Introduce BlobStoreToolBox interface

public interface BlobStoreToolBox {
    Mono<BlobId> copyBlob(BlobId blobId, BucketName sourceBucket, BucketName targetBucket);
}
  • The S3 implement looks like:
public class S3BlobStoreToolBox implements BlobStoreToolBox {
    private final S3AsyncClient s3Client;
    @Override
    public Mono<BlobId> copyBlob(BlobId blobId, BucketName sourceBucket, BucketName targetBucket) {
        return Mono.fromFuture(s3Client.copyObject(CopyObjectRequest.builder()
                .sourceBucket(sourceBucket.asString())
                .sourceKey(blobId.asString())
                .destinationBucket(targetBucket.asString())
                .destinationKey(blobId.asString())
                .build()))
            .publishOn(Schedulers.parallel())
            .thenReturn(blobId);
    }
}
  • For another implement
public class NaiveBlobStoreToolbox implements BlobStoreToolBox {
    private final BlobStore blobStore;
    @Override
    public Mono<BlobId> copyBlob(BlobId blobId, BucketName sourceBucket, BucketName targetBucket) {
        return Mono.from(blobStore.readBytes(sourceBucket, blobId))
            .flatMap(bytes -> Mono.from(blobStore.save(targetBucket, bytes, BlobStore.StoragePolicy.LOW_COST)));
    }
}

Location: tmail-backend/blob/blob-extensions

Adapt PublicAssetSetMethod

Currently, we are using blobResolvers to resolve creationRequest.blobId. I propose that we use UploadRepository directly to retrieve UploadMetaData.

Impact scope:

  • The blobId in the client request must have the prefix uploads-.
  • We can add a new API Publisher<UploadMetaData> listUploads(Username user, UploadId id) to UploadRepository, or use listUploads directly and filter UploadMetaData (in case the upload size for each user is not large).
  • Update the PublicAssetCreationRequest POJO by adding blobId and bucketName field, and removing content field:
case class PublicAssetCreationRequest(size: Size,
                                      contentType: ImageContentType,
                                      identityIds: Seq[IdentityId] = Seq.empty,
                                      blobId: BlobId,
                                      bucketName: BucketName)

Inject BlobStoreToolBox into PublicAssetRepository and use the copyBlob API.

Guice binding

  • using S3BlobStoreToolBox for S3blob store chooser
  • using NaiveBlobStoreToolbox for other remain
@chibenwa
Copy link
Member

I think creating public asset will be very rare.
I am expecting the gains of such an optimization to be low.
Also it breaks encapsulation and hard code the use of the blobStore which in terms of design do not seem desirable.

@vttranlina
Copy link
Member Author

honestly, when writing a ticket, I have a bit similar thought

@vttranlina
Copy link
Member Author

any thing other idea from team? if not, I will close it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants