use std::sync::Arc;
use frame_core::component::{ComponentId, ComponentMeta};
use frame_core::error::RegistryError;
use frame_core::event::LifecycleState;
use frame_core::registry::ComponentRegistry;
use frame_core::runtime::{SupportModuleRef, SupportSwapper};
use super::{CandidateBytes, GenerationReport, NodeControl, StartFailure};
pub type Witness = Box<dyn FnMut(&ComponentRegistry) -> Result<(), String> + Send>;
pub struct DevNodeControl {
registry: Arc<ComponentRegistry>,
swapper: SupportSwapper,
component: ComponentId,
meta: ComponentMeta,
support: SupportModuleRef,
witness_mailbox: Witness,
witness_content: Witness,
}
impl DevNodeControl {
#[must_use]
pub fn new(
registry: Arc<ComponentRegistry>,
swapper: SupportSwapper,
meta: ComponentMeta,
support: SupportModuleRef,
witness_mailbox: Witness,
witness_content: Witness,
) -> Self {
Self {
registry,
swapper,
component: meta.id,
meta,
support,
witness_mailbox,
witness_content,
}
}
fn state(&self) -> Result<LifecycleState, String> {
self.registry
.status(self.component)
.map_err(|error| error.to_string())?
.map(|status| status.state)
.ok_or_else(|| "component is not registered".to_owned())
}
}
impl NodeControl for DevNodeControl {
fn stop_component(&mut self) -> Result<(), String> {
self.registry
.stop(self.component)
.map(|_| ())
.map_err(|error| error.to_string())
}
fn stage(&mut self, candidate: &CandidateBytes) -> Result<(), String> {
match self.state()? {
LifecycleState::Failed => {
self.registry
.remove(self.component)
.map_err(|error| format!("recovering failed registration: {error}"))?;
self.registry
.register(self.meta.clone(), candidate.component_beam.clone())
.map_err(|error| format!("re-registering after failure: {error}"))?;
}
_ => {
self.registry
.upgrade_bytecode(self.component, candidate.component_beam.clone())
.map_err(|error| error.to_string())?;
}
}
self.support = self
.swapper
.swap(&self.support, &candidate.ffi_beam)
.map_err(|error| format!("support module swap: {error}"))?;
Ok(())
}
fn start_component(&mut self) -> Result<(), StartFailure> {
self.registry
.start(self.component)
.map_err(|error| match error {
RegistryError::ModuleLoad { .. } | RegistryError::DeferredBifImports { .. } => {
StartFailure::Load(error.to_string())
}
other => StartFailure::Tree(other.to_string()),
})
}
fn witness_mailbox(&mut self) -> Result<(), String> {
(self.witness_mailbox)(&self.registry)
}
fn witness_content(&mut self) -> Result<(), String> {
(self.witness_content)(&self.registry)
}
fn report(
&mut self,
build_generation: u64,
content_digest: [u8; 32],
) -> Result<GenerationReport, String> {
Ok(GenerationReport {
build_generation,
content_digest,
component_incarnation: self
.registry
.component_incarnation(self.component)
.map_err(|error| format!("incarnation witness unreadable: {error}"))?,
module_generation: self
.registry
.component_module_generation(self.component)
.map_err(|error| format!("module generation witness unreadable: {error}"))?,
})
}
}