krabka_client_streams/dsl/emit.rs
1//! `EmitStrategy` sets when a windowed aggregation forwards its results. It
2//! mirrors the JVM `org.apache.kafka.streams.kstream.EmitStrategy`.
3//! `on_window_update()` is the default and emits on every update.
4//! `on_window_close()` emits each window's final result once stream-time passes
5//! that window's close.
6//!
7//! The windowed handles carry it as a `Copy` field, and the lowering threads it
8//! into the aggregate processors. It changes ONLY the runtime forwarding
9//! behavior. The lowered topology, that is the node kind, the store
10//! registration, and the names, is identical for both strategies. This matches
11//! the JVM, which has one `KStreamWindowAggregate` class parameterized by
12//! `EmitStrategy`.
13
14/// When a windowed aggregation forwards its results downstream.
15#[derive(Clone, Copy, Debug, PartialEq, Eq)]
16pub struct EmitStrategy {
17 kind: EmitKind,
18}
19
20#[derive(Clone, Copy, Debug, PartialEq, Eq)]
21enum EmitKind {
22 OnWindowUpdate,
23 OnWindowClose,
24}
25
26impl EmitStrategy {
27 /// Emit on every update. This is the default.
28 #[must_use]
29 pub fn on_window_update() -> Self {
30 Self {
31 kind: EmitKind::OnWindowUpdate,
32 }
33 }
34
35 /// Emit each window's final result once stream-time passes its close.
36 #[must_use]
37 pub fn on_window_close() -> Self {
38 Self {
39 kind: EmitKind::OnWindowClose,
40 }
41 }
42
43 /// True for the emit-on-update strategy, which is the default. The aggregate
44 /// processors guard their per-update `ctx.forward` with this method.
45 pub(crate) fn is_on_update(self) -> bool {
46 matches!(self.kind, EmitKind::OnWindowUpdate)
47 }
48
49 /// True for the emit-on-close strategy.
50 pub(crate) fn is_on_close(self) -> bool {
51 matches!(self.kind, EmitKind::OnWindowClose)
52 }
53}
54
55impl Default for EmitStrategy {
56 fn default() -> Self {
57 Self::on_window_update()
58 }
59}
60
61#[cfg(test)]
62mod tests {
63 use super::*;
64
65 #[test]
66 fn defaults_to_on_update() {
67 assert!(EmitStrategy::default().is_on_update());
68 assert!(!EmitStrategy::default().is_on_close());
69 }
70
71 #[test]
72 fn on_window_close_is_close() {
73 let e = EmitStrategy::on_window_close();
74 assert!(e.is_on_close());
75 assert!(!e.is_on_update());
76 }
77}