@@ -76,6 +76,18 @@ type DataFlowSpec struct {
7676 // +optional
7777 CheckpointPersistence * bool `json:"checkpointPersistence,omitempty"`
7878
79+ // CheckpointSyncOnAck persists checkpoint to the ConfigMap immediately after each sink batch ack.
80+ // Shrinks the duplicate window on pod crash from the debounce interval to roughly one batch.
81+ // Default: false (debounced save only). Recommended for migration and cron workloads.
82+ // +optional
83+ CheckpointSyncOnAck * bool `json:"checkpointSyncOnAck,omitempty"`
84+
85+ // CheckpointSaveInterval controls how often pending checkpoints are flushed to the ConfigMap.
86+ // Also used as the minimum coalesce interval when checkpointSyncOnAck is true.
87+ // Default: 30s.
88+ // +optional
89+ CheckpointSaveInterval * metav1.Duration `json:"checkpointSaveInterval,omitempty"`
90+
7991 // ChannelBufferSize is the buffer size for message channels between source, processor, and sink.
8092 // Larger values reduce blocking when sink is slower than source (e.g. high Kafka throughput).
8193 // Default: 100. Recommended for high throughput: 500–1000.
@@ -733,6 +745,17 @@ type PostgreSQLSinkSpec struct {
733745 // +optional
734746 ConflictKey * string `json:"conflictKey,omitempty"`
735747
748+ // UpsertVersionColumn is the column used to compare row versions when UpsertStrategy is ifNewer.
749+ // On conflict, the existing row is updated only when EXCLUDED.<column> > target.<column>.
750+ // +optional
751+ UpsertVersionColumn * string `json:"upsertVersionColumn,omitempty"`
752+
753+ // UpsertStrategy controls conflict resolution: always (default) updates on every conflict;
754+ // ifNewer updates only when the incoming version is newer (requires upsertVersionColumn).
755+ // +optional
756+ // +kubebuilder:validation:Enum=always;ifNewer
757+ UpsertStrategy * string `json:"upsertStrategy,omitempty"`
758+
736759 // SoftDeleteColumn specifies column for soft delete (e.g. "deleted_at"). If set, DELETE operations will UPDATE this column instead of physical delete.
737760 // +optional
738761 SoftDeleteColumn * string `json:"softDeleteColumn,omitempty"`
@@ -785,6 +808,16 @@ type TrinoSinkSpec struct {
785808 // +optional
786809 AutoCreateTable * bool `json:"autoCreateTable,omitempty"`
787810
811+ // UpsertMode enables idempotent writes via MERGE (Iceberg catalog).
812+ // Requires conflictKey. Retries and replays update existing rows instead of creating duplicates.
813+ // +optional
814+ UpsertMode * bool `json:"upsertMode,omitempty"`
815+
816+ // ConflictKey specifies the column used to match rows in MERGE ON clause.
817+ // Required when upsertMode is true.
818+ // +optional
819+ ConflictKey * string `json:"conflictKey,omitempty"`
820+
788821 // RawMode when true, creates table with data VARCHAR column (JSON storage).
789822 // When false (default), uses columnar format matching message keys to table columns.
790823 // +optional
@@ -833,6 +866,27 @@ type ClickHouseSinkSpec struct {
833866 // +optional
834867 AutoCreateTable * bool `json:"autoCreateTable,omitempty"`
835868
869+ // UpsertMode enables idempotent writes via ReplacingMergeTree deduplication.
870+ // Inserts remain INSERT; duplicates are resolved on merge using conflictKey ORDER BY.
871+ // +optional
872+ UpsertMode * bool `json:"upsertMode,omitempty"`
873+
874+ // ConflictKey specifies the deduplication key column for ORDER BY when upsertMode is true.
875+ // If not set, the first message column (or created_at in raw mode) is used.
876+ // +optional
877+ ConflictKey * string `json:"conflictKey,omitempty"`
878+
879+ // TableEngine selects the MergeTree engine variant (default: MergeTree).
880+ // When upsertMode is true and tableEngine is unset, ReplacingMergeTree is used for auto-created tables.
881+ // +optional
882+ // +kubebuilder:validation:Enum=MergeTree;ReplacingMergeTree
883+ TableEngine * string `json:"tableEngine,omitempty"`
884+
885+ // ReplacingVersionColumn is the version column for ReplacingMergeTree(engine).
886+ // Rows with the highest version value are kept during background merges.
887+ // +optional
888+ ReplacingVersionColumn * string `json:"replacingVersionColumn,omitempty"`
889+
836890 // RawMode when true, creates table with data String and created_at columns (JSON storage).
837891 // When false (default), creates table from message structure (columnar, replicates source schema).
838892 // +optional
0 commit comments