1use std::sync::Arc;
15
16use frame_core::component::{ComponentId, ComponentMeta};
17use frame_core::error::RegistryError;
18use frame_core::event::LifecycleState;
19use frame_core::registry::ComponentRegistry;
20use frame_core::runtime::{SupportModuleRef, SupportSwapper};
21
22use super::{CandidateBytes, GenerationReport, NodeControl, StartFailure};
23
24pub type Witness = Box<dyn FnMut(&ComponentRegistry) -> Result<(), String> + Send>;
28
29pub struct DevNodeControl {
31 registry: Arc<ComponentRegistry>,
32 swapper: SupportSwapper,
33 component: ComponentId,
34 meta: ComponentMeta,
35 support: SupportModuleRef,
36 witness_mailbox: Witness,
37 witness_content: Witness,
38}
39
40impl DevNodeControl {
41 #[must_use]
43 pub fn new(
44 registry: Arc<ComponentRegistry>,
45 swapper: SupportSwapper,
46 meta: ComponentMeta,
47 support: SupportModuleRef,
48 witness_mailbox: Witness,
49 witness_content: Witness,
50 ) -> Self {
51 Self {
52 registry,
53 swapper,
54 component: meta.id,
55 meta,
56 support,
57 witness_mailbox,
58 witness_content,
59 }
60 }
61
62 fn state(&self) -> Result<LifecycleState, String> {
63 self.registry
64 .status(self.component)
65 .map_err(|error| error.to_string())?
66 .map(|status| status.state)
67 .ok_or_else(|| "component is not registered".to_owned())
68 }
69}
70
71impl NodeControl for DevNodeControl {
72 fn stop_component(&mut self) -> Result<(), String> {
73 self.registry
74 .stop(self.component)
75 .map(|_| ())
76 .map_err(|error| error.to_string())
77 }
78
79 fn stage(&mut self, candidate: &CandidateBytes) -> Result<(), String> {
80 match self.state()? {
81 LifecycleState::Failed => {
85 self.registry
86 .remove(self.component)
87 .map_err(|error| format!("recovering failed registration: {error}"))?;
88 self.registry
89 .register(self.meta.clone(), candidate.component_beam.clone())
90 .map_err(|error| format!("re-registering after failure: {error}"))?;
91 }
92 _ => {
93 self.registry
94 .upgrade_bytecode(self.component, candidate.component_beam.clone())
95 .map_err(|error| error.to_string())?;
96 }
97 }
98 self.support = self
99 .swapper
100 .swap(&self.support, &candidate.ffi_beam)
101 .map_err(|error| format!("support module swap: {error}"))?;
102 Ok(())
103 }
104
105 fn start_component(&mut self) -> Result<(), StartFailure> {
106 self.registry
107 .start(self.component)
108 .map_err(|error| match error {
109 RegistryError::ModuleLoad { .. } | RegistryError::DeferredBifImports { .. } => {
110 StartFailure::Load(error.to_string())
111 }
112 other => StartFailure::Tree(other.to_string()),
113 })
114 }
115
116 fn witness_mailbox(&mut self) -> Result<(), String> {
117 (self.witness_mailbox)(&self.registry)
118 }
119
120 fn witness_content(&mut self) -> Result<(), String> {
121 (self.witness_content)(&self.registry)
122 }
123
124 fn report(
125 &mut self,
126 build_generation: u64,
127 content_digest: [u8; 32],
128 ) -> Result<GenerationReport, String> {
129 Ok(GenerationReport {
130 build_generation,
131 content_digest,
132 component_incarnation: self
133 .registry
134 .component_incarnation(self.component)
135 .map_err(|error| format!("incarnation witness unreadable: {error}"))?,
136 module_generation: self
137 .registry
138 .component_module_generation(self.component)
139 .map_err(|error| format!("module generation witness unreadable: {error}"))?,
140 })
141 }
142}