Skip to content

Commit 280e40e

Browse files
feat: use SnapshotOp
1 parent 6619e9e commit 280e40e

File tree

11 files changed

+441
-328
lines changed

11 files changed

+441
-328
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

influxdb3_cache/src/last_cache/provider.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,8 @@ impl LastCacheProvider {
319319
}
320320
}
321321
WalOp::Catalog(_) => (),
322+
WalOp::ForcedSnapshot(_) => (),
323+
WalOp::Snapshot(_) => (),
322324
}
323325
}
324326
}

influxdb3_wal/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,6 @@ tokio.workspace = true
3434

3535
[lints]
3636
workspace = true
37+
38+
[dev-dependencies]
39+
test-log.workspace = true

influxdb3_wal/src/create.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ pub fn wal_contents(
1818
max_timestamp_ns,
1919
wal_file_number: WalFileSequenceNumber::new(wal_file_number),
2020
ops: ops.into_iter().collect(),
21-
snapshot: None,
2221
}
2322
}
2423

@@ -29,13 +28,14 @@ pub fn wal_contents_with_snapshot(
2928
ops: impl IntoIterator<Item = WalOp>,
3029
snapshot: SnapshotDetails,
3130
) -> WalContents {
31+
let mut wal_ops: Vec<WalOp> = ops.into_iter().collect();
32+
wal_ops.push(WalOp::Snapshot(snapshot));
3233
WalContents {
3334
persist_timestamp_ms: 0,
3435
min_timestamp_ns,
3536
max_timestamp_ns,
3637
wal_file_number: WalFileSequenceNumber::new(wal_file_number),
37-
ops: ops.into_iter().collect(),
38-
snapshot: Some(snapshot),
38+
ops: wal_ops,
3939
}
4040
}
4141

influxdb3_wal/src/lib.rs

Lines changed: 77 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ pub mod object_store;
88
pub mod serialize;
99
mod snapshot_tracker;
1010

11-
use crate::snapshot_tracker::SnapshotInfo;
1211
use async_trait::async_trait;
1312
use data_types::Timestamp;
1413
use hashbrown::HashMap;
@@ -77,16 +76,25 @@ pub trait Wal: Debug + Send + Sync + 'static {
7776
/// permit to release when done. The caller is responsible for cleaning up the wal.
7877
async fn flush_buffer(
7978
&self,
80-
) -> Option<(
81-
oneshot::Receiver<SnapshotDetails>,
82-
SnapshotInfo,
83-
OwnedSemaphorePermit,
84-
)>;
79+
) -> Option<(oneshot::Receiver<SnapshotDetails>, OwnedSemaphorePermit)>;
80+
81+
/// This is similar to flush buffer but it allows for snapshot to be done immediately rather
82+
/// than waiting for query buffer to get to a certain capacity. It would be nicer to not
83+
/// require an external interface to force flush the buffer however to decide whether to
84+
/// snapshot immediately is based on query buffer's capacity which is not visible to snapshot
85+
/// tracker which usually decides whether to snapshot or not. To bubble up the query buffer's
86+
/// size or even to indicate that buffer is full we need a shared state and because flushing
87+
/// the buffer is in hot path, this additional method acts as a compromise as this can be
88+
/// called by making the decision to force the snapshot externally to `WalObjectStore` (that
89+
/// implements this trait)
90+
async fn force_flush_buffer(
91+
&self,
92+
) -> Option<(oneshot::Receiver<SnapshotDetails>, OwnedSemaphorePermit)>;
8593

8694
/// Removes any snapshot wal files
8795
async fn cleanup_snapshot(
8896
&self,
89-
snapshot_details: SnapshotInfo,
97+
snapshot_details: SnapshotDetails,
9098
snapshot_permit: OwnedSemaphorePermit,
9199
);
92100

@@ -96,37 +104,29 @@ pub trait Wal: Debug + Send + Sync + 'static {
96104
/// Returns the last persisted wal file sequence number
97105
async fn last_snapshot_sequence_number(&self) -> SnapshotSequenceNumber;
98106

99-
/// Returns the snapshot info, if force snapshot is set it avoids checking
100-
/// certain cases and returns snapshot info leaving only the last wal period
101-
async fn snapshot_info_and_permit(
102-
&self,
103-
force_snapshot: bool,
104-
) -> Option<(SnapshotInfo, OwnedSemaphorePermit)>;
107+
/// Get snapshot details based on conditions
108+
async fn get_snapshot_details(&self, force_snapshot: bool) -> Option<SnapshotDetails>;
105109

106110
/// Stop all writes to the WAL and flush the buffer to a WAL file.
107111
async fn shutdown(&self);
108112

109113
async fn flush_buffer_and_cleanup_snapshot(self: Arc<Self>) {
110114
let maybe_snapshot = self.flush_buffer().await;
111-
if let Some((snapshot_complete, snapshot_info, permit)) = maybe_snapshot {
112-
self.cleanup_after_snapshot(snapshot_complete, snapshot_info, permit)
113-
.await;
115+
if let Some((snapshot_complete, permit)) = maybe_snapshot {
116+
self.cleanup_after_snapshot(snapshot_complete, permit).await;
114117
}
115118
}
116119

117120
async fn cleanup_after_snapshot(
118121
self: Arc<Self>,
119122
snapshot_complete: oneshot::Receiver<SnapshotDetails>,
120-
snapshot_info: SnapshotInfo,
121123
permit: OwnedSemaphorePermit,
122124
) {
123125
// handle snapshot cleanup outside of the flush loop
124126
let arcd_wal = Arc::clone(&self);
125127
tokio::spawn(async move {
126128
let snapshot_details = snapshot_complete.await.expect("snapshot failed");
127-
assert_eq!(snapshot_info.snapshot_details, snapshot_details);
128-
129-
arcd_wal.cleanup_snapshot(snapshot_info, permit).await;
129+
arcd_wal.cleanup_snapshot(snapshot_details, permit).await;
130130
});
131131
}
132132
}
@@ -136,22 +136,26 @@ pub trait Wal: Debug + Send + Sync + 'static {
136136
#[async_trait]
137137
pub trait WalFileNotifier: Debug + Send + Sync + 'static {
138138
/// Notify the handler that a new WAL file has been persisted with the given contents.
139-
fn notify(&self, write: WalContents);
140-
141-
/// Notify the handler that a new WAL file has been persisted with the given contents and tell
142-
/// it to snapshot the data. The returned receiver will be signalled when the snapshot is complete.
143-
async fn notify_and_snapshot(
139+
async fn notify(
144140
&self,
145141
write: WalContents,
146-
snapshot_details: SnapshotDetails,
147-
) -> oneshot::Receiver<SnapshotDetails>;
148-
149-
/// Snapshot only, currently used to force the snapshot
150-
async fn snapshot(
151-
&self,
152-
snapshot_details: SnapshotDetails,
153-
) -> oneshot::Receiver<SnapshotDetails>;
154-
142+
do_snapshot: bool,
143+
) -> Option<oneshot::Receiver<SnapshotDetails>>;
144+
145+
// /// Notify the handler that a new WAL file has been persisted with the given contents and tell
146+
// /// it to snapshot the data. The returned receiver will be signalled when the snapshot is complete.
147+
// async fn notify_and_snapshot(
148+
// &self,
149+
// write: WalContents,
150+
// snapshot_details: SnapshotDetails,
151+
// ) -> oneshot::Receiver<SnapshotDetails>;
152+
153+
// /// Snapshot only, currently used to force the snapshot
154+
// async fn snapshot(
155+
// &self,
156+
// snapshot_details: SnapshotDetails,
157+
// ) -> oneshot::Receiver<SnapshotDetails>;
158+
//
155159
fn as_any(&self) -> &dyn Any;
156160
}
157161

@@ -251,6 +255,8 @@ impl Default for Gen1Duration {
251255
pub enum WalOp {
252256
Write(WriteBatch),
253257
Catalog(OrderedCatalogBatch),
258+
ForcedSnapshot(SnapshotDetails),
259+
Snapshot(SnapshotDetails),
254260
}
255261

256262
impl PartialOrd for WalOp {
@@ -273,6 +279,18 @@ impl Ord for WalOp {
273279

274280
// For two Write ops, consider them equal
275281
(WalOp::Write(_), WalOp::Write(_)) => Ordering::Equal,
282+
(WalOp::Write(_), WalOp::ForcedSnapshot(_)) => Ordering::Equal,
283+
(WalOp::Write(_), WalOp::Snapshot(_)) => Ordering::Equal,
284+
(WalOp::Catalog(_), WalOp::ForcedSnapshot(_)) => Ordering::Equal,
285+
(WalOp::Catalog(_), WalOp::Snapshot(_)) => Ordering::Equal,
286+
(WalOp::ForcedSnapshot(_), WalOp::Write(_)) => Ordering::Equal,
287+
(WalOp::ForcedSnapshot(_), WalOp::Catalog(_)) => Ordering::Equal,
288+
(WalOp::ForcedSnapshot(_), WalOp::ForcedSnapshot(_)) => Ordering::Equal,
289+
(WalOp::ForcedSnapshot(_), WalOp::Snapshot(_)) => Ordering::Equal,
290+
(WalOp::Snapshot(_), WalOp::Write(_)) => Ordering::Equal,
291+
(WalOp::Snapshot(_), WalOp::Catalog(_)) => Ordering::Equal,
292+
(WalOp::Snapshot(_), WalOp::ForcedSnapshot(_)) => Ordering::Equal,
293+
(WalOp::Snapshot(_), WalOp::Snapshot(_)) => Ordering::Equal,
276294
}
277295
}
278296
}
@@ -282,13 +300,17 @@ impl WalOp {
282300
match self {
283301
WalOp::Write(w) => Some(w),
284302
WalOp::Catalog(_) => None,
303+
WalOp::ForcedSnapshot(_) => None,
304+
WalOp::Snapshot(_) => None,
285305
}
286306
}
287307

288308
pub fn as_catalog(&self) -> Option<&CatalogBatch> {
289309
match self {
290310
WalOp::Write(_) => None,
291311
WalOp::Catalog(c) => Some(&c.catalog),
312+
WalOp::ForcedSnapshot(_) => None,
313+
WalOp::Snapshot(_) => None,
292314
}
293315
}
294316
}
@@ -837,13 +859,29 @@ pub struct WalContents {
837859
pub wal_file_number: WalFileSequenceNumber,
838860
/// The operations contained in the WAL file
839861
pub ops: Vec<WalOp>,
840-
/// If present, the buffer should be snapshot after the contents of this file are loaded.
841-
pub snapshot: Option<SnapshotDetails>,
842862
}
843863

844864
impl WalContents {
845865
pub fn is_empty(&self) -> bool {
846-
self.ops.is_empty() && self.snapshot.is_none()
866+
self.ops.is_empty()
867+
}
868+
869+
pub fn add_snapshot_op(&mut self, snapshot_details: SnapshotDetails) {
870+
self.ops.push(WalOp::Snapshot(snapshot_details));
871+
}
872+
873+
pub fn add_force_snapshot_op(&mut self, snapshot_details: SnapshotDetails) {
874+
self.ops.push(WalOp::ForcedSnapshot(snapshot_details));
875+
}
876+
877+
pub fn find_snapshot_details(&self) -> Option<SnapshotDetails> {
878+
// There should be only one snapshot in a wal file?
879+
// should assert that
880+
self.ops.iter().find_map(|item| match item {
881+
WalOp::Snapshot(details) => Some(*details),
882+
WalOp::ForcedSnapshot(details) => Some(*details),
883+
_ => None,
884+
})
847885
}
848886
}
849887

@@ -912,6 +950,8 @@ pub struct SnapshotDetails {
912950
pub snapshot_sequence_number: SnapshotSequenceNumber,
913951
/// All chunks with data before this time can be snapshot and persisted
914952
pub end_time_marker: i64,
953+
/// All wal files with a sequence number >= to this can be deleted once snapshotting is complete
954+
pub first_wal_sequence_number: WalFileSequenceNumber,
915955
/// All wal files with a sequence number <= to this can be deleted once snapshotting is complete
916956
pub last_wal_sequence_number: WalFileSequenceNumber,
917957
}

0 commit comments

Comments
 (0)