(cont) routine methods
This commit is contained in:
parent
60fae25419
commit
e963ae250d
2 changed files with 121 additions and 11 deletions
|
@ -35,6 +35,7 @@ use casual_logger::Log;
|
||||||
use chrono::DateTime;
|
use chrono::DateTime;
|
||||||
// use chrono::Duration;
|
// use chrono::Duration;
|
||||||
use chrono::Local;
|
use chrono::Local;
|
||||||
|
use chrono::OutOfRangeError;
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
@ -655,17 +656,25 @@ impl Routine {
|
||||||
|
|
||||||
// WORK IN PROGRESS VECTOR - Vec<$RoutineAttr>
|
// WORK IN PROGRESS VECTOR - Vec<$RoutineAttr>
|
||||||
|
|
||||||
let wip_attr:Vec<&RoutineAttr> = vec![
|
let wip_attr:Vec<RoutineAttr> = vec![
|
||||||
&RoutineAttr::RunOnce
|
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
|
// [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() {
|
if unimplemented.next().is_some() {
|
||||||
|
|
||||||
|
@ -690,6 +699,23 @@ impl Routine {
|
||||||
return Ok("Valid & Implemented Setup".to_string())
|
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();
|
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;
|
let mut a = trg_routine_ar.write().await;
|
||||||
a.start_time = Some(chrono::offset::Local::now());
|
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;
|
trg_routine_ar.read().await.loopbody().await;
|
||||||
|
|
||||||
|
|
||||||
{ // End of Loop iteration
|
{ // [x] End of Loop iteration
|
||||||
let mut a = trg_routine_ar.write().await;
|
let mut a = trg_routine_ar.write().await;
|
||||||
a.complete_iterations += 1;
|
a.complete_iterations += 1;
|
||||||
if let Some(i) = a.remaining_iterations {
|
if let Some(i) = a.remaining_iterations {
|
||||||
|
@ -857,8 +967,8 @@ impl Routine {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// End of Loop Validation
|
// [x]End of Loop Validation
|
||||||
// These generally may include routine_attr related checks
|
// 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.routine_attr.contains(&RoutineAttr::RunOnce) {
|
||||||
if trg_routine_ar.read().await.complete_iterations > 0 { break; }
|
if trg_routine_ar.read().await.complete_iterations > 0 { break; }
|
||||||
|
|
|
@ -135,7 +135,7 @@ async fn test3_body(params : ExecBodyParams) {
|
||||||
routine_attr,
|
routine_attr,
|
||||||
exec_body,
|
exec_body,
|
||||||
params.clone()
|
params.clone()
|
||||||
);
|
).await;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue