faucet_source_mysql_cdc/
state.rs1use faucet_core::FaucetError;
10use serde::{Deserialize, Serialize};
11use serde_json::Value;
12
13pub fn state_key(server_id: u32) -> String {
15 format!("mysql-cdc:{server_id}")
16}
17
18#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
20#[serde(untagged)]
21pub enum Bookmark {
22 FilePos { file: String, pos: u64 },
24 GtidSet { gtid_set: String },
26}
27
28impl Bookmark {
29 pub fn from_value(v: Value) -> Result<Self, FaucetError> {
31 serde_json::from_value(v)
32 .map_err(|e| FaucetError::State(format!("mysql-cdc bookmark parse: {e}")))
33 }
34
35 pub fn to_value(&self) -> Result<Value, FaucetError> {
37 serde_json::to_value(self)
38 .map_err(|e| FaucetError::State(format!("mysql-cdc bookmark serialize: {e}")))
39 }
40}
41
42#[cfg(test)]
43mod tests {
44 use super::*;
45 use serde_json::json;
46
47 #[test]
48 fn state_key_format() {
49 assert_eq!(state_key(1001), "mysql-cdc:1001");
50 }
51
52 #[test]
53 fn file_pos_round_trip() {
54 let b = Bookmark::FilePos {
55 file: "binlog.000123".into(),
56 pos: 4567,
57 };
58 assert_eq!(Bookmark::from_value(b.to_value().unwrap()).unwrap(), b);
59 }
60
61 #[test]
62 fn gtid_round_trip() {
63 let b = Bookmark::GtidSet {
64 gtid_set: "uuid:1-1000".into(),
65 };
66 assert_eq!(Bookmark::from_value(b.to_value().unwrap()).unwrap(), b);
67 }
68
69 #[test]
70 fn file_pos_json_shape() {
71 let v = Bookmark::FilePos {
72 file: "b.1".into(),
73 pos: 9,
74 }
75 .to_value()
76 .unwrap();
77 assert_eq!(v, json!({ "file": "b.1", "pos": 9 }));
78 }
79
80 #[test]
81 fn rejects_garbage() {
82 assert!(Bookmark::from_value(json!({ "nope": 1 })).is_err());
83 }
84}