assemble_core/task/
task_container.rs

1use crate::__export::TaskId;
2use crate::identifier::TaskIdFactory;
3
4use crate::project::error::{ProjectError, ProjectResult};
5use crate::project::shared::WeakSharedProject;
6use crate::task::any_task::AnyTaskHandle;
7use crate::task::lazy_task::TaskHandle;
8use crate::task::TaskHandleFactory;
9use crate::{Executable, Project, Task};
10use once_cell::sync::OnceCell;
11
12use crate::error::PayloadError;
13use crate::project::finder::TaskPath;
14use crate::project::shared::SharedProject;
15use itertools::Itertools;
16use std::collections::HashMap;
17use std::fmt::Debug;
18
19#[derive(Debug)]
20pub struct TaskContainer {
21    shared: OnceCell<WeakSharedProject>,
22    task_id_factory: TaskIdFactory,
23    handle_factory: OnceCell<TaskHandleFactory>,
24    mapping: HashMap<TaskId, AnyTaskHandle>,
25}
26
27impl TaskContainer {
28    /// Creates a new task container. Tasks can not be registered until a project has been shared with
29    /// the task container.
30    pub fn new(id_factory: TaskIdFactory) -> Self {
31        Self {
32            shared: OnceCell::new(),
33            task_id_factory: id_factory,
34            handle_factory: OnceCell::new(),
35            mapping: HashMap::new(),
36        }
37    }
38
39    /// Initialize the task factory
40    pub(crate) fn init(&mut self, project: &WeakSharedProject) {
41        self.shared
42            .set(project.clone())
43            .expect("shared already set");
44        self.handle_factory
45            .set(TaskHandleFactory::new(project.clone()))
46            .expect("factory already set");
47    }
48
49    #[inline]
50    fn handle_factory(&self) -> &TaskHandleFactory {
51        self.handle_factory
52            .get()
53            .expect("task handle should be set")
54    }
55
56    #[inline]
57    fn shared_project(&self) -> SharedProject {
58        let weak = self.shared.get().unwrap();
59        weak.clone().upgrade().expect("should be not weak")
60    }
61
62    pub fn register_task<T: Task + Send + Sync + Debug + 'static>(
63        &mut self,
64        id: &str,
65    ) -> ProjectResult<TaskHandle<T>> {
66        let id = self.task_id_factory.create(id).map_err(PayloadError::new)?;
67
68        if self.mapping.contains_key(&id) {
69            panic!("Task with id {} already registered", id);
70        }
71
72        let handle = self
73            .handle_factory()
74            .create_handle::<T>(id.clone())
75            .map_err(PayloadError::new)?;
76        let any_task_handle = AnyTaskHandle::new(handle.clone());
77        self.mapping.insert(id, any_task_handle);
78        Ok(handle)
79    }
80    pub fn register_task_with<
81        T: Task + Send + Sync + Debug + 'static,
82        F: 'static + Send + FnOnce(&mut Executable<T>, &Project) -> ProjectResult,
83    >(
84        &mut self,
85        id: &str,
86        config: F,
87    ) -> ProjectResult<TaskHandle<T>> {
88        let mut handle = self.register_task::<T>(id)?;
89        handle.configure_with(config)?;
90        Ok(handle)
91    }
92
93    /// Get all tasks registered to this task container
94    pub fn get_tasks(&self) -> impl IntoIterator<Item = &TaskId> {
95        self.mapping.keys()
96    }
97
98    /// Get a task
99    pub fn get_task(&self, id: &TaskId) -> Option<&AnyTaskHandle> {
100        self.mapping.get(id)
101    }
102}