Skip to content

KAFKA-20132: Implement TimestampedKeyValueStoreWithHeaders (2/N)#21446

Open
aliehsaeedii wants to merge 15 commits intoapache:trunkfrom
aliehsaeedii:hrocksdb
Open

KAFKA-20132: Implement TimestampedKeyValueStoreWithHeaders (2/N)#21446
aliehsaeedii wants to merge 15 commits intoapache:trunkfrom
aliehsaeedii:hrocksdb

Conversation

@aliehsaeedii
Copy link
Contributor

@aliehsaeedii aliehsaeedii commented Feb 10, 2026

This PR add RocksDBTimestampedStoreWithHeaders and the corresponding
unit test (RocksDBTimestampedStoreWithHeadersTest) for the
TimestampedKeyValueStoreWithHeaders introduced in KIP-1271.

Reviewers: TengYao Chi frankvicky@apache.org, Matthias J. Sax
matthias@confluent.io

@github-actions github-actions bot added triage PRs from the community streams labels Feb 10, 2026
@mjsax mjsax added kip Requires or implements a KIP ci-approved and removed triage PRs from the community labels Feb 10, 2026
Copy link
Contributor

@frankvicky frankvicky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR.

// Check if we're upgrading from RocksDBTimestampedStore (which uses keyValueWithTimestamp CF)
final List<byte[]> existingCFs;
try {
final org.rocksdb.Options options = new org.rocksdb.Options(dbOptions, new ColumnFamilyOptions());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we replace full qualified name with import?

existingCFs = RocksDB.listColumnFamilies(options, dbDir.getAbsolutePath());
options.close();
} catch (final org.rocksdb.RocksDBException e) {
throw new org.apache.kafka.streams.errors.ProcessorStateException("Error listing column families for store " + name, e);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

}

final boolean upgradingFromTimestampedStore = existingCFs.stream()
.anyMatch(cf -> java.util.Arrays.equals(cf, LEGACY_TIMESTAMPED_CF_NAME));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

try (final LogCaptureAppender appender = LogCaptureAppender.createAndRegister(RocksDBTimestampedStoreWithHeaders.class)) {
rocksDBStore.init(context, rocksDBStore);

assertThat(appender.getMessages(), hasItem("Opening store " + DB_NAME + " in regular headers-aware mode"));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering should we keep using hamcrest in test.
AFAIK, hamcrest is not active, maybe we should use JUnit instead?
cc. @mjsax @bbejeck

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I never pay close attention to this, and I am personally fine either way. Of course, if there is some overall effort to move off hamcrest in favor of JUnit, it would make sense to avoid adding hamcrest code.

Copy link
Contributor

@frankvicky frankvicky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR.
There are lots of descriptive comments in the test.
Could you please consider to put them in the assertion message?

For example:

        // approx: 7 entries on legacy timestamped CF, 0 in new headers-aware CF
        assertEquals(7L, rocksDBStore.approximateNumEntries());

to

        assertEquals(7L, rocksDBStore.approximateNumEntries(), "should have 7 entries on legacy timestamped");

private static final byte[] LEGACY_TIMESTAMPED_CF_NAME =
"keyValueWithTimestamp".getBytes(StandardCharsets.UTF_8);

// New column family for header-aware timestamped values.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// New column family for header-aware timestamped values.
/**
* New column family for header-aware timestamped values.
*/

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment seems to not add any value -- I would remove it.

private static final byte[] LEGACY_TIMESTAMPED_CF_NAME =
"keyValueWithTimestamp".getBytes(StandardCharsets.UTF_8);

// New column family for header-aware timestamped values.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment seems to not add any value -- I would remove it.

{
final KeyValue<Bytes, byte[]> keyValue = itAll.next();
assertArrayEquals("key4".getBytes(), keyValue.key.get());
assertEquals(13, keyValue.value.length, "Expected header-aware format: varint(0) + empty headers(0) + timestamp(8) + value(4) = 13 bytes for key4 from legacy CF");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to above. putIfAbsent would not update the value, because the key exists, but still migrate the value from legacy- to headers-CF?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the same

Copy link
Contributor Author

@aliehsaeedii aliehsaeedii Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iterator does the conversion on the fly but does not apply it to the physical store.

{
final KeyValue<Bytes, byte[]> keyValue = itAll.next();
assertArrayEquals("key5".getBytes(), keyValue.key.get());
assertEquals(14, keyValue.value.length, "Expected header-aware format: varint(0) + empty headers(0) + timestamp(8) + value(5) = 14 bytes for key5 from legacy CF");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as for key4

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the same

@mjsax
Copy link
Member

mjsax commented Feb 12, 2026

Please rebase to trunk to ensure we don't miss anything about the checkstyle/spotbugs fix.

aliehsaeedii and others added 3 commits February 12, 2026 12:23
…/RocksDBTimestampedStoreWithHeaders.java

Co-authored-by: TengYao Chi <kitingiao@gmail.com>
…/RocksDBTimestampedStoreWithHeaders.java

Co-authored-by: TengYao Chi <kitingiao@gmail.com>
…/RocksDBTimestampedStoreWithHeaders.java

Co-authored-by: TengYao Chi <kitingiao@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci-approved kip Requires or implements a KIP streams

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants