store_api/logstore.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
15//! LogStore APIs.
16
17pub mod entry;
18pub mod provider;
19
20use std::collections::HashMap;
21use std::pin::Pin;
22
23use common_error::ext::ErrorExt;
24use entry::Entry;
25use futures::Stream;
26
27pub type SendableEntryStream<'a, I, E> = Pin<Box<dyn Stream<Item = Result<Vec<I>, E>> + Send + 'a>>;
28
29pub use crate::logstore::entry::Id as EntryId;
30use crate::logstore::provider::Provider;
31use crate::storage::RegionId;
32
33/// `LogStore` serves as a Write-Ahead-Log for storage engine.
34#[async_trait::async_trait]
35pub trait LogStore: Send + Sync + 'static + std::fmt::Debug {
36 type Error: ErrorExt + Send + Sync + 'static;
37
38 /// Stops components of the logstore.
39 async fn stop(&self) -> Result<(), Self::Error>;
40
41 /// Appends a batch of entries and returns a response containing a map where the key is a region id
42 /// while the value is the id of the last successfully written entry of the region.
43 async fn append_batch(&self, entries: Vec<Entry>) -> Result<AppendBatchResponse, Self::Error>;
44
45 /// Creates a new `EntryStream` to asynchronously generates `Entry` with ids
46 /// starting from `id`.
47 async fn read(
48 &self,
49 provider: &Provider,
50 id: EntryId,
51 ) -> Result<SendableEntryStream<'static, Entry, Self::Error>, Self::Error>;
52
53 /// Creates a new `Namespace` from the given ref.
54 async fn create_namespace(&self, ns: &Provider) -> Result<(), Self::Error>;
55
56 /// Deletes an existing `Namespace` specified by the given ref.
57 async fn delete_namespace(&self, ns: &Provider) -> Result<(), Self::Error>;
58
59 /// Lists all existing namespaces.
60 async fn list_namespaces(&self) -> Result<Vec<Provider>, Self::Error>;
61
62 /// Marks all entries with ids `<=entry_id` of the given `namespace` as obsolete,
63 /// so that the log store can safely delete those entries. This method does not guarantee
64 /// that the obsolete entries are deleted immediately.
65 async fn obsolete(
66 &self,
67 provider: &Provider,
68 region_id: RegionId,
69 entry_id: EntryId,
70 ) -> Result<(), Self::Error>;
71
72 /// Marks all entries of a region as obsolete and removes its dedicated namespace when
73 /// supported by the backend.
74 async fn obsolete_all(
75 &self,
76 provider: &Provider,
77 region_id: RegionId,
78 ) -> Result<(), Self::Error>;
79
80 /// Makes an entry instance of the associated Entry type
81 fn entry(
82 &self,
83 data: Vec<u8>,
84 entry_id: EntryId,
85 region_id: RegionId,
86 provider: &Provider,
87 ) -> Result<Entry, Self::Error>;
88
89 /// Returns the latest entry id in the log store.
90 fn latest_entry_id(&self, provider: &Provider) -> Result<EntryId, Self::Error>;
91
92 /// Waits until every entry of the provider's region with an id at or below
93 /// `entry_id` has the persistence this log store guarantees for an
94 /// acknowledged append, so that a caller can persist `entry_id` as a
95 /// replay watermark.
96 ///
97 /// The default returns at once and keeps each log store's own
98 /// acknowledgement guarantee, whatever it is: Raft Engine with
99 /// `sync_write = false`, for example, acknowledges an append before its
100 /// periodic sync. A log store that acknowledges an append before its
101 /// entries have that persistence overrides this method.
102 async fn wait_durable(
103 &self,
104 _provider: &Provider,
105 _entry_id: EntryId,
106 ) -> Result<(), Self::Error> {
107 Ok(())
108 }
109
110 /// Releases every entry of a region the caller dropped, after `obsolete`
111 /// marked them obsolete, so that the log store keeps none of them even
112 /// across a restart, which never opens the region again to mark its
113 /// entries obsolete.
114 ///
115 /// The default does nothing and keeps each log store's existing handling
116 /// of a dropped region. A log store that keeps obsolete marks only in
117 /// memory overrides this method and returns once the release is durable.
118 async fn release_region(
119 &self,
120 _provider: &Provider,
121 _region_id: RegionId,
122 ) -> Result<(), Self::Error> {
123 Ok(())
124 }
125}
126
127/// The response of an `append` operation.
128#[derive(Debug, Default)]
129pub struct AppendResponse {
130 /// The id of the entry appended to the log store.
131 pub last_entry_id: EntryId,
132}
133
134/// The response of an `append_batch` operation.
135#[derive(Debug, Default)]
136pub struct AppendBatchResponse {
137 /// Key: region id (as u64). Value: the id of the last successfully written entry of the region.
138 pub last_entry_ids: HashMap<RegionId, EntryId>,
139}