WIP: Basic Routine Functionality #40
2 changed files with 121 additions and 11 deletions
|
@ -35,6 +35,7 @@ use casual_logger::Log;
|
|||
use chrono::DateTime;
|
||||
// use chrono::Duration;
|
||||
use chrono::Local;
|
||||
use chrono::OutOfRangeError;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
use async_trait::async_trait;
|
||||
|
@ -655,17 +656,25 @@ impl Routine {
|
|||
|
||||
// WORK IN PROGRESS VECTOR - Vec<$RoutineAttr>
|
||||
|
||||
let wip_attr:Vec<&RoutineAttr> = vec![
|
||||
&RoutineAttr::RunOnce
|
||||
let wip_attr:Vec<RoutineAttr> = vec![
|
||||
RoutineAttr::RunOnce,
|
||||
RoutineAttr::ScheduledStart(chrono::offset::Local::now()),
|
||||
RoutineAttr::DelayedStart,
|
||||
];
|
||||
|
||||
let implemented_attr:Vec<&RoutineAttr> = vec![
|
||||
let implemented_attr:Vec<RoutineAttr> = vec![
|
||||
];
|
||||
|
||||
|
||||
// [x] 2. Built in Logic will check these vectors, and return if Not Implemented
|
||||
|
||||
let mut unimplemented = routine_attr.iter().filter(|x| !wip_attr.contains(x) && !implemented_attr.contains(x));
|
||||
let mut unimplemented = routine_attr.iter()
|
||||
.filter(|x| {
|
||||
let inx = x;
|
||||
wip_attr.iter().filter(|y| matches!(y,i if i == inx)).next().is_none()
|
||||
|| implemented_attr.iter().filter(|y| matches!(y,i if i == inx)).next().is_none()
|
||||
}
|
||||
);
|
||||
|
||||
if unimplemented.next().is_some() {
|
||||
|
||||
|
@ -690,6 +699,23 @@ impl Routine {
|
|||
return Ok("Valid & Implemented Setup".to_string())
|
||||
}
|
||||
|
||||
if routine_attr.contains(&RoutineAttr::RunOnce) &
|
||||
routine_attr.contains(&RoutineAttr::LoopInfinitely)
|
||||
{
|
||||
return Err("Conflicting Routine Attributes".to_string())
|
||||
}
|
||||
|
||||
|
||||
// [x] Err if DelayedStart but no LoopDuration
|
||||
if routine_attr.contains(&RoutineAttr::DelayedStart) &&
|
||||
routine_attr.iter()
|
||||
.filter(|x| matches!(x,&&RoutineAttr::LoopDuration(_)) )
|
||||
.next().is_none()
|
||||
{
|
||||
return Err("DelayedStart must include a LoopDuration".to_string())
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -837,19 +863,103 @@ impl Routine {
|
|||
);
|
||||
|
||||
Log::flush();
|
||||
{ // Prior to Loop that calls Custom Routine Execution Body
|
||||
|
||||
// [ ] If Scheduled Start or Delayed Start, Handle that first
|
||||
|
||||
|
||||
fn duration_to_datetime(future_dt: DateTime<Local>) -> Result<Duration,OutOfRangeError>
|
||||
{
|
||||
(future_dt - chrono::offset::Local::now()).to_std()
|
||||
}
|
||||
|
||||
let delayduration = {
|
||||
|
||||
let lock = trg_routine_ar.read().await;
|
||||
|
||||
let mut related_attrs = lock
|
||||
.routine_attr.iter()
|
||||
.filter(|x| matches!(x,&&RoutineAttr::DelayedStart) || matches!(x,&&RoutineAttr::ScheduledStart(_)) );
|
||||
|
||||
// match related_attrs.next() {
|
||||
|
||||
// }
|
||||
|
||||
async fn duration_from_attr(attr: &RoutineAttr,trg_routine_ar : RoutineAR) -> Option<Duration> {
|
||||
// let duration_from_attr = async {
|
||||
let lock = trg_routine_ar.read().await;
|
||||
|
||||
match attr {
|
||||
RoutineAttr::ScheduledStart(dt) => {
|
||||
if let Ok(dur) = duration_to_datetime(*dt) {
|
||||
Some(dur)
|
||||
} else { None }
|
||||
},
|
||||
RoutineAttr::DelayedStart => {
|
||||
let mut loopdur_attr_iter = lock
|
||||
.routine_attr.iter()
|
||||
.filter(|x| matches!(x,&&RoutineAttr::LoopDuration(_)) );
|
||||
|
||||
if let Some(loopdur_attr) = loopdur_attr_iter.next() {
|
||||
if let RoutineAttr::LoopDuration(dur) = loopdur_attr {
|
||||
Some(*dur)
|
||||
} else { None }
|
||||
} else { None }
|
||||
// None
|
||||
},
|
||||
_ => { None } // Handle no other combination
|
||||
}
|
||||
}
|
||||
|
||||
// The following is done twice just in case ScheduledStart and DelayedStart are defined
|
||||
let delayduration01 = if let Some(attr) = related_attrs.next() {
|
||||
duration_from_attr(attr, trg_routine_ar.clone()).await
|
||||
} else { None };
|
||||
|
||||
let delayduration02 = if let Some(attr) = related_attrs.next() {
|
||||
duration_from_attr(attr, trg_routine_ar.clone()).await
|
||||
} else { None };
|
||||
|
||||
// if there is a 2nd related duration, pick the minimum, otherwise, pick the results of delayduration01
|
||||
if delayduration02.is_some() {
|
||||
Some(Duration::min(delayduration01.unwrap(),delayduration02.unwrap()))
|
||||
} else { delayduration01 }
|
||||
|
||||
};
|
||||
|
||||
|
||||
botlog::trace(
|
||||
format!(
|
||||
"[TRACE][Routine Processing] {} in {} > Delay Duration - {:?} ",
|
||||
trg_routine_ar.read().await.name,
|
||||
trg_routine_ar.read().await.channel.0 ,
|
||||
delayduration ,
|
||||
)
|
||||
.as_str(),
|
||||
Some(format!(
|
||||
"Routine > start() > (In Tokio Spawn) > {:?}",
|
||||
trg_routine_ar.read().await.module
|
||||
)),
|
||||
Some(&trg_routine_ar.read().await.parent_params.msg),
|
||||
);
|
||||
|
||||
if let Some(dur) = delayduration {
|
||||
sleep(dur).await;
|
||||
}
|
||||
|
||||
|
||||
{ // [x] Prior to Loop that calls Custom Routine Execution Body
|
||||
let mut a = trg_routine_ar.write().await;
|
||||
a.start_time = Some(chrono::offset::Local::now());
|
||||
}
|
||||
|
||||
loop { // Routine loop
|
||||
loop { // [x] Routine loop
|
||||
|
||||
|
||||
// execution body
|
||||
// [x] execution body
|
||||
trg_routine_ar.read().await.loopbody().await;
|
||||
|
||||
|
||||
{ // End of Loop iteration
|
||||
{ // [x] End of Loop iteration
|
||||
let mut a = trg_routine_ar.write().await;
|
||||
a.complete_iterations += 1;
|
||||
if let Some(i) = a.remaining_iterations {
|
||||
|
@ -857,8 +967,8 @@ impl Routine {
|
|||
}
|
||||
}
|
||||
|
||||
// End of Loop Validation
|
||||
// These generally may include routine_attr related checks
|
||||
// [x]End of Loop Validation
|
||||
// These generally may include routine_attr related checks to , for example, break out of the loop
|
||||
|
||||
if trg_routine_ar.read().await.routine_attr.contains(&RoutineAttr::RunOnce) {
|
||||
if trg_routine_ar.read().await.complete_iterations > 0 { break; }
|
||||
|
|
|
@ -135,7 +135,7 @@ async fn test3_body(params : ExecBodyParams) {
|
|||
routine_attr,
|
||||
exec_body,
|
||||
params.clone()
|
||||
);
|
||||
).await;
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue