private void createMultipartUpload0(WriteOptions options, String path, CompletableFuture<String> cf) {
        TimerUtil timerUtil = new TimerUtil();
        doCreateMultipartUpload(options, path).thenAccept(uploadId -> {
            S3OperationStats.getInstance().createMultiPartUploadStats(true).record(timerUtil.elapsedAs(TimeUnit.NANOSECONDS));
            cf.complete(uploadId);
        }).exceptionally(ex -> {
            S3OperationStats.getInstance().createMultiPartUploadStats(false).record(timerUtil.elapsedAs(TimeUnit.NANOSECONDS));
            Pair<RetryStrategy, Throwable> strategyAndCause = toRetryStrategyAndCause(ex, S3Operation.CREATE_MULTI_PART_UPLOAD);
            RetryStrategy retryStrategy = strategyAndCause.getLeft();
            Throwable cause = strategyAndCause.getRight();
            if (retryStrategy == RetryStrategy.ABORT || checkS3ApiMode) {
                logger.error("CreateMultipartUpload for object {} fail", path, cause);
                cf.completeExceptionally(cause);
            } else {
                int delay = retryDelay(S3Operation.CREATE_MULTI_PART_UPLOAD, options.retryCountGetAndAdd());
                logger.warn("CreateMultipartUpload for object {} fail, retry in {}ms", path, delay, cause);
                scheduler.schedule(() -> createMultipartUpload0(options, path, cf), delay, TimeUnit.MILLISECONDS);
            }
            return null;
        });
    }
Put an object to the specified path.

@param options   options (or context) about the write operation
@param path      the path to put the object
@param data      the data to put, it will be released once the finalCf is done
@param attemptCf the CompletableFuture to complete when a single attempt is done
@param finalCf   the CompletableFuture to complete when the write operation is done
s3stream/src/main/java/com/automq/stream/s3/operator/AbstractObjectStorage.java