Skip to main content

dbx_core/replication/
protocol.rs

1//! Replication 프로토콜 메시지 정의
2
3use serde::{Deserialize, Serialize};
4
5/// Replication 메시지 타입
6#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
7pub enum ReplicationMessage {
8    /// WAL 항목 전송.
9    /// `node_id`: 발신 노드 식별자
10    /// `lsn`: 로그 시퀀스 번호
11    /// `timestamp`: LWW (Last-Writer-Wins) 기반 충돌 해결용
12    WalEntry {
13        node_id: u32,
14        lsn: u64,
15        timestamp: u64,
16        data: Vec<u8>,
17    },
18    /// 연결 유지 신호
19    Heartbeat { node_id: u32, lsn: u64 },
20    /// 특정 LSN부터 재전송 요청
21    RequestFrom { node_id: u32, lsn: u64 },
22    /// 동기화 완료 확인
23    Acknowledge { node_id: u32, lsn: u64 },
24    /// 마스터 승격(Failover) 표를 요청
25    /// `term`: 선출 임기 번호 (중복 선출 방지)
26    VoteRequest {
27        node_id: u32,
28        term: u64,
29        last_lsn: u64,
30    },
31    /// 마스터 승격(Failover) 투표 응답
32    /// `voter_id`: 투표한 노드 ID (집계용)
33    VoteResponse {
34        node_id: u32,
35        voter_id: u32,
36        term: u64,
37        granted: bool,
38    },
39    /// 새 마스터 승격 알림
40    Promotion { node_id: u32, term: u64 },
41}
42
43impl ReplicationMessage {
44    /// 메시지의 LSN 반환
45    pub fn lsn(&self) -> u64 {
46        match self {
47            ReplicationMessage::WalEntry { lsn, .. } => *lsn,
48            ReplicationMessage::Heartbeat { lsn, .. } => *lsn,
49            ReplicationMessage::RequestFrom { lsn, .. } => *lsn,
50            ReplicationMessage::Acknowledge { lsn, .. } => *lsn,
51            ReplicationMessage::VoteRequest { last_lsn, .. } => *last_lsn,
52            _ => 0,
53        }
54    }
55
56    /// WAL Entry 여부
57    pub fn is_wal_entry(&self) -> bool {
58        matches!(self, ReplicationMessage::WalEntry { .. })
59    }
60}
61
62#[cfg(test)]
63mod tests {
64    use super::*;
65
66    #[test]
67    fn test_message_lsn() {
68        let msg = ReplicationMessage::WalEntry {
69            node_id: 1,
70            lsn: 42,
71            timestamp: 123456789,
72            data: vec![1, 2, 3],
73        };
74        assert_eq!(msg.lsn(), 42);
75        assert!(msg.is_wal_entry());
76    }
77
78    #[test]
79    fn test_heartbeat() {
80        let msg = ReplicationMessage::Heartbeat {
81            node_id: 1,
82            lsn: 100,
83        };
84        assert_eq!(msg.lsn(), 100);
85        assert!(!msg.is_wal_entry());
86    }
87}