public int numRecords() {
        return numRecords;
    }
There are three cases of finding max timestamp to return:
1) version 0: The max timestamp is NO_TIMESTAMP (-1)
2) LogAppendTime: All records have same timestamp, and so the max timestamp is equal to logAppendTime
3) CreateTime: The max timestamp of record
<p>
Let's talk about OffsetOfMaxTimestamp. There are some paths that we don't try to find the OffsetOfMaxTimestamp
to avoid expensive records iteration. Those paths include follower append and index recovery. In order to
avoid inconsistent time index, we let all paths find shallowOffsetOfMaxTimestamp instead of OffsetOfMaxTimestamp.
<p>
Let's define the shallowOffsetOfMaxTimestamp: It is last offset of the batch having max timestamp. If there are
many batches having same max timestamp, we pick up the earliest batch.
<p>
There are five cases of finding shallowOffsetOfMaxTimestamp to return:
1) version 0: It is always the -1
2) LogAppendTime with single batch: It is the offset of last record
3) LogAppendTime with many single-record batches: Those single-record batches have same max timestamp, so we return
                                                  the base offset, which is equal to the last offset of earliest batch
4) CreateTime with single batch: We return offset of last record to follow the spec we mentioned above. Of course,
                                 we do have the OffsetOfMaxTimestamp for this case, but we want to make all paths
                                 find the shallowOffsetOfMaxTimestamp rather than offsetOfMaxTimestamp
5) CreateTime with many single-record batches: Each batch is composed of single record, and hence offsetOfMaxTimestamp
                                               is equal to the last offset of earliest batch with max timestamp
clients/src/main/java/org/apache/kafka/common/record/MemoryRecordsBuilder.java