reactive_graph_command_impl/
command_manager_impl.rs1use async_trait::async_trait;
2use serde_json::json;
3use std::sync::Arc;
4
5use reactive_graph_command_api::CommandManager;
6use reactive_graph_command_api::CommandRegistrationError;
7use reactive_graph_command_model::component::COMPONENT_COMMAND;
8use reactive_graph_command_model::component::CommandProperties::COMMAND_NAME;
9use reactive_graph_command_model::entity::Command;
10use reactive_graph_command_model::error::NoSuchCommand;
11use reactive_graph_graph::EntityType;
12use reactive_graph_graph::EntityTypeId;
13use reactive_graph_graph::PropertyInstanceGetter;
14use reactive_graph_lifecycle::Lifecycle;
15use reactive_graph_reactive_model_impl::ReactiveEntity;
16use reactive_graph_reactive_service_api::ReactiveEntityManager;
17use reactive_graph_type_system_api::EntityTypeManager;
18use springtime_di::Component;
19use springtime_di::component_alias;
20
21#[derive(Component)]
22pub struct CommandManagerImpl {
23 entity_type_manager: Arc<dyn EntityTypeManager + Send + Sync>,
24 reactive_entity_manager: Arc<dyn ReactiveEntityManager + Send + Sync>,
25}
26
27#[async_trait]
28#[component_alias]
29impl CommandManager for CommandManagerImpl {
30 fn get_command(&self, name: &str) -> Result<Command, NoSuchCommand> {
31 let name = name.into();
32 match self
33 .reactive_entity_manager
34 .get_by_component(&COMPONENT_COMMAND)
35 .iter()
36 .find(|e| e.as_string(COMMAND_NAME).is_some_and(|command_name| command_name == name))
37 {
38 Some(e) => Command::try_from(e.clone()).map_err(NoSuchCommand::NotACommand),
39 None => Err(NoSuchCommand::CommandNotFound(name)),
40 }
41 }
42
43 fn get_commands(&self) -> Vec<Command> {
44 self.reactive_entity_manager
45 .get_by_component(&COMPONENT_COMMAND)
46 .iter()
47 .filter_map(|e| Command::try_from(e.clone()).ok())
48 .collect()
49 }
50
51 fn register_command(&self, command: Command) -> Result<(), CommandRegistrationError> {
52 let ty = command.ty();
53 if !self.entity_type_manager.has(&ty) {
54 return Err(CommandRegistrationError::EntityTypeNotFound(ty));
55 }
56 let _ = self
57 .reactive_entity_manager
58 .register_reactive_instance(command.get_instance())
59 .map_err(CommandRegistrationError::ReactiveEntityRegistrationError);
60 Ok(())
61 }
62
63 fn register_singleton_command(&self, command: Command, entity_type: EntityType) -> Result<(), CommandRegistrationError> {
64 let _ = self
65 .entity_type_manager
66 .register(entity_type)
67 .map_err(CommandRegistrationError::EntityTypeRegistrationError)?;
68 let _ = self
69 .reactive_entity_manager
70 .register_reactive_instance(command.get_instance())
71 .map_err(CommandRegistrationError::ReactiveEntityRegistrationError);
72 Ok(())
73 }
74}
75
76#[async_trait]
77impl Lifecycle for CommandManagerImpl {
78 async fn init(&self) {
79 let reactive_entity_manager = self.reactive_entity_manager.clone();
80
81 let executor = Box::new(move |_: &ReactiveEntity| json!(reactive_entity_manager.get_by_component(&COMPONENT_COMMAND).len()));
82 let command = Command::builder()
83 .ty(EntityTypeId::new_from_type("core", "num_commands"))
84 .help("Number of commands")
85 .description("Number of commands")
86 .executor(executor)
87 .build();
88 let entity_type: EntityType = command.get_entity_type();
89 let _ = self.register_singleton_command(command, entity_type);
90
91 }
101}