Skip to content
This repository has been archived by the owner on Aug 13, 2024. It is now read-only.

Commit

Permalink
WIP #60 start converting executor to work on task-lists
Browse files Browse the repository at this point in the history
  • Loading branch information
ninjabear committed Sep 23, 2016
1 parent ca9557f commit 3ecd18f
Show file tree
Hide file tree
Showing 8 changed files with 161 additions and 37 deletions.
3 changes: 2 additions & 1 deletion src/factotum/executor/execution_strategy/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ mod tests;
use super::*;
use std::process::Command;
use chrono::UTC;
use std::time::{Duration};
use std::time::Duration;
use super::task_list::RunResult;

pub struct CommandRequest {
name: String,
Expand Down
1 change: 1 addition & 0 deletions src/factotum/executor/execution_strategy/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ use chrono::duration::Duration;
}

#[test]
#[ignore]
fn os_execution_good() {
let execution_strategy_os_exec = OSExecution::new();
let mut command:Command = Command::new("banana");
Expand Down
67 changes: 53 additions & 14 deletions src/factotum/executor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,33 +13,39 @@
* governing permissions and limitations there under.
*/

use factotum::factfile::*;
use factotum::factfile::Task as FactfileTask;
use factotum::factfile::Factfile;
use std::process::Command;
use std::time::{Duration, Instant};
use std::time::{Instant, Duration};
use std::thread;
use std::sync::mpsc;
use std::collections::HashMap;
use chrono::DateTime;
use chrono::UTC;

mod execution_strategy;
mod task_list;
pub mod execution_strategy;
pub mod task_list;
#[cfg(test)]
mod tests;

use factotum::executor::task_list::*;
use factotum::executor::execution_strategy::*;

enum TaskResult {
Ok(i32, Duration),
TerminateJobPlease(i32, Duration),
Error(Option<i32>, String)
}

pub struct RunResult {
pub run_started: DateTime<UTC>,
pub duration: Duration,
pub requests_job_termination: bool,
pub task_execution_error: Option<String>,
pub stdout: Option<String>,
pub stderr: Option<String>,
pub return_code: i32
}
// pub struct RunResult {
// pub run_started: DateTime<UTC>,
// pub duration: Duration,
// pub requests_job_termination: bool,
// pub task_execution_error: Option<String>,
// pub stdout: Option<String>,
// pub stderr: Option<String>,
// pub return_code: i32
// }

pub struct TaskExecutionResult {
pub name: String,
Expand All @@ -54,7 +60,7 @@ pub enum ExecutionResult {
}

#[inline]
fn drain_values(mut map:HashMap<String, TaskExecutionResult>, tasks_in_order:&Vec<Vec<&Task>>) -> Vec<TaskExecutionResult> {
fn drain_values(mut map:HashMap<String, TaskExecutionResult>, tasks_in_order:&Vec<Vec<&FactfileTask>>) -> Vec<TaskExecutionResult> {
let mut task_seq:Vec<TaskExecutionResult> = vec![];
for task_level in tasks_in_order.iter() {
for task in task_level.iter() {
Expand All @@ -67,6 +73,39 @@ fn drain_values(mut map:HashMap<String, TaskExecutionResult>, tasks_in_order:&Ve
task_seq
}


pub fn get_task_execution_list(factfile:&Factfile, start_from:Option<String>) -> TaskList<&FactfileTask> {
let mut task_list = TaskList::<&FactfileTask>::new();

let tasks = if let Some(start_task) = start_from {
info!("Reduced run! starting from {}", &start_task);
factfile.get_tasks_in_order_from(&start_task)
} else {
factfile.get_tasks_in_order()
};

for task_level in tasks.iter() {
let task_group: TaskGroup<&FactfileTask> = task_level
.iter()
.map(|t| task_list::Task::<&FactfileTask>::new(t.name.clone(), t))
.collect();

task_list.add_group(task_group).ok().unwrap();
}

for task_level in tasks.iter() {
for task in task_level.iter() {
for dep in task.depends_on.iter() {
task_list.set_child(&dep, &task.name).ok().unwrap();
}
}
}


task_list
}


pub fn execute_factfile(factfile:&Factfile, start_from:Option<String>) -> ExecutionResult {

let tasks = if let Some(start_task) = start_from {
Expand Down
27 changes: 17 additions & 10 deletions src/factotum/executor/task_list/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
mod tests;
use chrono::DateTime;
use chrono::UTC;
use chrono::Duration;
use std::time::Duration;
use std::collections::HashMap;

#[derive(Clone)]
Expand Down Expand Up @@ -95,16 +95,16 @@ impl<T> TaskList<T> {
return Ok(());
}

pub fn set_child(&mut self, parent:&Task<T>, child:&Task<T>) -> Result<(), String> {
if self.get_task_by_name(&child.name).is_some() {
if let Some(children) = self.edges.get_mut(&parent.name) {
children.push(child.name.clone());
pub fn set_child(&mut self, parent:&str, child:&str) -> Result<(), String> {
if self.get_task_by_name(&child).is_some() {
if let Some(children) = self.edges.get_mut(parent) {
children.push(child.to_string());
Ok(())
} else {
Err(format!("Parent task '{}' doesn't exist!", parent.name))
Err(format!("Parent task '{}' doesn't exist!", parent))
}
} else {
Err(format!("Child task '{}' doesn't exist!", &child.name))
Err(format!("Child task '{}' doesn't exist!", &child))
}
}

Expand All @@ -120,18 +120,25 @@ impl<T> TaskList<T> {
}

pub fn get_descendants(&self, task_name:&str) -> Vec<String> {
let mut descendants = self.get_descendants_recursively(task_name);
descendants.sort();
descendants.dedup();
descendants
}

fn get_descendants_recursively(&self, task_name:&str) -> Vec<String> {
let default = &vec![];
let deps:Vec<String> = self.edges.get(task_name).unwrap_or(default).iter().map(|x| x.clone()).collect();

let mut seen = vec![];

for dep in deps {
seen.push(dep.clone());
seen.extend(self.get_descendants(&dep));
seen.extend(self.get_descendants_recursively(&dep));
}

return seen;
}
return seen;
}


}
Expand Down
36 changes: 26 additions & 10 deletions src/factotum/executor/task_list/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ fn set_child_no_parent_err() {
tl.add_group(vec![
Task::<&str>::new("child", "world"),
]).ok().unwrap();
let r = tl.set_child(&Task::<&str>::new("parent", "world"), &Task::<&str>::new("child", "world"));
let r = tl.set_child("parent", "child");
assert!(r.ok().is_some()==false);
}

Expand All @@ -82,7 +82,7 @@ fn set_child_no_child_err() {
tl.add_group(vec![
Task::<&str>::new("parent", "world"),
]).ok().unwrap();
let r = tl.set_child(&Task::<&str>::new("parent", "world"), &Task::<&str>::new("child", "world"));
let r = tl.set_child("parent", "child");
assert!(r.ok().is_some()==false);
}

Expand All @@ -94,8 +94,7 @@ fn set_child_good() {
Task::<&str>::new("child", "world")
];
tl.add_group(tg).ok().unwrap();
let r = tl.set_child(&Task::<&str>::new("parent", "world"),
&Task::<&str>::new("child", "world"));
let r = tl.set_child("parent", "child");
assert!(r.ok().is_some()==true);
}

Expand All @@ -109,13 +108,30 @@ fn get_children() {
Task::<&str>::new("grandchild2", "world")
];
tl.add_group(tg).ok().unwrap();
tl.set_child(&Task::<&str>::new("parent", "world"),
&Task::<&str>::new("child", "world")).ok();
tl.set_child(&Task::<&str>::new("child", "world"),
&Task::<&str>::new("grandchild", "world")).ok();
tl.set_child(&Task::<&str>::new("child", "world"),
&Task::<&str>::new("grandchild2", "world")).ok();
tl.set_child("parent", "child").ok();
tl.set_child("child", "grandchild").ok();
tl.set_child("child", "grandchild2").ok();

assert_eq!(vec!["grandchild", "grandchild2"], tl.get_descendants("child"));
assert_eq!(vec!["child", "grandchild", "grandchild2"], tl.get_descendants("parent"));
assert_eq!(Vec::<String>::new(), tl.get_descendants(""))
}

#[test]
fn get_children_dups_removed() {
let mut tl = TaskList::<&str>::new();
let tg = vec![
Task::<&str>::new("parent", "world"),
Task::<&str>::new("child", "world"),
Task::<&str>::new("grandchild", "world"),
Task::<&str>::new("grandchild2", "world")
];
tl.add_group(tg).ok().unwrap();
tl.set_child("parent", "child").ok();
tl.set_child("child", "grandchild").ok();
tl.set_child("child", "grandchild2").ok();
tl.set_child("parent", "grandchild2").ok();

assert_eq!(vec!["grandchild", "grandchild2"], tl.get_descendants("child"));
assert_eq!(vec!["child", "grandchild", "grandchild2"], tl.get_descendants("parent"));
assert_eq!(Vec::<String>::new(), tl.get_descendants(""))
Expand Down
58 changes: 58 additions & 0 deletions src/factotum/executor/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright (c) 2016 Snowplow Analytics Ltd. All rights reserved.
*
* This program is licensed to you under the Apache License Version 2.0, and
* you may not use this file except in compliance with the Apache License
* Version 2.0. You may obtain a copy of the Apache License Version 2.0 at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the Apache License Version 2.0 is distributed on an "AS
* IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the Apache License Version 2.0 for the specific language
* governing permissions and limitations there under.
*/

use factotum::tests::make_task;
use factotum::factfile::*;
use factotum::executor::*;

#[test]
fn get_task_execution_list_good() {
let mut ff = Factfile::new("test");
ff.add_task_obj(&make_task("apple", &vec![]));
ff.add_task_obj(&make_task("turnip", &vec![]));
ff.add_task_obj(&make_task("orange", &vec!["apple"]));
ff.add_task_obj(&make_task("egg", &vec!["apple"]));
ff.add_task_obj(&make_task("potato", &vec!["apple", "egg"]));
ff.add_task_obj(&make_task("chicken", &vec!["potato","orange"]));

// apple---------- turnip
// / \ \
// orange egg----- \
// \ \ \
// \ potato
// \ \
// --------------- chicken

let tl = get_task_execution_list(&ff, None);

let expected = vec![ vec!["turnip", "apple"],
vec!["egg", "orange"],
vec!["potato"],
vec!["chicken"] ];

let actual:Vec<Vec<String>> = tl.tasks
.iter()
.map(|task_group| task_group.iter().map(|task| task.name.clone()).collect())
.collect();

assert_eq!(actual, expected);

// check the children are correctly mapped

assert_eq!(tl.get_descendants("turnip"), Vec::<String>::new());
assert_eq!(tl.get_descendants("apple"), vec!["chicken", "egg", "orange", "potato"]);
assert_eq!(tl.get_descendants("egg"), vec!["chicken", "potato"]);
assert_eq!(tl.get_descendants("orange"), vec!["chicken"]);
}
2 changes: 2 additions & 0 deletions src/factotum/factfile/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pub struct Factfile {
root: NodeIndex
}

#[derive(Clone)]
pub struct Task {
pub name: String,
pub depends_on: Vec<String>,
Expand All @@ -34,6 +35,7 @@ pub struct Task {
pub on_result: OnResult
}

#[derive(Clone)]
pub struct OnResult {
pub terminate_job: Vec<i32>,
pub continue_job: Vec<i32>
Expand Down
4 changes: 2 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ fn get_duration_with_hours() {
#[test]
fn test_get_task_result_line_str() {
use chrono::UTC;
use factotum::executor::RunResult;
use factotum::executor::task_list::RunResult;

let dt = UTC::now();
let sample_task = TaskExecutionResult {
Expand Down Expand Up @@ -469,7 +469,7 @@ fn test_get_task_result_line_str() {
#[test]
fn test_get_task_results_str_summary() {
use chrono::UTC;
use factotum::executor::RunResult;
use factotum::executor::task_list::RunResult;

let dt = UTC::now();

Expand Down

0 comments on commit 3ecd18f

Please sign in to comment.