Skip to content

KAFKA-20132: Implement TimestampedKeyValueStoreWithHeaders (3/N)#21451

Open
aliehsaeedii wants to merge 7 commits intoapache:trunkfrom
aliehsaeedii:metered
Open

KAFKA-20132: Implement TimestampedKeyValueStoreWithHeaders (3/N)#21451
aliehsaeedii wants to merge 7 commits intoapache:trunkfrom
aliehsaeedii:metered

Conversation

@aliehsaeedii
Copy link
Contributor

@aliehsaeedii aliehsaeedii commented Feb 11, 2026

This PR implements the metered layer of the TimestampedKeyValueStoreWithHeaders introduced in
KIP-1271. It include utests as well.

@github-actions github-actions bot added triage PRs from the community streams and removed triage PRs from the community labels Feb 11, 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

final ValueTimestampHeaders<V> value) {
Objects.requireNonNull(key, "key cannot be null");
try {
Headers headers = value.headers();
Copy link
Contributor

Choose a reason for hiding this comment

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

final

}

protected ValueTimestampHeaders<V> outerValue(final byte[] value) {
Headers headers = ValueTimestampHeadersDeserializer.headers(value);
Copy link
Contributor

Choose a reason for hiding this comment

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

final

Comment on lines 258 to 261
final KeyValueIterator<String, ValueTimestampHeaders<String>> iterator = metered.range(KEY, KEY);
assertEquals(VALUE_TIMESTAMP_HEADERS, iterator.next().value);
assertFalse(iterator.hasNext());
iterator.close();
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
final KeyValueIterator<String, ValueTimestampHeaders<String>> iterator = metered.range(KEY, KEY);
assertEquals(VALUE_TIMESTAMP_HEADERS, iterator.next().value);
assertFalse(iterator.hasNext());
iterator.close();
try (final KeyValueIterator<String, ValueTimestampHeaders<String>> iterator = metered.range(KEY, KEY)) {
assertEquals(VALUE_TIMESTAMP_HEADERS, iterator.next().value);
assertFalse(iterator.hasNext());
}

Comment on lines 274 to 277
final KeyValueIterator<String, ValueTimestampHeaders<String>> iterator = metered.all();
assertEquals(VALUE_TIMESTAMP_HEADERS, iterator.next().value);
assertFalse(iterator.hasNext());
iterator.close();
Copy link
Contributor

Choose a reason for hiding this comment

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

ditto

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.

Hi @aliehsaeedii,
I have a question about the test shouldPassDefaultChangelogTopicNameToStateStoreSerdeIfLoggingDisabled to make sure I understand its purpose correctly.

My understanding is that this test verifies the following behavior:

When changelog logging is disabled (i.e., context.changelogFor(STORE_NAME) returns null), the MeteredTimestampedKeyValueStoreWithHeaders should still pass a default changelog topic name to the serde's serializer/deserializer methods, rather than passing null.

The default topic name is generated using:

  ProcessorStateManager.storeChangelogTopic(APPLICATION_ID, STORE_NAME, taskId.topologyName())

This ensures that the serde can still be properly configured even when changelog logging is not enabled for the state store.

Is my understanding correct?
Thanks!

@aliehsaeedii
Copy link
Contributor Author

Is my understanding correct?

@frankvicky
Yes, it was my understanding as well.

@mjsax mjsax added kip Requires or implements a KIP ci-approved labels Feb 12, 2026
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.

I am still trying to wrap my head around details -- left one more comment for now, to hear what you think.

We need to avoid too much back and forth -- in my last comment, I also only said we don't need to overload get(), but I think the overloads to put() and putIfAbsent() were actually correct, as we need to change the code to extract the headers from the given value to pass into the key serializer?

For the value serializer I think, it's not necessary to pass the headers as own parameter, because the value itself is already of type ValueTimestampHeader and contains the headers already, so there seems to be no reason to pass the same headers a second time?

return value != null ? serdes.valueFrom(value, new RecordHeaders()) : null;
}

protected Bytes keyBytes(final K key) {
Copy link
Member

Choose a reason for hiding this comment

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

Looking into the POC PR, we actually added Headers parameter here, and I think it would be the right thing to do, and just pass in new RecrodHeaders() when used inside MeteredKeyValueStore but pass in the extracted Headers object from the value in the MeteredTimestampedKeyValueWithHeadersStore case?

This implies we need to overload put() in MeteredTimestampedKeyValueWithHeadersStore.

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