-
Notifications
You must be signed in to change notification settings - Fork 15.4k
KAFKA-6455: Session Aggregation should use window-end-time as record timestamp #6645
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,38 +16,41 @@ | |
| */ | ||
| package org.apache.kafka.streams.kstream.internals; | ||
|
|
||
| import org.apache.kafka.streams.kstream.Windowed; | ||
| import org.apache.kafka.streams.processor.ProcessorContext; | ||
| import org.apache.kafka.streams.processor.StateStore; | ||
| import org.apache.kafka.streams.processor.To; | ||
| import org.apache.kafka.streams.state.internals.CacheFlushListener; | ||
| import org.apache.kafka.streams.state.internals.WrappedStateStore; | ||
|
|
||
| /** | ||
| * This class is used to determine if a processor should forward values to child nodes. | ||
| * Forwarding by this class only occurs when caching is not enabled. If caching is enabled, | ||
| * forwarding occurs in the flush listener when the cached store flushes. | ||
| * | ||
| * @param <K> the type of the key | ||
| * @param <V> the type of the value | ||
| * @param <K> | ||
| * @param <V> | ||
| */ | ||
| class TupleForwarder<K, V> { | ||
| class SessionTupleForwarder<K, V> { | ||
| private final ProcessorContext context; | ||
| private final boolean sendOldValues; | ||
| private final boolean cachingEnabled; | ||
|
|
||
| @SuppressWarnings("unchecked") | ||
| TupleForwarder(final StateStore store, | ||
| final ProcessorContext context, | ||
| final ForwardingCacheFlushListener<K, V> flushListener, | ||
| final boolean sendOldValues) { | ||
| SessionTupleForwarder(final StateStore store, | ||
| final ProcessorContext context, | ||
| final CacheFlushListener<Windowed<K>, V> flushListener, | ||
| final boolean sendOldValues) { | ||
| this.context = context; | ||
| this.sendOldValues = sendOldValues; | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As above |
||
| cachingEnabled = ((WrappedStateStore) store).setFlushListener(flushListener, sendOldValues); | ||
| } | ||
|
|
||
| public void maybeForward(final K key, | ||
| public void maybeForward(final Windowed<K> key, | ||
| final V newValue, | ||
| final V oldValue) { | ||
| if (!cachingEnabled) { | ||
| context.forward(key, new Change<>(newValue, sendOldValues ? oldValue : null)); | ||
| context.forward(key, new Change<>(newValue, sendOldValues ? oldValue : null), To.all().withTimestamp(key.window().end())); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -160,12 +160,17 @@ public <K, V> void forward(final K key, | |
| final V value, | ||
| final To to) { | ||
| final ProcessorNode previousNode = currentNode(); | ||
| final long currentTimestamp = recordContext.timestamp(); | ||
| final ProcessorRecordContext previousContext = recordContext; | ||
|
|
||
| try { | ||
| toInternal.update(to); | ||
| if (toInternal.hasTimestamp()) { | ||
| recordContext.setTimestamp(toInternal.timestamp()); | ||
| recordContext = new ProcessorRecordContext( | ||
| toInternal.timestamp(), | ||
| recordContext.offset(), | ||
| recordContext.partition(), | ||
| recordContext.topic(), | ||
| recordContext.headers()); | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @vvcephei I put this fix to make |
||
| } | ||
|
|
||
| final String sendTo = toInternal.child(); | ||
|
|
@@ -183,7 +188,7 @@ public <K, V> void forward(final K key, | |
| forward(child, key, value); | ||
| } | ||
| } finally { | ||
| recordContext.setTimestamp(currentTimestamp); | ||
| recordContext = previousContext; | ||
| setCurrentNode(previousNode); | ||
| } | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -29,7 +29,7 @@ | |
|
|
||
| public class ProcessorRecordContext implements RecordContext { | ||
|
|
||
| private long timestamp; | ||
| private final long timestamp; | ||
| private final long offset; | ||
| private final String topic; | ||
| private final int partition; | ||
|
|
@@ -48,10 +48,6 @@ public ProcessorRecordContext(final long timestamp, | |
| this.headers = headers; | ||
| } | ||
|
|
||
| public void setTimestamp(final long timestamp) { | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This class must be immutable -- otherwise, using |
||
| this.timestamp = timestamp; | ||
| } | ||
|
|
||
| @Override | ||
| public long offset() { | ||
| return offset; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -38,8 +38,8 @@ public AbstractStoreBuilder(final String name, | |
| final Serde<K> keySerde, | ||
| final Serde<V> valueSerde, | ||
| final Time time) { | ||
| Objects.requireNonNull(name, "name can't be null"); | ||
| Objects.requireNonNull(time, "time can't be null"); | ||
| Objects.requireNonNull(name, "name cannot be null"); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why we change this?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's improves the style. It's internal only anyway. |
||
| Objects.requireNonNull(time, "time cannot be null"); | ||
| this.name = name; | ||
| this.keySerde = keySerde; | ||
| this.valueSerde = valueSerde; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to #6667 -- we should obey
sendOldValues.