Skip to main content

common_wal/
options.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
15pub mod kafka;
16pub mod object_store;
17
18use serde::{Deserialize, Serialize};
19use serde_with::with_prefix;
20
21pub use crate::options::kafka::KafkaWalOptions;
22pub use crate::options::object_store::ObjectStoreWalOptions;
23
24/// An encoded wal options will be wrapped into a (WAL_OPTIONS_KEY, encoded wal options) key-value pair
25/// and inserted into the options of a `RegionCreateRequest`.
26pub const WAL_OPTIONS_KEY: &str = "wal_options";
27
28/// Wal options allocated to a region.
29/// A wal options is encoded by metasrv with `serde_json::to_string`, and then decoded
30/// by datanode with `serde_json::from_str`.
31#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
32#[serde(tag = "wal.provider", rename_all = "snake_case")]
33pub enum WalOptions {
34    #[default]
35    RaftEngine,
36    #[serde(with = "kafka_prefix")]
37    Kafka(KafkaWalOptions),
38    Noop,
39    #[serde(with = "object_store_prefix")]
40    ObjectStore(ObjectStoreWalOptions),
41}
42
43with_prefix!(kafka_prefix "wal.kafka.");
44with_prefix!(object_store_prefix "wal.object_store.");
45
46#[cfg(test)]
47mod tests {
48    use super::*;
49
50    #[test]
51    fn test_serde_wal_options() {
52        // Test serde raft-engine wal options.
53        let wal_options = WalOptions::RaftEngine;
54        let encoded = serde_json::to_string(&wal_options).unwrap();
55        let expected = r#"{"wal.provider":"raft_engine"}"#;
56        assert_eq!(&encoded, expected);
57
58        let decoded: WalOptions = serde_json::from_str(&encoded).unwrap();
59        assert_eq!(decoded, wal_options);
60
61        // Test serde kafka wal options.
62        let wal_options = WalOptions::Kafka(KafkaWalOptions::new("test_topic".to_string()));
63        let encoded = serde_json::to_string(&wal_options).unwrap();
64        let expected = r#"{"wal.provider":"kafka","wal.kafka.topic":"test_topic"}"#;
65        assert_eq!(&encoded, expected);
66
67        let decoded: WalOptions = serde_json::from_str(&encoded).unwrap();
68        assert_eq!(decoded, wal_options);
69
70        let wal_options = WalOptions::Kafka(KafkaWalOptions {
71            topic: "test_topic".to_string(),
72            initial_pruned_entry_id: Some(42),
73        });
74        let encoded = serde_json::to_string(&wal_options).unwrap();
75        let expected = r#"{"wal.provider":"kafka","wal.kafka.topic":"test_topic","wal.kafka.initial_pruned_entry_id":42}"#;
76        assert_eq!(&encoded, expected);
77
78        let decoded: WalOptions = serde_json::from_str(&encoded).unwrap();
79        assert_eq!(decoded, wal_options);
80
81        let decoded: WalOptions =
82            serde_json::from_str(r#"{"wal.provider":"kafka","wal.kafka.topic":"test_topic"}"#)
83                .unwrap();
84        assert_eq!(
85            decoded,
86            WalOptions::Kafka(KafkaWalOptions::new("test_topic".to_string()))
87        );
88
89        // Test serde noop wal options.
90        let wal_options = WalOptions::Noop;
91        let encoded = serde_json::to_string(&wal_options).unwrap();
92        let expected = r#"{"wal.provider":"noop"}"#;
93        assert_eq!(&encoded, expected);
94
95        let decoded: WalOptions = serde_json::from_str(&encoded).unwrap();
96        assert_eq!(decoded, wal_options);
97
98        let wal_options = WalOptions::ObjectStore(ObjectStoreWalOptions::new("wal".to_string()));
99        let encoded = serde_json::to_string(&wal_options).unwrap();
100        let expected = r#"{"wal.provider":"object_store","wal.object_store.prefix":"wal"}"#;
101        assert_eq!(&encoded, expected);
102
103        let decoded: WalOptions = serde_json::from_str(&encoded).unwrap();
104        assert_eq!(decoded, wal_options);
105    }
106
107    #[test]
108    fn test_decode_persisted_wal_options() {
109        let cases = [
110            (r#"{"wal.provider":"raft_engine"}"#, WalOptions::RaftEngine),
111            (
112                r#"{"wal.provider":"kafka","wal.kafka.topic":"test_topic"}"#,
113                WalOptions::Kafka(KafkaWalOptions::new("test_topic".to_string())),
114            ),
115            (r#"{"wal.provider":"noop"}"#, WalOptions::Noop),
116            (
117                r#"{"wal.provider":"object_store","wal.object_store.prefix":"wal"}"#,
118                WalOptions::ObjectStore(ObjectStoreWalOptions::new("wal".to_string())),
119            ),
120        ];
121        for (encoded, expected) in cases {
122            let decoded: WalOptions = serde_json::from_str(encoded).unwrap();
123            assert_eq!(decoded, expected);
124        }
125
126        assert!(serde_json::from_str::<WalOptions>(r#"{"wal.provider":"unknown"}"#).is_err());
127        assert!(serde_json::from_str::<WalOptions>(r#"{"wal.provider":"object_store"}"#).is_err());
128    }
129}