Skip to content

Comments

KAFKA-20132: Implement TimestampedKeyValueStoreWithHeaders (5/N) #21455

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

KAFKA-20132: Implement TimestampedKeyValueStoreWithHeaders (5/N) #21455
aliehsaeedii wants to merge 15 commits intoapache:trunkfrom
aliehsaeedii:builders

Conversation

@aliehsaeedii
Copy link
Contributor

@aliehsaeedii aliehsaeedii commented Feb 11, 2026

This PR adds required classes or modifies the existing ones to build
the TimestampedKeyValueStoreWithHeaders introduced in
KIP-1271.
It include utests as well.

@github-actions github-actions bot added triage PRs from the community streams labels Feb 11, 2026
@github-actions
Copy link

A label of 'needs-attention' was automatically added to this PR in order to raise the
attention of the committers. Once this issue has been triaged, the triage label
should be removed to prevent this automation from happening again.

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.

Comment on lines 44 to 48
return returnHeadersStore ?
new RocksDBTimestampedStoreWithHeaders(name, metricsScope()) :
returnTimestampedStore ?
new RocksDBTimestampedStore(name, metricsScope()) :
new RocksDBStore(name, metricsScope());
Copy link
Contributor

Choose a reason for hiding this comment

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

Given this condition is getting complex, should we use if statement?
For example

        if (returnHeadersStore)
            return new RocksDBTimestampedStoreWithHeaders(name, metricsScope());
        if (returnTimestampedStore)
            return new RocksDBTimestampedStore(name, metricsScope());
        return new RocksDBStore(name, metricsScope());

Comment on lines 48 to 49
* {@link org.apache.kafka.streams.state.TimestampedKeyValueStoreWithHeaders} and
* {@link org.apache.kafka.streams.state.TimestampedKeyValueStore}.
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you please use import instead of full qualified name?

* {@link org.apache.kafka.streams.state.TimestampedKeyValueStore}.
* <p>
* If a user provides a supplier for {@code TimestampedKeyValueStore} (without headers) via
* {@link org.apache.kafka.streams.kstream.Materialized#as(KeyValueBytesStoreSupplier)} when building
Copy link
Contributor

Choose a reason for hiding this comment

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

ditto

Comment on lines 36 to 38
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.core.IsInstanceOf.instanceOf;
Copy link
Contributor

Choose a reason for hiding this comment

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

As previous PRs, we should avoid using hamcrest

Comment on lines 64 to 65
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;
Copy link
Contributor

Choose a reason for hiding this comment

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

As previous PRs, we should avoid using hamcrest

Copy link
Member

@mjsax mjsax left a comment

Choose a reason for hiding this comment

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

Made a pass (skipped tests for now)

final boolean returnHeadersStore) {
this.name = name;
this.returnTimestampedStore = returnTimestampedStore;
this.returnHeadersStore = returnHeadersStore;
Copy link
Member

Choose a reason for hiding this comment

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

Should we add a check for invalid combination of returnTimestampedStore and returnHeadersStore?

We only support 3 out of 4 combinations, right?

Copy link
Contributor Author

@aliehsaeedii aliehsaeedii Feb 20, 2026

Choose a reason for hiding this comment

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

Due to the first else, the 4th combination (both true) is served with the first if which sematically is not wrong as headers stores are both ts and are WithHeaders. No idea if considering 4th combination helps. Should we throw exception for now?

Copy link
Member

Choose a reason for hiding this comment

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

Should we throw exception for now?

That was the idea.

if (!enableCaching) {
return inner;
}
return new CachingKeyValueStore(inner, true);
Copy link
Member

Choose a reason for hiding this comment

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

I was just wondering about true parameter -- seems to be related to IQv2. Do we need to do something about this (I believe yes from a quick look into the code) -- can we write a proper test, that IQv2 is disabled, and does not crash anything if one tries to use it, and provides a good error message?

/**
* Generic iterator adapter for range/all operations
*/
private static class TimestampedToHeadersIteratorAdapter<K> implements KeyValueIterator<K, byte[]> {
Copy link
Member

Choose a reason for hiding this comment

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

Why are we nesting this as private classes? For the ts/kv-adapter we have it as top level classes, and re-use them for other store types, too. Can't we re-use them for other store types for the header case?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For the ts/kv-adapter we have it as top level classes

I see private static class KeyValueToTimestampedKeyValueAdapterIterator inside KeyValueToTimestampedKeyValueByteStoreAdapter

Copy link
Member

Choose a reason for hiding this comment

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

There is two classes with very similar names... KeyValueToTimestampedKeyValueIteratorAdapter (is a standalone class), and there is also KeyValueToTimestampedKeyValueAdapterIterator which is the private one... (we would rename the private one as a pointed out on some other comment to get better names -- very easy to mix up)


private final RocksDbIterator rocksDbIterator;

public TimestampedToHeadersRocksIteratorAdapter(final RocksDbIterator rocksDbIterator) {
Copy link
Member

Choose a reason for hiding this comment

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

This naming is much better than the one from KeyValueToTimestampedKeyValueByteStoreAdapter.KeyValueToTimestampedKeyValueAdapterIterator -- can we update the exiting name over there to align naming schema (best in a follow up PR)

return returnTimestampedStore ?
new RocksDBTimestampedStore(name, metricsScope()) :
new RocksDBStore(name, metricsScope());
if (returnHeadersStore) {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
if (returnHeadersStore) {
if (returnTimestampedStore && returnHeadersStore) {

Copy link
Member

Choose a reason for hiding this comment

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

Maybe somewhat redundant, but this is how the flags are used... seems cleaner?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

?

Copy link
Member

@mjsax mjsax Feb 20, 2026

Choose a reason for hiding this comment

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

Well, it's redundant because returnTimestampedStore == false and returnHeadersStore == true is not something we support. -- And returnHeadersStore == true implies that returnTimestampedStore must be true as well. -- It still feel "cleaner" to check both flags?

@github-actions github-actions bot removed needs-attention triage PRs from the community labels Feb 20, 2026
@mjsax
Copy link
Member

mjsax commented Feb 20, 2026

Build failed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants