protected static CompletableFuture<Void> deleteWithCompositeObjectReader(
        S3ObjectMetadata objectMetadata,
        ObjectStorage objectStorage,
        CompositeObjectReader reader) {
        return reader.basicObjectInfo().thenCompose(info -> {
            // 2. delete linked object
            List<CompositeObjectReader.ObjectIndex> objectIndexes = ((CompositeObjectReader.BasicObjectInfoExt) info).objectsBlock().indexes();
            List<ObjectPath> objectPaths = objectIndexes
                .stream()
                .map(o -> new ObjectPath(o.bucketId(), ObjectUtils.genKey(0, o.objectId())))
                .collect(Collectors.toList());
            return objectStorage.delete(objectPaths)
                .thenApply(rst -> objectIndexes.stream().map(o -> o.bucketId() + "/" + o.objectId()).collect(Collectors.toList()));
        }).thenCompose(linkedObjects -> {
            // 3. delete composite object
            return objectStorage.delete(List.of(new ObjectPath(objectMetadata.bucket(), objectMetadata.key()))).thenAccept(rst ->
                LOGGER.info("Delete composite object {}/{} success, linked objects: {}",
                    ObjectAttributes.from(objectMetadata.attributes()).bucket(), objectMetadata.objectId(), linkedObjects)
            );
        }).thenAccept(rst -> {
        }).exceptionally(ex -> {
            Throwable cause = FutureUtil.cause(ex);
            if (cause instanceof ObjectNotExistException) {
                // The composite object is already deleted.
                return null;
            }
            throw new CompletionException(cause);
        });
    }
CompositeObject is a logic object which soft links multiple objects together.
<p>
v0 format:
objects
object_count u32
objects (
object_id u64
block_start_index u32
bucket_index u16
)*
indexes
index_count u32
(
stream_id u64
start_offset u64
end_offset_delta u32
record_count u32
block_start_position u64
block_size u32
)*
index_handle
position u64
length u32
padding 40byte - 8 - 8 - 4
magic u64
s3stream/src/main/java/com/automq/stream/s3/CompositeObject.java