canic_core/ops/
lifecycle.rs

1use crate::{
2    VERSION,
3    cdk::{api::canister_self, println},
4    ids::{CanisterRole, SubnetRole},
5    log,
6    log::Topic,
7    model::memory::topology::SubnetIdentity,
8    ops::{
9        CanisterInitPayload,
10        model::memory::{
11            EnvOps,
12            directory::{AppDirectoryOps, SubnetDirectoryOps},
13            registry::MemoryRegistryOps,
14            topology::SubnetCanisterRegistryOps,
15        },
16        service::TimerService,
17    },
18};
19use canic_memory::runtime::init_eager_tls;
20
21/// root_init
22/// Bootstraps the root canister runtime and environment.
23pub fn root_init(identity: SubnetIdentity) {
24    // --- Phase 1: Init base systems ---
25
26    // log - clear some space
27    println!("");
28    println!("");
29    println!("");
30    log!(
31        Topic::Init,
32        Info,
33        "🔧 --------------------- 'canic v{VERSION} -----------------------",
34    );
35    log!(Topic::Init, Info, "🏁 init: root ({identity:?})");
36
37    // init
38    init_eager_tls();
39    MemoryRegistryOps::init_memory().unwrap();
40
41    // --- Phase 2: Env registration ---
42    let self_pid = canister_self();
43    EnvOps::set_canister_type(CanisterRole::ROOT);
44    EnvOps::set_root_pid(self_pid);
45
46    match identity {
47        SubnetIdentity::Prime => {
48            EnvOps::set_prime_root_pid(self_pid);
49            EnvOps::set_subnet_type(SubnetRole::PRIME);
50            EnvOps::set_subnet_pid(self_pid);
51        }
52        SubnetIdentity::Standard(params) => {
53            EnvOps::set_prime_root_pid(params.prime_root_pid);
54            EnvOps::set_subnet_type(params.subnet_type);
55            EnvOps::set_subnet_pid(self_pid);
56        }
57        SubnetIdentity::Manual(subnet_pid) => {
58            EnvOps::set_prime_root_pid(self_pid);
59            EnvOps::set_subnet_type(SubnetRole::PRIME);
60            EnvOps::set_subnet_pid(subnet_pid);
61        }
62    }
63
64    SubnetCanisterRegistryOps::register_root(self_pid);
65
66    // --- Phase 3: Service startup ---
67    if let Err(err) = TimerService::start_all_root() {
68        log!(Topic::Init, Warn, "timer startup failed (root): {err}");
69    }
70}
71
72/// root_post_upgrade
73pub fn root_post_upgrade() {
74    // --- Phase 1: Init base systems ---
75    log!(Topic::Init, Info, "🏁 post_upgrade: root");
76    init_eager_tls();
77    MemoryRegistryOps::init_memory().unwrap();
78
79    // --- Phase 2: Env registration ---
80
81    // --- Phase 3: Service startup ---
82    if let Err(err) = TimerService::start_all_root() {
83        log!(Topic::Init, Warn, "timer startup failed (root): {err}");
84    }
85}
86
87/// nonroot_init
88pub fn nonroot_init(canister_type: CanisterRole, payload: CanisterInitPayload) {
89    // --- Phase 1: Init base systems ---
90    log!(Topic::Init, Info, "🏁 init: {}", canister_type);
91    init_eager_tls();
92    MemoryRegistryOps::init_memory().unwrap();
93
94    // --- Phase 2: Payload registration ---
95    EnvOps::import(payload.env);
96    AppDirectoryOps::import(payload.app_directory);
97    SubnetDirectoryOps::import(payload.subnet_directory);
98
99    // --- Phase 3: Service startup ---
100    if let Err(err) = TimerService::start_all() {
101        log!(Topic::Init, Warn, "timer startup failed (nonroot): {err}");
102    }
103}
104
105/// nonroot_post_upgrade
106pub fn nonroot_post_upgrade(canister_type: CanisterRole) {
107    // --- Phase 1: Init base systems ---
108    log!(Topic::Init, Info, "🏁 post_upgrade: {}", canister_type);
109    init_eager_tls();
110    MemoryRegistryOps::init_memory().unwrap();
111
112    // --- Phase 2: Env registration ---
113
114    // --- Phase 3: Service startup ---
115    if let Err(err) = TimerService::start_all() {
116        log!(Topic::Init, Warn, "timer startup failed (nonroot): {err}");
117    }
118}