private CompletableFuture<Long> getStartStreamSetObjectId(int nodeId, long startOffset, GetObjectsContext ctx) {
        if (ctx.indexCache != null && ctx.indexCache.nodeId() == nodeId) {
            return ctx.indexCache.searchObjectId(ctx.streamId, startOffset);
        }
        // search from cache and refresh the cache from remote if necessary
        return NodeRangeIndexCache.getInstance().searchObjectId(nodeId, ctx.streamId, startOffset,
            () -> ctx.rangeGetter.readNodeRangeIndex(nodeId).thenApply(buff -> {
                try {
                    return LocalStreamRangeIndexCache.fromBuffer(buff);
                } finally {
                    buff.release();
                }
            }));
    }
Get the object id of the first stream set object to start search from.
Possible results:
<p>
a. -1, no stream set object can be found, this can happen when index cache is not exist or is invalidated,
searching should be done from the beginning of the objects in this case.
<p>
b. non-negative value:
1. the object exists in stream set objects in node image, search should start from that object
2. the object does not exist in stream set objects in node image, that means the index cache is out of date and
should be invalidated, so we can refresh the index from object storage next time
metadata/src/main/java/org/apache/kafka/image/S3StreamsMetadataImage.java