aboutsummaryrefslogtreecommitdiff
path: root/core/operator/watermark.go
diff options
context:
space:
mode:
Diffstat (limited to 'core/operator/watermark.go')
-rw-r--r--core/operator/watermark.go61
1 files changed, 61 insertions, 0 deletions
diff --git a/core/operator/watermark.go b/core/operator/watermark.go
new file mode 100644
index 0000000..3d591e5
--- /dev/null
+++ b/core/operator/watermark.go
@@ -0,0 +1,61 @@
1package operator
2
3import (
4 "context"
5
6 "flux/core"
7)
8
9// TimestampAssigner is responsible for event time defined by user
10type TimestampAssigner[IN any] func(in IN) int64
11
12type WaterGeneratorOperator[IN any] struct {
13 assigner TimestampAssigner[IN]
14 maxOutOfOrder int64
15 currentMaxTimestamp int64
16 lastEmittedWatermark int64
17}
18
19func NewWatermarkGeneratorOperator[IN any](maxOutOfOrder int64, assigner TimestampAssigner[IN]) *WaterGeneratorOperator[IN] {
20 return &WaterGeneratorOperator[IN]{
21 maxOutOfOrder: maxOutOfOrder,
22 assigner: assigner,
23 lastEmittedWatermark: -1,
24 }
25}
26
27func (w *WaterGeneratorOperator[IN]) Open(ctx context.Context) error {
28 return nil
29}
30
31func (w *WaterGeneratorOperator[IN]) Process(ctx context.Context, record core.StreamRecord[IN], out Emitter[IN]) error {
32 if record.Type == core.RecordData {
33 if err := out.Emit(ctx, record); err != nil {
34 return err
35 }
36 // query the time
37 eventTime := w.assigner(record.Value)
38 record.Timestamp = eventTime
39
40 // update the max timestamp
41 if w.currentMaxTimestamp < eventTime {
42 w.currentMaxTimestamp = eventTime
43 }
44
45 // calc the watermark
46
47 watermark := w.currentMaxTimestamp - w.maxOutOfOrder
48
49 // check if current watermark later than previous watermark
50 if watermark > w.lastEmittedWatermark {
51 w.lastEmittedWatermark = watermark
52 return out.Emit(ctx, core.NewWatermarkRecord[IN](watermark))
53 }
54 return nil
55 }
56 return out.Emit(ctx, record)
57}
58
59func (w *WaterGeneratorOperator[IN]) Close(ctx context.Context) error {
60 return nil
61}