Skip to main content

flow/batching_mode/
checkpoint.rs

1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::batching_mode::state::CheckpointMode;
16
17pub(super) const CHECKPOINT_DECISION_ADVANCE: &str = "advance";
18pub(super) const CHECKPOINT_DECISION_FALLBACK: &str = "fallback";
19pub(super) const CHECKPOINT_REASON_NONE: &str = "none";
20
21/// Why the task fell back to full snapshot mode.
22#[derive(Debug, Clone, Copy, PartialEq, Eq)]
23pub(super) enum FlowQueryFallbackReason {
24    /// The query result did not include a region-watermark map at all.
25    MissingRegionWatermark,
26    /// Some participating regions could not prove safe advancement against
27    /// both the returned watermarks and the checkpoint map.
28    IncompleteRegionWatermark,
29    /// The query only covered part of the dirty backlog, so global checkpoints
30    /// cannot advance yet. Incremental SQL drains all dirty windows before
31    /// checkpoint advancement; this primarily protects scoped full-snapshot
32    /// runs capped by the per-query dirty-window limit.
33    DirtyBacklogPending,
34    /// The datanode detected a stale incremental cursor and the Flow
35    /// must recompute from scratch.
36    StaleCursor,
37    /// A non-stale-cursor query failure; the Flow resets to full snapshot
38    /// to avoid cascading errors.
39    IncrementalQueryFailure,
40    /// Incremental mode has been permanently disabled for this Flow
41    /// (e.g. because the query shape is not incrementally safe).
42    IncrementalDisabled,
43}
44
45impl FlowQueryFallbackReason {
46    pub(super) fn as_label(self) -> &'static str {
47        match self {
48            Self::MissingRegionWatermark => "missing_region_watermark",
49            Self::IncompleteRegionWatermark => "incomplete_region_watermark",
50            Self::DirtyBacklogPending => "dirty_backlog_pending",
51            Self::StaleCursor => "stale_cursor",
52            Self::IncrementalQueryFailure => "incremental_query_failure",
53            Self::IncrementalDisabled => "incremental_disabled",
54        }
55    }
56}
57
58/// Decision produced by `BatchingTask::apply_query_result_to_state` after
59/// each Flow query execution. Describes whether the task advanced its
60/// checkpoint state or fell back to full snapshot, and why.
61#[derive(Debug, Clone, Copy, PartialEq, Eq)]
62pub(super) enum FlowCheckpointDecision {
63    /// FullSnapshot → Incremental transition.
64    ///
65    /// The query exercised every participating region, all returned valid
66    /// watermarks, and the checkpoint map was populated from scratch.
67    /// Subsequent executions will use incremental after-seqs.
68    AdvancedFromFullSnapshot {
69        participating_regions: usize,
70        watermarks: usize,
71    },
72    /// Existing Incremental → Incremental (in-place advancement).
73    ///
74    /// A subset of participating regions advanced their watermarks. The
75    /// task stays in incremental mode with an updated checkpoint map.
76    AdvancedIncremental {
77        participating_regions: usize,
78        watermarks: usize,
79    },
80    /// Any mode → FullSnapshot.
81    ///
82    /// Watermark information was incomplete, a participating region was
83    /// absent from the existing checkpoint map, the task has permanently
84    /// disabled incremental mode, or the query itself failed. The task
85    /// resets to full snapshot semantics for the next execution.
86    FallbackToFullSnapshot {
87        previous_mode: CheckpointMode,
88        reason: FlowQueryFallbackReason,
89    },
90}
91
92impl FlowCheckpointDecision {
93    pub(super) fn mode_label(self) -> &'static str {
94        match self {
95            Self::AdvancedFromFullSnapshot { .. } => {
96                checkpoint_mode_label(CheckpointMode::FullSnapshot)
97            }
98            Self::AdvancedIncremental { .. } => checkpoint_mode_label(CheckpointMode::Incremental),
99            Self::FallbackToFullSnapshot { previous_mode, .. } => {
100                checkpoint_mode_label(previous_mode)
101            }
102        }
103    }
104
105    pub(super) fn decision_label(self) -> &'static str {
106        match self {
107            Self::AdvancedFromFullSnapshot { .. } | Self::AdvancedIncremental { .. } => {
108                CHECKPOINT_DECISION_ADVANCE
109            }
110            Self::FallbackToFullSnapshot { .. } => CHECKPOINT_DECISION_FALLBACK,
111        }
112    }
113
114    pub(super) fn reason_label(self) -> &'static str {
115        match self {
116            Self::FallbackToFullSnapshot { reason, .. } => reason.as_label(),
117            _ => CHECKPOINT_REASON_NONE,
118        }
119    }
120}
121
122pub(super) fn checkpoint_mode_label(mode: CheckpointMode) -> &'static str {
123    match mode {
124        CheckpointMode::FullSnapshot => "full_snapshot",
125        CheckpointMode::Incremental => "incremental",
126    }
127}