Simplifying action and task reference a bit, fixing some logic errors, and adding in runner message queue polling
This commit is contained in:
parent
ce621dc9d5
commit
2c96b16ec8
+53
-21
@@ -3,28 +3,67 @@ use std::convert::From;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct TaskSet(HashMap<String, Task>);
|
||||
pub struct TaskSet(Vec<Task>);
|
||||
|
||||
impl TaskSet {
|
||||
pub fn new() -> Self {
|
||||
TaskSet(HashMap::new())
|
||||
TaskSet(Vec::new())
|
||||
}
|
||||
|
||||
pub fn coverage(&self) -> Result<ResourceInterval> {
|
||||
pub fn coverage(&self) -> ResourceInterval {
|
||||
self.get_state(MAX_TIME)
|
||||
}
|
||||
|
||||
pub fn validate(&self) -> Result<()> {
|
||||
self.get_state(MAX_TIME)?;
|
||||
let state = self.coverage();
|
||||
|
||||
for task in &self.0 {
|
||||
for resource in task.requires_resources() {
|
||||
if !state.contains_key(&resource) {
|
||||
return Err(anyhow!(
|
||||
"Task {} requires resource {}, which isn't produced.",
|
||||
task.name,
|
||||
resource
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// validate that no task generates the same resource on overlapping times
|
||||
let providers: HashMap<Resource, Vec<usize>> =
|
||||
self.0
|
||||
.iter()
|
||||
.enumerate()
|
||||
.fold(HashMap::new(), |mut acc, (idx, t)| {
|
||||
for res in &t.provides {
|
||||
acc.entry(res.clone()).or_insert(Vec::new()).push(idx)
|
||||
}
|
||||
acc
|
||||
});
|
||||
for (res, tids) in providers {
|
||||
let mut is = IntervalSet::new();
|
||||
for tid in tids {
|
||||
let already_provided = is.intersection(&self.0[tid].valid_over);
|
||||
if !already_provided.is_empty() {
|
||||
return Err(anyhow!(
|
||||
"Task set invalid: multiple tasks provide resource {} on the intervals {:?}",
|
||||
res,
|
||||
already_provided
|
||||
));
|
||||
}
|
||||
is.merge(&self.0[tid].valid_over);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_state<T: TimeZone>(&self, time: DateTime<T>) -> Result<ResourceInterval> {
|
||||
pub fn get_state<T: TimeZone>(&self, time: DateTime<T>) -> ResourceInterval {
|
||||
let mut res = ResourceInterval::new();
|
||||
|
||||
// Insert all of the covered items
|
||||
for task in self.values() {
|
||||
// TODO Need to align each of these intervals with a scheduled time
|
||||
for task in &self.0 {
|
||||
// Need to align each of these intervals with a scheduled time
|
||||
let timeline = if time < MAX_TIME {
|
||||
let cur_intv = task.schedule.interval(time.clone(), 0);
|
||||
if cur_intv.end > time {
|
||||
@@ -37,25 +76,18 @@ impl TaskSet {
|
||||
};
|
||||
let task_timeline = task.valid_over.intersection(&timeline);
|
||||
for resource in &task.provides {
|
||||
let ris = res.entry(resource.clone()).or_insert(IntervalSet::new());
|
||||
let already_provided = ris.intersection(&task_timeline);
|
||||
if !already_provided.is_empty() {
|
||||
return Err(anyhow!(
|
||||
"Task set invalid: multiple tasks provide resource {} on the intervals {:?}",
|
||||
resource,
|
||||
already_provided
|
||||
));
|
||||
}
|
||||
ris.merge(&task_timeline);
|
||||
res.entry(resource.clone())
|
||||
.or_insert(IntervalSet::new())
|
||||
.merge(&task_timeline);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(res)
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for TaskSet {
|
||||
type Target = HashMap<String, Task>;
|
||||
type Target = Vec<Task>;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
@@ -67,8 +99,8 @@ impl DerefMut for TaskSet {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<HashMap<String, Task>> for TaskSet {
|
||||
fn from(data: HashMap<String, Task>) -> Self {
|
||||
impl From<Vec<Task>> for TaskSet {
|
||||
fn from(data: Vec<Task>) -> Self {
|
||||
Self(data)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user