Skip to main content

ic_canister_kit/functions/
pausable.rs

1//! 维护状态
2
3// ================== 功能 ==================
4
5/// 维护原因
6pub trait Reasonable {
7    /// 维护原因
8    fn message(&self) -> &str;
9}
10
11/// 维护记录
12pub trait Pausable<Reason: Reasonable> {
13    // 查询
14
15    /// 查询维护状态
16    fn pause_query(&self) -> &Option<Reason>;
17
18    // 修改
19
20    /// 修改维护状态
21    fn pause_replace(&mut self, reason: Option<Reason>);
22
23    // 默认方法
24
25    /// 是否维护中
26    fn pause_is_paused(&self) -> bool {
27        self.pause_query().is_some()
28    }
29    /// 是否正常运行
30    fn pause_is_running(&self) -> bool {
31        !self.pause_is_paused()
32    }
33    /// 正常运行中才能继续
34    fn pause_must_be_running(&self) -> Result<(), String> {
35        if let Some(reason) = &self.pause_query() {
36            return Err(format!("Canister is paused: {}", reason.message()));
37        }
38        Ok(())
39    }
40    /// 维护中才能继续
41    fn pause_must_be_paused(&self) -> Result<(), String> {
42        if self.pause_is_running() {
43            return Err("Canister is running. Not paused.".into());
44        }
45        Ok(())
46    }
47}
48
49// ================== 简单实现 ==================
50
51/// 维护功能简单实现
52pub mod basic {
53    use std::fmt::Display;
54
55    use candid::CandidType;
56    use serde::{Deserialize, Serialize};
57
58    use crate::{
59        functions::types::{Pausable, Reasonable},
60        types::TimestampNanos,
61    };
62
63    /// 维护原因对象
64    #[derive(CandidType, Serialize, Deserialize, Debug, Clone)]
65    pub struct PauseReason {
66        /// 维护时间
67        pub timestamp_nanos: TimestampNanos,
68
69        /// 维护原因
70        pub message: String,
71    }
72
73    impl Display for PauseReason {
74        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
75            f.write_str(&format!("{:?}", self))
76        }
77    }
78
79    impl std::error::Error for PauseReason {}
80
81    impl Reasonable for PauseReason {
82        fn message(&self) -> &str {
83            &self.message
84        }
85    }
86
87    impl PauseReason {
88        /// 构造维护原因
89        pub fn new(message: String) -> Self {
90            PauseReason {
91                timestamp_nanos: crate::times::now(),
92                message,
93            }
94        }
95    }
96
97    /// 记录维护状态
98    #[derive(CandidType, Serialize, Deserialize, Debug, Clone, Default)]
99    pub struct Pause(Option<PauseReason>);
100
101    impl Pausable<PauseReason> for Pause {
102        // 查询
103        fn pause_query(&self) -> &Option<PauseReason> {
104            &self.0
105        }
106        // 修改
107        // 设置维护状态
108        fn pause_replace(&mut self, reason: Option<PauseReason>) {
109            self.0 = reason;
110        }
111    }
112}