-
Notifications
You must be signed in to change notification settings - Fork 1k
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
feat: enable new emit-final implementation #9141
Changes from all commits
58aa967
7838aec
d3132a4
5978aea
6c1e50d
dcd7a85
7a8ba81
c69a0fd
913cc7a
7ec592e
22c60f5
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 |
---|---|---|
|
@@ -37,7 +37,7 @@ public enum OutputRefinement { | |
* | ||
* <p>For a stream, all events are final, so all are output. | ||
*/ | ||
FINAL; | ||
FINAL | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,6 +19,7 @@ | |
import com.fasterxml.jackson.annotation.JsonProperty; | ||
import com.google.errorprone.annotations.Immutable; | ||
import io.confluent.ksql.model.WindowType; | ||
import io.confluent.ksql.parser.OutputRefinement; | ||
import java.time.Duration; | ||
import java.util.Objects; | ||
import java.util.Optional; | ||
|
@@ -31,17 +32,26 @@ public final class WindowInfo { | |
|
||
private final WindowType type; | ||
private final Optional<Duration> size; | ||
private final OutputRefinement emitStrategy; | ||
|
||
@JsonCreator | ||
public static WindowInfo of( | ||
@JsonProperty(value = "type", required = true) final WindowType type, | ||
@JsonProperty(value = "size") final Optional<Duration> size) { | ||
return new WindowInfo(type, size); | ||
@JsonProperty(value = "size") final Optional<Duration> size, | ||
@JsonProperty(value = "emitStrategy") final Optional<OutputRefinement> emitStrategy) { | ||
return new WindowInfo(type, size, emitStrategy); | ||
} | ||
|
||
private WindowInfo(final WindowType type, final Optional<Duration> size) { | ||
private WindowInfo( | ||
final WindowType type, | ||
final Optional<Duration> size, | ||
final Optional<OutputRefinement> emitStrategy | ||
) { | ||
this.type = Objects.requireNonNull(type, "type"); | ||
this.size = Objects.requireNonNull(size, "size"); | ||
this.emitStrategy = Objects.requireNonNull( | ||
emitStrategy.orElse(OutputRefinement.CHANGES), | ||
"emitStrategy"); | ||
|
||
if (type.requiresWindowSize() && !size.isPresent()) { | ||
throw new IllegalArgumentException("Size required"); | ||
|
@@ -64,6 +74,10 @@ public Optional<Duration> getSize() { | |
return size; | ||
} | ||
|
||
public OutputRefinement getEmitStrategy() { | ||
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. Does the serialize/deserialize to/from JSON loop work for this, now that this getter is updated to return 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. 🤔 -- Interesting question... To me it just did not make sense to return an |
||
return emitStrategy; | ||
} | ||
|
||
@Override | ||
public boolean equals(final Object o) { | ||
if (this == o) { | ||
|
@@ -73,12 +87,17 @@ public boolean equals(final Object o) { | |
return false; | ||
} | ||
final WindowInfo that = (WindowInfo) o; | ||
|
||
// we omit `emitStrategy` because `WindowInfo` is used to determine the topic format, | ||
// and the emit-strategy has no impact on the serialization format | ||
return type == that.type | ||
&& Objects.equals(size, that.size); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
// we omit `emitStrategy` because `WindowInfo` is used to determine the topic format, | ||
// and the emit-strategy has no impact on the serialization format | ||
return Objects.hash(type, size); | ||
} | ||
|
||
|
@@ -87,6 +106,7 @@ public String toString() { | |
return "WindowInfo{" | ||
+ "type=" + type | ||
+ ", size=" + size.map(Duration::toMillis) | ||
+ ", emitStrategy=" + emitStrategy | ||
+ '}'; | ||
} | ||
} |
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.
Need this one to run QTTs...
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.
Is this only meant for QTT or are we expecting users to want/be able to set this for their own queries too? (Guessing the latter but want to check.)
Also, the first config (outer join spurious results fix emit interval) is unrelated to this PR, right? Is that another config we think users might want to set?
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.
Both are internal KS configs -- they control how often we try to emit results -- the other configs is for left/outer stream-stream joins (yes, it's unrelated to this PR, but serves the exact same purpose for a different operator).
We need them for QTT to ensure we alway try to emit result (both configs work on wall-clock time); otherwise, in QTT results might get "stuck" and are not emitted. I remember that for stream-stream join back in the days, we did not add test for all scenarios because we did not have access to this config.
Because both are internal, we don't really expect users to set them (with the exception that there is a perf problem and we tell them to change it). But we should be able for set the configs IMHO -- otherwise, the guard they provide for KS does not work for ksqlDB.
There are a few more internal configs, and we could consider to add them here, too. Also happy to remove the second config from this PR and we do some follow up.
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.
That makes sense. Just to confirm: users will be able to set these internal streams configs on their ksql queries (and have the configs take effect) after this change, right?
I think it's fine to leave the second config in -- we're essentially saying it's safe for users to set these configs on their ksql queries if they want to.
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.
Technically, yes.
Of course, both configs are "internal" meaning it's not documented anywhere (on purpose) and user most likely don't know about them (and should not need to know about them in general).