From 6c7290883f5bb09b6b2a98a6d9f8cc397ac42e1a Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Tue, 26 Mar 2024 11:29:47 -0400 Subject: [PATCH 01/23] (init) routine methods --- src/core/botmodules.rs | 126 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 124 insertions(+), 2 deletions(-) diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index c104fdd..5b725b8 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -30,9 +30,13 @@ use std::sync::Arc; use casual_logger::Log; +use chrono::DateTime; +use chrono::Duration; +use chrono::Local; use tokio::sync::RwLock; use async_trait::async_trait; +use tokio::task::JoinHandle; use crate::core::bot_actions::actions_util; use crate::core::bot_actions::ExecBodyParams; @@ -568,8 +572,126 @@ impl BotActionTrait for Listener { } } -#[derive(Debug)] -pub struct Routine {} + +enum RoutineAttr { + DelayedStart, + ScheduledStart(DateTime), // Scheduled Date (if any) after which, if not started, may trigger + LoopDuration(Duration), // How long to wait between iterations + LoopInfinitely, + RunOnce, + MaxTimeThreshold(DateTime), // DateTime after which, it will abort/cancel or stop + MaxIterations(i64), +} +/* + a Routine can be given different combinations of the above, but business logic may validate + these at Routine construction + + For example, a Routine could have the following characteristics + - DelayedStart (so it skips the first iteration) + - ScheduledStart(DateTime) - With a Start Date-Time for the first iteration to trigger + - LoopDuration(Duration) - How long to wait between iterations + + The above without any other thresholds would loop infinitely with the above characteristics + + Another example, + - LoopDuration(Duration) - How long to wait between iterations + - MaxTimeThreshold(DateTime) + - MaxIterations(i64) + + The above has thresholds , so if either are reached, it would abort/cancel or stop . Since there is no + ScheduledStart, the routine would have to be started manually elsewhere + + Another example , + - (no RoutineAttr) + + The above would only run once, and only when the Start() is called + +*/ + +// #[derive(Debug)] +pub struct Routine { + // pub name : String , + module : BotModule , // from() can determine this if passed parents_params + // pub channel : Option , // Routines generally run by Channel ; but can be left None + channel : Channel , // Requiring some channel context + exec_body: bot_actions::actions_util::ExecBody, + parent_params : Option , + join_handle : Option> , + complete_iterations : i64 , + remaining_iterations : i64 , + start_time : Option> , + routine_attr : Vec , +} + + +impl Routine { + + // Constructor + pub fn from( + _module : BotModule , + _channel : Channel, + _exec_body : bot_actions::actions_util::ExecBody , + _parent_params : Option + ) -> Result { + + // [ ] Validation is made against parent_params + // to ensure those params don't conflict + // conlicts would throw an error + + Err("NOT IMPLEMENTED".to_string()) + } + + pub fn change_channel( + &self, + _channel : Channel + ) -> Result { + // [ ] Think Ideally it should try to + // change the target channel of the + // internal process too if possible? + + Err("NOT IMPLEMENTED".to_string()) + } + + + pub fn start(&self) -> Result + { + + // [ ] Asyncio Spawn likely around here + // [ ] & Assigns self.join_handle + + Err("NOT IMPLEMENTED".to_string()) + } + + pub fn stop(&self) -> Result + { + Err("NOT IMPLEMENTED".to_string()) + } + + pub fn restart( + &self, + _force : bool + ) -> Result + { + // force flag aborts the routine immediately (like cancel()) + Err("NOT IMPLEMENTED".to_string()) + } + + pub fn cancel(&self) -> Result + { + + // [ ] Likely calls abort() + // Related : + // https://docs.rs/tokio/latest/tokio/task/struct.JoinHandle.html#method.abort + + Err("NOT IMPLEMENTED".to_string()) + } + + + +} + + + type StatusdbEntry = (ModGroup, Vec); type ModuleActions = Vec>>; -- 2.46.1 From 2ba92388a276e92de220d784010d4145d014bf40 Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Tue, 26 Mar 2024 14:30:13 -0400 Subject: [PATCH 02/23] runonce implementation --- src/core/botmodules.rs | 133 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 119 insertions(+), 14 deletions(-) diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index 5b725b8..a752ad5 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -31,13 +31,16 @@ use std::sync::Arc; use casual_logger::Log; use chrono::DateTime; -use chrono::Duration; +// use chrono::Duration; use chrono::Local; use tokio::sync::RwLock; use async_trait::async_trait; use tokio::task::JoinHandle; +use tokio::time::Instant; +use tokio::time::{sleep, Duration}; + use crate::core::bot_actions::actions_util; use crate::core::bot_actions::ExecBodyParams; use crate::core::botinstance::{BotInstance, Channel,ChangeResult}; @@ -572,8 +575,9 @@ impl BotActionTrait for Listener { } } - -enum RoutineAttr { +// #[derive(Debug, PartialEq, Eq, Hash, Clone)] +#[derive(PartialEq, Eq, Hash)] +pub enum RoutineAttr { DelayedStart, ScheduledStart(DateTime), // Scheduled Date (if any) after which, if not started, may trigger LoopDuration(Duration), // How long to wait between iterations @@ -610,16 +614,17 @@ enum RoutineAttr { // #[derive(Debug)] pub struct Routine { - // pub name : String , + pub name : String , module : BotModule , // from() can determine this if passed parents_params // pub channel : Option , // Routines generally run by Channel ; but can be left None channel : Channel , // Requiring some channel context exec_body: bot_actions::actions_util::ExecBody, - parent_params : Option , + // parent_params : Option , + parent_params : ExecBodyParams , join_handle : Option> , - complete_iterations : i64 , - remaining_iterations : i64 , start_time : Option> , + complete_iterations : i64 , + remaining_iterations : Option , routine_attr : Vec , } @@ -628,16 +633,37 @@ impl Routine { // Constructor pub fn from( - _module : BotModule , - _channel : Channel, - _exec_body : bot_actions::actions_util::ExecBody , - _parent_params : Option - ) -> Result { + name : String , + module : BotModule , + channel : Channel, + routine_attr : Vec , + exec_body : bot_actions::actions_util::ExecBody , + // parent_params : Option + parent_params : ExecBodyParams + // ) -> Result { + ) -> Result { // [ ] Validation is made against parent_params // to ensure those params don't conflict // conlicts would throw an error + // parent_params.unwrap(). + + if routine_attr.contains(&RoutineAttr::RunOnce) { + return Ok(Routine { + name , + module , + channel , + exec_body , + parent_params , + join_handle : None , + start_time : None , + complete_iterations : 0 , + remaining_iterations : None , + routine_attr : routine_attr + }) ; + } + Err("NOT IMPLEMENTED".to_string()) } @@ -652,16 +678,95 @@ impl Routine { Err("NOT IMPLEMENTED".to_string()) } - - pub fn start(&self) -> Result + pub async fn start(self) -> Result { // [ ] Asyncio Spawn likely around here // [ ] & Assigns self.join_handle + + let self_rw = Arc::new(RwLock::new(self)); + let mut self_wr_lock = self_rw.write().await; + + if self_wr_lock.routine_attr.contains(&RoutineAttr::RunOnce) { + self_wr_lock.remaining_iterations = Some(1); + + fn innerhelper(self_rw : Arc>) -> Option> { + Some( + tokio::spawn(async move { + + + let mut self_wr_lock = self_rw.write().await; + let mut remainingiter = self_wr_lock.remaining_iterations.unwrap(); + + + + botlog::trace( + format!( + "[TRACE][Routine Started] {} in {}", + self_wr_lock.name,self_wr_lock.channel.0 + ) + .as_str(), + Some(format!( + "Routine > start() > (In Tokio Spawn) > {:?}", + self_wr_lock.module + )), + Some(&self_wr_lock.parent_params.msg), + ); + + self_wr_lock.start_time = Some(chrono::offset::Local::now()); + + + // Loop iteration + while remainingiter > 1 { + + // execution body + self_wr_lock.loopbody().await; + + // end of loop iteration + remainingiter -= 1; + { + self_wr_lock.remaining_iterations = Some(remainingiter); + self_wr_lock.complete_iterations += 1; + } + + } + + botlog::trace( + format!( + "[TRACE][Routine Completed] {} in {}", + self_wr_lock.name,self_wr_lock.channel.0 + ) + .as_str(), + Some(format!( + "Routine > start() > (In Tokio Spawn) > {:?}", + self_wr_lock.module + )), + Some(&self_wr_lock.parent_params.msg), + ); + + + })) + } + + self_wr_lock.join_handle = innerhelper(self_rw.clone()) ; + return Ok("Successfully Started Routine".to_string()); + } + + + + Err("NOT IMPLEMENTED".to_string()) } + + async fn loopbody(&self) + { + (self.exec_body)( + self.parent_params.clone() + ).await; + } + pub fn stop(&self) -> Result { Err("NOT IMPLEMENTED".to_string()) -- 2.46.1 From 4e9316ad49576c820564e03b1f479b6c8f73f89c Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Tue, 26 Mar 2024 16:56:30 -0400 Subject: [PATCH 03/23] (init) experiment test module --- src/core/bot_actions.rs | 53 ++++- src/core/botmodules.rs | 89 +++++++- src/core/chat.rs | 6 +- src/custom/experimental.rs | 2 + src/custom/experimental/experiment003.rs | 277 +++++++++++++++++++++++ 5 files changed, 413 insertions(+), 14 deletions(-) create mode 100644 src/custom/experimental/experiment003.rs diff --git a/src/core/bot_actions.rs b/src/core/bot_actions.rs index 8941654..8b88c2a 100644 --- a/src/core/bot_actions.rs +++ b/src/core/bot_actions.rs @@ -5,7 +5,7 @@ use tokio::sync::RwLock; use crate::core::botinstance::BotInstance; -use super::{botmodules::{BotAction, BotModule}, identity::ChatBadge}; +use super::{botinstance::Channel, botmodules::{BotAction, BotModule}, identity::ChatBadge}; pub type BotAR = Arc>; @@ -21,24 +21,63 @@ pub struct ExecBodyParams { impl ExecBodyParams { - pub async fn get_parent_module(&self) -> Option { + // pub async fn get_parent_module(&self) -> Option { + pub async fn get_parent_module(&self) -> BotModule { let parent_act = Arc::clone(&self.parent_act); let parent_act_lock = parent_act.read().await; let act = &(*parent_act_lock); match act { BotAction::C(c) => { - let temp = c.module.clone(); - Some(temp) + // let temp = c.module.clone(); + // Some(temp) + c.module.clone() }, BotAction::L(l) => { - let temp = l.module.clone(); - Some(temp) + // let temp = l.module.clone(); + // Some(temp) + l.module.clone() }, - _ => None + BotAction::R(r) => { + // let temp = r.module.clone(); + // Some(temp) + r.module.clone() + } + // _ => None } } + pub async fn get_routine_channel(&self) -> Option { + + // THIS IS INCORRECT - BELOW MAY BE PULLING THE PARENT BOTACTION + // NOT THE CURRENT BOT ACTION + + let parent_act = Arc::clone(&self.parent_act); + let parent_act_lock = parent_act.read().await; + let act = &(*parent_act_lock); + match act { + BotAction::C(_) => { + // let temp = c.module.clone(); + // Some(temp) + None + }, + BotAction::L(_) => { + // let temp = l.module.clone(); + // Some(temp) + // l.module.clone() + None + }, + BotAction::R(r) => { + // let temp = r.module.clone(); + // Some(temp) + Some(r.channel.clone()) + } + // _ => None + } + } + + + pub fn get_sender(&self) -> String { self.msg.sender.name.clone() } diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index a752ad5..f327266 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -615,9 +615,9 @@ pub enum RoutineAttr { // #[derive(Debug)] pub struct Routine { pub name : String , - module : BotModule , // from() can determine this if passed parents_params + pub module : BotModule , // from() can determine this if passed parents_params // pub channel : Option , // Routines generally run by Channel ; but can be left None - channel : Channel , // Requiring some channel context + pub channel : Channel , // Requiring some channel context exec_body: bot_actions::actions_util::ExecBody, // parent_params : Option , parent_params : ExecBodyParams , @@ -664,6 +664,7 @@ impl Routine { }) ; } + Err("NOT IMPLEMENTED".to_string()) } @@ -685,6 +686,7 @@ impl Routine { // [ ] & Assigns self.join_handle + let self_rw = Arc::new(RwLock::new(self)); let mut self_wr_lock = self_rw.write().await; @@ -746,15 +748,31 @@ impl Routine { ); + Log::flush(); })) } self_wr_lock.join_handle = innerhelper(self_rw.clone()) ; return Ok("Successfully Started Routine".to_string()); + } + botlog::trace( + format!( + "[ERROR][Routine NOT IMPLEMENTED] {} in {}", + self_wr_lock.name,self_wr_lock.channel.0 + ) + .as_str(), + Some(format!( + "Routine > start() > (In Tokio Spawn) > {:?}", + self_wr_lock.module + )), + Some(&self_wr_lock.parent_params.msg), + ); + + Log::flush(); Err("NOT IMPLEMENTED".to_string()) } @@ -767,27 +785,88 @@ impl Routine { ).await; } - pub fn stop(&self) -> Result + pub async fn stop(&self) -> Result { + + + let self_rw = Arc::new(RwLock::new(self)); + let self_lock = self_rw.read().await; + + + botlog::trace( + format!( + "[ERROR][Routine NOT IMPLEMENTED] {} in {}", + self_lock.name,self_lock.channel.0 + ) + .as_str(), + Some(format!( + "Routine > start() > (In Tokio Spawn) > {:?}", + self_lock.module + )), + Some(&self_lock.parent_params.msg), + ); + + Log::flush(); + Err("NOT IMPLEMENTED".to_string()) } - pub fn restart( + pub async fn restart( &self, _force : bool ) -> Result { // force flag aborts the routine immediately (like cancel()) + + + let self_rw = Arc::new(RwLock::new(self)); + let self_lock = self_rw.read().await; + + + botlog::trace( + format!( + "[ERROR][Routine NOT IMPLEMENTED] {} in {}", + self_lock.name,self_lock.channel.0 + ) + .as_str(), + Some(format!( + "Routine > start() > (In Tokio Spawn) > {:?}", + self_lock.module + )), + Some(&self_lock.parent_params.msg), + ); + + Log::flush(); Err("NOT IMPLEMENTED".to_string()) } - pub fn cancel(&self) -> Result + pub async fn cancel(&self) -> Result { // [ ] Likely calls abort() // Related : // https://docs.rs/tokio/latest/tokio/task/struct.JoinHandle.html#method.abort + + + let self_rw = Arc::new(RwLock::new(self)); + let self_lock = self_rw.read().await; + + + botlog::trace( + format!( + "[ERROR][Routine NOT IMPLEMENTED] {} in {}", + self_lock.name,self_lock.channel.0 + ) + .as_str(), + Some(format!( + "Routine > start() > (In Tokio Spawn) > {:?}", + self_lock.module + )), + Some(&self_lock.parent_params.msg), + ); + + Log::flush(); Err("NOT IMPLEMENTED".to_string()) } diff --git a/src/core/chat.rs b/src/core/chat.rs index bb938cc..d0b85e6 100644 --- a/src/core/chat.rs +++ b/src/core/chat.rs @@ -108,7 +108,8 @@ impl Chat { let botlock = botclone.read().await; let modmgr = Arc::clone(&botlock.botmodules); let modstatus = (*modmgr).modstatus( - parent_module.clone().expect("ERROR - Expected a module"), + // parent_module.clone().expect("ERROR - Expected a module"), + parent_module.clone(), Channel(channel_login.clone()) ).await; @@ -180,7 +181,8 @@ impl Chat { self.send_botmsg(BotMsgType::Notif( format!("uuh {:?} is disabled on {} : {:?}", - parent_module.clone().unwrap(), + // parent_module.clone().unwrap(), + parent_module.clone(), channel_login.clone(), lvl ), diff --git a/src/custom/experimental.rs b/src/custom/experimental.rs index 409abd1..7da2ecb 100644 --- a/src/custom/experimental.rs +++ b/src/custom/experimental.rs @@ -12,6 +12,7 @@ pub use crate::core::botmodules::ModulesManager; mod experiment001; mod experiment002; +mod experiment003; // [ ] init() function that accepts bot instance - this is passed to init() on submodules @@ -21,4 +22,5 @@ pub async fn init(mgr: Arc) { experiment001::init(Arc::clone(&mgr)).await; experiment002::init(Arc::clone(&mgr)).await; + experiment003::init(Arc::clone(&mgr)).await; } diff --git a/src/custom/experimental/experiment003.rs b/src/custom/experimental/experiment003.rs new file mode 100644 index 0000000..0bb98b9 --- /dev/null +++ b/src/custom/experimental/experiment003.rs @@ -0,0 +1,277 @@ +/* + Custom Modules - + + Usage : + [ ] within the file's init(), define BotActions & Load them into the ModulesManager + [ ] Define Execution Bodies for these BotActions + [ ] Afterwards, add the following to parent modules.rs file + - mod ; + - within init(), ::init(mgr).await + +*/ + + +const OF_CMD_CHANNEL:Channel = Channel(String::new()); + + +use casual_logger::Log; +use rand::Rng; +use std::sync::Arc; + +use crate::core::bot_actions::ExecBodyParams; +use crate::core::botinstance::Channel; +use crate::core::botlog; + +use crate::core::bot_actions::actions_util; +use crate::core::botmodules::{BotAction, BotActionTrait, BotCommand, BotModule, Listener, ModulesManager, Routine, RoutineAttr}; + +use crate::core::identity::UserRole::*; + +use tokio::time::{sleep, Duration}; + +pub async fn init(mgr: Arc) { + + // 1. Define the BotAction + let botc1 = BotCommand { + module: BotModule(String::from("experiments003")), + command: String::from("test3"), // command call name + alias: vec![], // String of alternative names + exec_body: actions_util::asyncbox(test3_body), + help: String::from("Test Command tester"), + required_roles: vec![ + BotAdmin, + Mod(OF_CMD_CHANNEL), + ], + }; + + // 2. Add the BotAction to ModulesManager + botc1.add_to_modmgr(Arc::clone(&mgr)).await; + + +} + + +async fn test3_body(params : ExecBodyParams) { + // println!("testy triggered!"); // NOTE : This test function intends to print (e.g., to stdout) at fn call + botlog::debug( + "testy triggered!", + Some("Experiments003 > test3 command body".to_string()), + Some(¶ms.msg), + ); + + /* + Test Routine Start() by : + 1. In this single exec body , create a Routine + 2. Create a Routine Execution Body + 3. Pass the Execution Body & Routine Attributes to create the Routine + 4. Start the Routine + 5. For RunOnce , we should see it only trigger once, and then complete in the logs + + */ + + // [x] Get the module from params + + let parentmodule = params.get_parent_module().await; + let channel = params.get_routine_channel().await; + let routine_attr = vec![ + RoutineAttr::RunOnce + ]; + let exec_body = actions_util::asyncbox(rtestbody); + let parent_params = params.clone(); + + async fn rtestbody(params : ExecBodyParams) { + + let bot = Arc::clone(¶ms.bot); + + let botlock = bot.read().await; + + // uses chat.say_in_reply_to() for the bot controls for messages + botlock + .botmgrs + .chat + .say_in_reply_to( + ¶ms.msg.clone(), + String::from("Inner Routine Loop Message"), + params.clone() + ).await; + } + + let a = Routine::from( + "Routine Test".to_string(), + parentmodule, + channel.unwrap(), + routine_attr, + exec_body, + parent_params + ); + + if let Ok(newr) = a { + let rslt = newr.start().await; + + + botlog::debug( + format!("TEST3_BODY RESULT : {:?}", + rslt + ).as_str(), + Some("experiment003 > test3_body".to_string()), + Some(¶ms.msg), + ); + + + let bot = Arc::clone(¶ms.bot); + + let botlock = bot.read().await; + + // uses chat.say_in_reply_to() for the bot controls for messages + botlock + .botmgrs + .chat + .say_in_reply_to( + ¶ms.msg, + format!("Routine Result : {:?}",rslt), + params.clone() + ).await; + + + } + + + + + Log::flush(); +} + + + + + +async fn good_girl(params : ExecBodyParams) { + + // [ ] Uses gen_ratio() to output bool based on a ratio probability . + // - For example gen_ratio(2,3) is 2 out of 3 or 0.67% (numerator,denomitator) + // - More Info : https://rust-random.github.io/rand/rand/trait.Rng.html#method.gen_ratio + + if params.msg.sender.name.to_lowercase() == "ModulatingForce".to_lowercase() + || params.msg.sender.name.to_lowercase() == "mzNToRi".to_lowercase() + { + botlog::debug( + "Good Girl Detected > Pausechamp", + Some("experiments > goodgirl()".to_string()), + Some(¶ms.msg), + ); + + let rollwin = rand::thread_rng().gen_ratio(1, 10); + + if rollwin { + botlog::debug( + "Oh that's a good girl!", + Some("experiments > goodgirl()".to_string()), + Some(¶ms.msg), + ); + + let bot = Arc::clone(¶ms.bot); + + + let botlock = bot.read().await; + + // uses chat.say_in_reply_to() for the bot controls for messages + botlock + .botmgrs + .chat + .say_in_reply_to( + ¶ms.msg, + String::from("GoodGirl xdd "), + params.clone() + ).await; + + + } + } +} + +async fn testy(params : ExecBodyParams) { + println!("testy triggered!"); // NOTE : This test function intends to print (e.g., to stdout) at fn call + botlog::debug( + "testy triggered!", + Some("experiments > testy()".to_string()), + Some(¶ms.msg), + ); +} + + +async fn babygirl(params : ExecBodyParams) { + + + println!("babygirl triggered!"); // NOTE : This test function intends to print (e.g., to stdout) at fn call + botlog::debug( + "babygirl triggered!", + Some("experiments > babygirl()".to_string()), + Some(¶ms.msg), + ); + + + let bot = Arc::clone(¶ms.bot); + + let botlock = bot.read().await; + + + botlock + .botmgrs + .chat + .say_in_reply_to( + ¶ms.msg, + String::from("16:13 notohh: cafdk"), + params.clone() + ).await; + + + sleep(Duration::from_secs_f64(0.5)).await; + + botlock + .botmgrs + .chat + .say_in_reply_to( + ¶ms.msg, + String::from("16:13 notohh: have fun eating princess"), + params.clone() + ).await; + + + sleep(Duration::from_secs_f64(2.0)).await; + + botlock + .botmgrs + .chat + .say_in_reply_to( + ¶ms.msg, + String::from("16:13 notohh: baby girl"), + params.clone() + ).await; + + + +} + + +async fn routinelike(params : ExecBodyParams) { + println!("routinelike triggered!"); // NOTE : This test function intends to print (e.g., to stdout) at fn call + botlog::debug( + "routinelike triggered!", + Some("experiments > routinelike()".to_string()), + Some(¶ms.msg), + ); + + // spawn an async block that runs independently from others + + tokio::spawn( async { + for _ in 0..5 { + println!(">> Innterroutine triggered!"); + sleep(Duration::from_secs_f64(5.0)).await; + } + } + ); + + // lines are executed after in conjunction to the spawn + +} + -- 2.46.1 From 5249c3af250f5de7841bf2fce801e93003bf2ece Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Wed, 27 Mar 2024 01:29:09 -0400 Subject: [PATCH 04/23] smol debug in identity --- src/core/identity.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/core/identity.rs b/src/core/identity.rs index dc2da72..e1500eb 100644 --- a/src/core/identity.rs +++ b/src/core/identity.rs @@ -553,7 +553,16 @@ async fn getroles(params : ExecBodyParams) { let arg1 = argv.next(); let targetuser = match arg1 { - None => return, // exit if no arguments + None => { + + botlog::debug( + "Exittingcmd getroles - Invalid arguments ", + Some("identity.rs > init > getroles()".to_string()), + Some(¶ms.msg), + ); + return + + }, // exit if no arguments Some(arg) => arg, }; -- 2.46.1 From 3f8e798050928229a00835bab807e8197c511915 Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Wed, 27 Mar 2024 01:29:25 -0400 Subject: [PATCH 05/23] (cont) routine start --- src/core/bot_actions.rs | 25 +++--- src/core/botinstance.rs | 10 +-- src/core/botmodules.rs | 99 +++++++++++++++++------- src/core/chat.rs | 2 +- src/custom/experimental/experiment003.rs | 78 ++++++++++++++++--- 5 files changed, 160 insertions(+), 54 deletions(-) diff --git a/src/core/bot_actions.rs b/src/core/bot_actions.rs index 8b88c2a..a88e5de 100644 --- a/src/core/bot_actions.rs +++ b/src/core/bot_actions.rs @@ -15,17 +15,19 @@ pub type ActAR = Arc>; pub struct ExecBodyParams { pub bot : BotAR, pub msg : PrivmsgMessage, - pub parent_act : ActAR , + // pub parent_act : ActAR , + pub curr_act : ActAR , } impl ExecBodyParams { // pub async fn get_parent_module(&self) -> Option { - pub async fn get_parent_module(&self) -> BotModule { + // pub async fn get_parent_module(&self) -> BotModule { + pub async fn get_module(&self) -> BotModule { - let parent_act = Arc::clone(&self.parent_act); - let parent_act_lock = parent_act.read().await; + let curr_act = Arc::clone(&self.curr_act); + let parent_act_lock = curr_act.read().await; let act = &(*parent_act_lock); match act { BotAction::C(c) => { @@ -41,36 +43,37 @@ impl ExecBodyParams { BotAction::R(r) => { // let temp = r.module.clone(); // Some(temp) - r.module.clone() + r.read().await.module.clone() } // _ => None } } - pub async fn get_routine_channel(&self) -> Option { + pub async fn get_channel(&self) -> Option { // THIS IS INCORRECT - BELOW MAY BE PULLING THE PARENT BOTACTION // NOT THE CURRENT BOT ACTION - let parent_act = Arc::clone(&self.parent_act); - let parent_act_lock = parent_act.read().await; + + let curr_act = Arc::clone(&self.curr_act); + let parent_act_lock = curr_act.read().await; let act = &(*parent_act_lock); match act { BotAction::C(_) => { // let temp = c.module.clone(); // Some(temp) - None + Some(Channel(self.msg.channel_login.clone())) }, BotAction::L(_) => { // let temp = l.module.clone(); // Some(temp) // l.module.clone() - None + Some(Channel(self.msg.channel_login.clone())) }, BotAction::R(r) => { // let temp = r.module.clone(); // Some(temp) - Some(r.channel.clone()) + Some(r.read().await.channel.clone()) } // _ => None } diff --git a/src/core/botinstance.rs b/src/core/botinstance.rs index 07b481d..563856f 100644 --- a/src/core/botinstance.rs +++ b/src/core/botinstance.rs @@ -404,7 +404,7 @@ impl BotInstance { let params = ExecBodyParams { bot : Arc::clone(&bot), msg : (*msg).clone(), - parent_act : Arc::clone(&act_clone), + curr_act : Arc::clone(&act_clone), }; // When sending a BotMsgTypeNotif, send_botmsg does Roles related validation as required @@ -461,7 +461,7 @@ impl BotInstance { let params = ExecBodyParams { bot : Arc::clone(&bot), msg : (*msg).clone(), - parent_act : Arc::clone(&act_clone), + curr_act : Arc::clone(&act_clone), }; @@ -491,7 +491,7 @@ impl BotInstance { let params = ExecBodyParams { bot : Arc::clone(&bot), msg : (*msg).clone(), - parent_act : Arc::clone(&act_clone), + curr_act : Arc::clone(&act_clone), }; @@ -516,7 +516,7 @@ impl BotInstance { c.execute(ExecBodyParams { bot : a, msg : msg.clone() , - parent_act : Arc::clone(&act_clone), + curr_act : Arc::clone(&act_clone), }).await; botlog::trace( @@ -564,7 +564,7 @@ impl BotInstance { l.execute(ExecBodyParams { bot : a, msg : msg.clone() , - parent_act : Arc::clone(&act_clone), + curr_act : Arc::clone(&act_clone), } ).await; } diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index f327266..34c6b02 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -469,7 +469,8 @@ pub enum StatusType { pub enum BotAction { C(BotCommand), L(Listener), - R(Routine), + // R(Routine), + R(Arc>), } impl BotAction { @@ -621,7 +622,7 @@ pub struct Routine { exec_body: bot_actions::actions_util::ExecBody, // parent_params : Option , parent_params : ExecBodyParams , - join_handle : Option> , + pub join_handle : Option> , start_time : Option> , complete_iterations : i64 , remaining_iterations : Option , @@ -641,7 +642,11 @@ impl Routine { // parent_params : Option parent_params : ExecBodyParams // ) -> Result { - ) -> Result { + // ) -> Result { + ) -> Result< + Arc>, + String + > { // [ ] Validation is made against parent_params // to ensure those params don't conflict @@ -650,7 +655,7 @@ impl Routine { // parent_params.unwrap(). if routine_attr.contains(&RoutineAttr::RunOnce) { - return Ok(Routine { + return Ok(Arc::new(RwLock::new(Routine { name , module , channel , @@ -661,7 +666,7 @@ impl Routine { complete_iterations : 0 , remaining_iterations : None , routine_attr : routine_attr - }) ; + }))) ; } @@ -679,57 +684,80 @@ impl Routine { Err("NOT IMPLEMENTED".to_string()) } - pub async fn start(self) -> Result + // pub async fn start(self) -> Result + // pub async fn start(self : &mut Self) -> Result + pub async fn start( + trg_routine_ar : Arc> + ) -> Result { // [ ] Asyncio Spawn likely around here // [ ] & Assigns self.join_handle + // let self_rw = Arc::new(RwLock::new(self)); + // let mut self_wr_lock = self_rw.write().await; + // let self_ar = Arc::new(RwLock::new(trg_routine_ar)); - let self_rw = Arc::new(RwLock::new(self)); - let mut self_wr_lock = self_rw.write().await; - if self_wr_lock.routine_attr.contains(&RoutineAttr::RunOnce) { - self_wr_lock.remaining_iterations = Some(1); + if trg_routine_ar.read().await.routine_attr.contains(&RoutineAttr::RunOnce) { + // if self_wr_lock.routine_attr.contains(&RoutineAttr::RunOnce) { + // let = self_wr_lock.remaining_iterations + + // let mut self_wr_lock = self_rw.write().await; + + + // let self_rw_copy = Arc::new(self); + // let self_rw_copy = Arc::clone(&self_rw); + // let mut a = *(*self_wr_lock); + // a.remaining_iterations = Some(1); + // (*self_wr_lock).remaining_iterations = Some(1); + // let routine = *self_rw_copy.read().await; + + // fn innerhelper(self_rw : Arc>) -> Option> { + // fn innerhelper(self_rw : Arc>) -> Option> { + // fn innerhelper(inroutine : &Routine) -> Option> { + // fn innerhelper(inroutine : Routine) -> Option> { + fn innerhelper(inroutine : Arc>) -> Option> { - fn innerhelper(self_rw : Arc>) -> Option> { Some( tokio::spawn(async move { - let mut self_wr_lock = self_rw.write().await; - let mut remainingiter = self_wr_lock.remaining_iterations.unwrap(); + // let mut self_wr_lock = self_rw.write().await; + // let mut remainingiter = self_wr_lock.remaining_iterations.unwrap(); + let mut remainingiter = inroutine.write().await.remaining_iterations.unwrap_or(0); botlog::trace( format!( "[TRACE][Routine Started] {} in {}", - self_wr_lock.name,self_wr_lock.channel.0 + inroutine.read().await.name, + inroutine.read().await.channel.0 ) .as_str(), Some(format!( "Routine > start() > (In Tokio Spawn) > {:?}", - self_wr_lock.module + inroutine.read().await.module )), - Some(&self_wr_lock.parent_params.msg), + Some(&inroutine.read().await.parent_params.msg), ); - self_wr_lock.start_time = Some(chrono::offset::Local::now()); + inroutine.write().await.start_time = Some(chrono::offset::Local::now()); // Loop iteration while remainingiter > 1 { // execution body - self_wr_lock.loopbody().await; + inroutine.read().await.loopbody().await; // end of loop iteration remainingiter -= 1; { - self_wr_lock.remaining_iterations = Some(remainingiter); - self_wr_lock.complete_iterations += 1; + inroutine.write().await.remaining_iterations = Some(remainingiter); + inroutine.write().await.complete_iterations += 1; } } @@ -737,14 +765,15 @@ impl Routine { botlog::trace( format!( "[TRACE][Routine Completed] {} in {}", - self_wr_lock.name,self_wr_lock.channel.0 + inroutine.read().await.name, + inroutine.read().await.channel.0 ) .as_str(), Some(format!( "Routine > start() > (In Tokio Spawn) > {:?}", - self_wr_lock.module + inroutine.read().await.module )), - Some(&self_wr_lock.parent_params.msg), + Some(&inroutine.read().await.parent_params.msg), ); @@ -752,7 +781,20 @@ impl Routine { })) } - self_wr_lock.join_handle = innerhelper(self_rw.clone()) ; + + // let self_rw = Arc::new(RwLock::new(self)); + // let mut self_wr_lock = self_rw.write().await; + + // self_wr_lock.join_handle = innerhelper(&routine) ; + + // let mut routine = self_rw_copy.write().await; + // (**routine).join_handle = innerhelper(*routine); + // routine.join_handle = innerhelper(*routine); + // let routine = *self_rw_copy.read().await; + // self_rw_copy.write().await.join_handle = innerhelper(&routine); + // let self_ref = Arc::clone(&trg_routine_ar); + trg_routine_ar.write().await.join_handle = innerhelper(trg_routine_ar.clone()); + return Ok("Successfully Started Routine".to_string()); } @@ -762,14 +804,17 @@ impl Routine { botlog::trace( format!( "[ERROR][Routine NOT IMPLEMENTED] {} in {}", - self_wr_lock.name,self_wr_lock.channel.0 + // self_wr_lock.name,self_wr_lock.channel.0 + trg_routine_ar.read().await.name, + trg_routine_ar.read().await.channel.0 ) .as_str(), Some(format!( "Routine > start() > (In Tokio Spawn) > {:?}", - self_wr_lock.module + // self_wr_lock.module + trg_routine_ar.read().await.module )), - Some(&self_wr_lock.parent_params.msg), + Some(&trg_routine_ar.read().await.parent_params.msg), ); Log::flush(); diff --git a/src/core/chat.rs b/src/core/chat.rs index d0b85e6..a83bd8c 100644 --- a/src/core/chat.rs +++ b/src/core/chat.rs @@ -101,7 +101,7 @@ impl Chat { Some(¶ms.msg), ); - let parent_module = params.get_parent_module().await; + let parent_module = params.get_module().await; let params_clone = params.clone(); let botclone = Arc::clone(¶ms_clone.bot); diff --git a/src/custom/experimental/experiment003.rs b/src/custom/experimental/experiment003.rs index 0bb98b9..1e25591 100644 --- a/src/custom/experimental/experiment003.rs +++ b/src/custom/experimental/experiment003.rs @@ -16,6 +16,7 @@ const OF_CMD_CHANNEL:Channel = Channel(String::new()); use casual_logger::Log; use rand::Rng; +use tokio::sync::RwLock; use std::sync::Arc; use crate::core::bot_actions::ExecBodyParams; @@ -71,13 +72,19 @@ async fn test3_body(params : ExecBodyParams) { // [x] Get the module from params - let parentmodule = params.get_parent_module().await; - let channel = params.get_routine_channel().await; + // let parentmodule = params.get_parent_module().await; + let module = params.get_module().await; + let channel = params.get_channel().await; let routine_attr = vec![ RoutineAttr::RunOnce ]; - let exec_body = actions_util::asyncbox(rtestbody); - let parent_params = params.clone(); + // let exec_body = actions_util::asyncbox(rtestbody); + let exec_body = actions_util::asyncbox(rtestbody); // <-- 03.27 - when below is uncommented, this is throwing an issue + + + // let parent_params = params.clone(); + // let params_clone = params.clone(); + async fn rtestbody(params : ExecBodyParams) { @@ -94,19 +101,64 @@ async fn test3_body(params : ExecBodyParams) { String::from("Inner Routine Loop Message"), params.clone() ).await; + + let logmsg_botact = match *params.curr_act.read().await { + BotAction::C(_) => "command", + BotAction::R(_) => "routine", + BotAction::L(_) => "listener", + } ; + + botlog::trace( + // format!("Params > Curr_act : {:?}", params.curr_act).as_str(), // BotAction doesn't imblement debug + format!("Params > Curr_act type : {:?}", logmsg_botact).as_str(), + Some("Experiments003 > test3 command body".to_string()), + Some(¶ms.msg), + ); + Log::flush(); } + botlog::debug( + format!("TEST3_BODY BEFORE FROM CALL : module - {:?} ; channel - {:?}", + module,channel + ).as_str(), + Some("experiment003 > test3_body".to_string()), + Some(¶ms.msg), + ); + + + let a = Routine::from( "Routine Test".to_string(), - parentmodule, + module, channel.unwrap(), routine_attr, exec_body, - parent_params + params.clone() ); + + if let Ok(newr) = a { - let rslt = newr.start().await; + + // [ ] before execute , be sure to adjust curr_act + + let mut params_mut = params.clone(); + // let newr_ar = Arc::new(RwLock::new(newr)); + let newr_ar = newr.clone(); + + params_mut.curr_act = Arc::new(RwLock::new( + BotAction::R(newr_ar.clone()) + )); + + // let a = newr_ar.read().await; + // let rslt = (&*a).start().await; + + // let mut newr_lock = newr_ar.write().await; + + // let rslt = newr_ar.write().await.start().await; + let rslt = Routine::start(newr_ar.clone()).await; + + // let rslt = newr_ar.read().await.start().await; botlog::debug( @@ -117,7 +169,8 @@ async fn test3_body(params : ExecBodyParams) { Some(¶ms.msg), ); - + Log::flush(); + let bot = Arc::clone(¶ms.bot); let botlock = bot.read().await; @@ -132,13 +185,18 @@ async fn test3_body(params : ExecBodyParams) { params.clone() ).await; + newr.clone().write().await.join_handle.take().expect("Issue with join handle").await.unwrap(); + + // newr.read().await.join_handle.unwrap().await.unwrap(); + + } - - Log::flush(); + + } -- 2.46.1 From b08d91af5d2c67a54f1921aee5640523c09aad22 Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Wed, 27 Mar 2024 10:18:13 -0400 Subject: [PATCH 06/23] (cont) start runonce --- src/core/botmodules.rs | 260 ++++++++++++++++++++--- src/custom/experimental/experiment003.rs | 9 +- 2 files changed, 237 insertions(+), 32 deletions(-) diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index 34c6b02..0e6dfc2 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -688,7 +688,8 @@ impl Routine { // pub async fn start(self : &mut Self) -> Result pub async fn start( trg_routine_ar : Arc> - ) -> Result + // ) -> Result +) -> Result>,String> { // [ ] Asyncio Spawn likely around here @@ -718,50 +719,228 @@ impl Routine { // fn innerhelper(self_rw : Arc>) -> Option> { // fn innerhelper(inroutine : &Routine) -> Option> { // fn innerhelper(inroutine : Routine) -> Option> { - fn innerhelper(inroutine : Arc>) -> Option> { + // async fn innerhelper(inroutine : Arc>) -> Option> { + async fn runonce_innerhelper(inroutine : Arc>) -> JoinHandle<()> { - Some( - tokio::spawn(async move { + botlog::trace( + "innerhelper() started", + Some(format!( + "Routine > start() > (In Tokio Spawn)", + )), + Some(&inroutine.read().await.parent_params.msg), + ); + + Log::flush(); + + // Some( + // tokio::spawn(async move { + + // botlog::trace( + // ">> Within Spawn", + // Some(format!( + // "Routine > start() > (In Tokio Spawn)", + // )), + // Some(&inroutine.read().await.parent_params.msg), + // ); + + // Log::flush(); + + + + // // let mut self_wr_lock = self_rw.write().await; + // // let mut remainingiter = self_wr_lock.remaining_iterations.unwrap(); + // let mut remainingiter = inroutine.write().await.remaining_iterations.unwrap_or(0); + + + + // botlog::trace( + // format!( + // "[TRACE][Routine Started] {} in {}", + // inroutine.read().await.name, + // inroutine.read().await.channel.0 + // ) + // .as_str(), + // Some(format!( + // "Routine > start() > (In Tokio Spawn) > {:?}", + // inroutine.read().await.module + // )), + // Some(&inroutine.read().await.parent_params.msg), + // ); + + // Log::flush(); + + // inroutine.write().await.start_time = Some(chrono::offset::Local::now()); + + + // // Loop iteration + // while remainingiter > 1 { + + // // execution body + // inroutine.read().await.loopbody().await; + + // // end of loop iteration + // remainingiter -= 1; + // { + // inroutine.write().await.remaining_iterations = Some(remainingiter); + // inroutine.write().await.complete_iterations += 1; + // } + + // } + + // botlog::trace( + // format!( + // "[TRACE][Routine Completed] {} in {}", + // inroutine.read().await.name, + // inroutine.read().await.channel.0 + // ) + // .as_str(), + // Some(format!( + // "Routine > start() > (In Tokio Spawn) > {:?}", + // inroutine.read().await.module + // )), + // Some(&inroutine.read().await.parent_params.msg), + // ); + + + // Log::flush(); + // })) + + return tokio::spawn(async move { + + botlog::trace( + ">> Within Spawn", + Some(format!( + "Routine > start() > (In Tokio Spawn)", + )), + Some(&inroutine.read().await.parent_params.msg), + ); + + Log::flush(); + + + // botlog::trace( + // &format!( + // ">> Within Spawn - Reamining Iter Eval : {:?}" + // ,inroutine.read().await.remaining_iterations), + // Some(format!( + // "Routine > start() > (In Tokio Spawn)", + // )), + // Some(&inroutine.read().await.parent_params.msg), + // ); + + // Log::flush(); + + botlog::trace( + ">> Within Spawn >> After remaining iter eval", + Some(format!( + "Routine > start() > (In Tokio Spawn)", + )), + Some(&inroutine.read().await.parent_params.msg), + ); + + Log::flush(); + + + botlog::trace( + ">> Within Spawn >> After remaining iter eval 2 ", + Some(format!( + "Routine > start() > (In Tokio Spawn)", + )), + Some(&inroutine.read().await.parent_params.msg), + ); + + Log::flush(); + + + botlog::trace( + ">> Within Spawn >> After remaining iter eval 3 ", + Some(format!( + "Routine > start() > (In Tokio Spawn)", + )), + Some(&inroutine.read().await.parent_params.msg), + ); + + Log::flush(); // let mut self_wr_lock = self_rw.write().await; // let mut remainingiter = self_wr_lock.remaining_iterations.unwrap(); - let mut remainingiter = inroutine.write().await.remaining_iterations.unwrap_or(0); + // let mut remainingiter = inroutine.write().await.remaining_iterations.unwrap_or(0); + // let mut remainingiter = inroutine.read().await.remaining_iterations.unwrap_or(0); + // let mut remainingiter = inroutine.read().await.remaining_iterations.unwrap_or(0); + // async fn setremain(inroutine : Arc> , number : Option) { + // inroutine.write().await.remaining_iterations = number; + // } + // if inroutine.read().await.remaining_iterations.is_none() { + // // inroutine.write().await.remaining_iterations = Some(0); + // // setremain(inroutine.clone(),Some(0)).await; + // } - botlog::trace( - format!( - "[TRACE][Routine Started] {} in {}", - inroutine.read().await.name, - inroutine.read().await.channel.0 - ) - .as_str(), - Some(format!( - "Routine > start() > (In Tokio Spawn) > {:?}", - inroutine.read().await.module - )), - Some(&inroutine.read().await.parent_params.msg), - ); + // botlog::trace( + // format!( + // "[TRACE][Routine Started] {} in {}", + // inroutine.read().await.name, + // inroutine.read().await.channel.0 + // ) + // .as_str(), + // Some(format!( + // "Routine > start() > (In Tokio Spawn) > {:?}", + // inroutine.read().await.module + // )), + // Some(&inroutine.read().await.parent_params.msg), + // ); - inroutine.write().await.start_time = Some(chrono::offset::Local::now()); + // botlog::trace( + // format!( + // "[TRACE][Routine Started] {} in {}", + // inroutine.read().await.name, + // inroutine.read().await.channel.0 + // ) + // .as_str(), + // Some(format!( + // "Routine > start() > (In Tokio Spawn) > {:?}", + // inroutine.read().await.module + // )), + // Some(&inroutine.read().await.parent_params.msg), + // ); + + // Log::flush(); + + // inroutine.write().await.start_time = Some(chrono::offset::Local::now()); + // { + // inroutine.write().await.start_time = Some(chrono::offset::Local::now()); + // } // Loop iteration - while remainingiter > 1 { + // while remainingiter > 1 { + // while inroutine.read().await.remaining_iterations.unwrap_or(0) > 1 { // execution body inroutine.read().await.loopbody().await; // end of loop iteration - remainingiter -= 1; - { - inroutine.write().await.remaining_iterations = Some(remainingiter); - inroutine.write().await.complete_iterations += 1; - } + + // let remain_iter = inroutine.read().await.remaining_iterations.unwrap_or(0); + + // { + // // inroutine.write().await.remaining_iterations = Some(remain_iter - 1); + // setremain(inroutine.clone(),Some(remain_iter - 1)).await; + // } + // { + // inroutine.write().await.complete_iterations += 1; + // } + + // remainingiter -= 1; + // { + // inroutine.write().await.remaining_iterations = Some(remainingiter); + // inroutine.write().await.complete_iterations += 1; + // } - } - + // } + botlog::trace( format!( "[TRACE][Routine Completed] {} in {}", @@ -778,7 +957,10 @@ impl Routine { Log::flush(); - })) + }) + + + } @@ -793,9 +975,17 @@ impl Routine { // let routine = *self_rw_copy.read().await; // self_rw_copy.write().await.join_handle = innerhelper(&routine); // let self_ref = Arc::clone(&trg_routine_ar); - trg_routine_ar.write().await.join_handle = innerhelper(trg_routine_ar.clone()); + // trg_routine_ar.write().await.join_handle = innerhelper(trg_routine_ar.clone()).await; + { + trg_routine_ar.write().await.join_handle = Some(runonce_innerhelper(trg_routine_ar.clone()).await); + } - return Ok("Successfully Started Routine".to_string()); + // if let Some(a) = &trg_routine_ar.read().await.join_handle { + // (*a).await.unwrap(); + // }; + + // return Ok("Successfully Started Routine".to_string()); + return Ok(trg_routine_ar); } @@ -825,6 +1015,16 @@ impl Routine { async fn loopbody(&self) { + botlog::trace( + "loopbody() started", + Some(format!( + "Routine > start() > (During Tokio Spawn) > Execution body", + )), + None, + ); + + Log::flush(); + (self.exec_body)( self.parent_params.clone() ).await; diff --git a/src/custom/experimental/experiment003.rs b/src/custom/experimental/experiment003.rs index 1e25591..76862f6 100644 --- a/src/custom/experimental/experiment003.rs +++ b/src/custom/experimental/experiment003.rs @@ -160,10 +160,15 @@ async fn test3_body(params : ExecBodyParams) { // let rslt = newr_ar.read().await.start().await; + let rsltstr = match rslt { + Ok(_) => "successful".to_string(), + Err(a) => a, + }; + botlog::debug( format!("TEST3_BODY RESULT : {:?}", - rslt + rsltstr ).as_str(), Some("experiment003 > test3_body".to_string()), Some(¶ms.msg), @@ -181,7 +186,7 @@ async fn test3_body(params : ExecBodyParams) { .chat .say_in_reply_to( ¶ms.msg, - format!("Routine Result : {:?}",rslt), + format!("Routine Result : {:?}",rsltstr), params.clone() ).await; -- 2.46.1 From 8da8460e4739bda0e51fffc8fdb2003bc993c61e Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Wed, 27 Mar 2024 14:51:56 -0400 Subject: [PATCH 07/23] proper join handling at custom --- src/core/botmodules.rs | 7 ++-- src/custom/experimental/experiment003.rs | 45 ++++++++++++++++-------- 2 files changed, 36 insertions(+), 16 deletions(-) diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index 0e6dfc2..49fca78 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -622,7 +622,10 @@ pub struct Routine { exec_body: bot_actions::actions_util::ExecBody, // parent_params : Option , parent_params : ExecBodyParams , - pub join_handle : Option> , + // pub join_handle : Option> , + // pub join_handle : Option> , + // pub join_handle : Option>>> , + pub join_handle : Option>>> , start_time : Option> , complete_iterations : i64 , remaining_iterations : Option , @@ -977,7 +980,7 @@ impl Routine { // let self_ref = Arc::clone(&trg_routine_ar); // trg_routine_ar.write().await.join_handle = innerhelper(trg_routine_ar.clone()).await; { - trg_routine_ar.write().await.join_handle = Some(runonce_innerhelper(trg_routine_ar.clone()).await); + trg_routine_ar.write().await.join_handle = Some(Arc::new(RwLock::new(runonce_innerhelper(trg_routine_ar.clone()).await))); } // if let Some(a) = &trg_routine_ar.read().await.join_handle { diff --git a/src/custom/experimental/experiment003.rs b/src/custom/experimental/experiment003.rs index 76862f6..1d76930 100644 --- a/src/custom/experimental/experiment003.rs +++ b/src/custom/experimental/experiment003.rs @@ -17,6 +17,7 @@ const OF_CMD_CHANNEL:Channel = Channel(String::new()); use casual_logger::Log; use rand::Rng; use tokio::sync::RwLock; +use std::borrow::Borrow; use std::sync::Arc; use crate::core::bot_actions::ExecBodyParams; @@ -88,19 +89,19 @@ async fn test3_body(params : ExecBodyParams) { async fn rtestbody(params : ExecBodyParams) { - let bot = Arc::clone(¶ms.bot); + // let bot = Arc::clone(¶ms.bot); - let botlock = bot.read().await; + // let botlock = bot.read().await; - // uses chat.say_in_reply_to() for the bot controls for messages - botlock - .botmgrs - .chat - .say_in_reply_to( - ¶ms.msg.clone(), - String::from("Inner Routine Loop Message"), - params.clone() - ).await; + // // uses chat.say_in_reply_to() for the bot controls for messages + // botlock + // .botmgrs + // .chat + // .say_in_reply_to( + // ¶ms.msg.clone(), + // String::from("Inner Routine Loop Message"), + // params.clone() + // ).await; let logmsg_botact = match *params.curr_act.read().await { BotAction::C(_) => "command", @@ -115,10 +116,16 @@ async fn test3_body(params : ExecBodyParams) { Some(¶ms.msg), ); Log::flush(); + + for _ in 0..5 { + println!("tester"); + sleep(Duration::from_secs_f64(0.5)).await; + } } + botlog::debug( - format!("TEST3_BODY BEFORE FROM CALL : module - {:?} ; channel - {:?}", + format!("RTESTBODY : module - {:?} ; channel - {:?}", module,channel ).as_str(), Some("experiment003 > test3_body".to_string()), @@ -190,10 +197,20 @@ async fn test3_body(params : ExecBodyParams) { params.clone() ).await; - newr.clone().write().await.join_handle.take().expect("Issue with join handle").await.unwrap(); + // [x] Will not be handling JoinHandles here . If immediate abort() handling is required, below is an example that works + /* - // newr.read().await.join_handle.unwrap().await.unwrap(); + let a = newr.clone().read().await.join_handle.clone(); + match a { + Some(b) => { + b.read().await.borrow().abort(); // [x] <-- This aborts if wanting to abort immediately + //() + }, + None => (), + } + + */ } -- 2.46.1 From 226da4362a465345ce1c41b145d9b188f1f19157 Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Wed, 27 Mar 2024 16:04:15 -0400 Subject: [PATCH 08/23] comments cleanup --- src/core/botmodules.rs | 287 ++++++----------------------------------- 1 file changed, 37 insertions(+), 250 deletions(-) diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index 49fca78..eb12cc1 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -76,7 +76,6 @@ pub async fn init(mgr: Arc) { // 2. Add the BotAction to ModulesManager botc1.add_core_to_modmgr(Arc::clone(&mgr)).await; - // async fn cmd_enable(bot: BotAR, msg: PrivmsgMessage) { async fn cmd_enable(params : ExecBodyParams) { /* There should be additional validation checks @@ -260,7 +259,6 @@ pub async fn init(mgr: Arc) { // 2. Add the BotAction to ModulesManager botc1.add_core_to_modmgr(Arc::clone(&mgr)).await; - // async fn cmd_disable(bot: BotAR, msg: PrivmsgMessage) { async fn cmd_disable(params : ExecBodyParams) { /* There should be additional validation checks @@ -469,7 +467,6 @@ pub enum StatusType { pub enum BotAction { C(BotCommand), L(Listener), - // R(Routine), R(Arc>), } @@ -617,14 +614,9 @@ pub enum RoutineAttr { pub struct Routine { pub name : String , pub module : BotModule , // from() can determine this if passed parents_params - // pub channel : Option , // Routines generally run by Channel ; but can be left None pub channel : Channel , // Requiring some channel context exec_body: bot_actions::actions_util::ExecBody, - // parent_params : Option , parent_params : ExecBodyParams , - // pub join_handle : Option> , - // pub join_handle : Option> , - // pub join_handle : Option>>> , pub join_handle : Option>>> , start_time : Option> , complete_iterations : i64 , @@ -642,10 +634,7 @@ impl Routine { channel : Channel, routine_attr : Vec , exec_body : bot_actions::actions_util::ExecBody , - // parent_params : Option parent_params : ExecBodyParams - // ) -> Result { - // ) -> Result { ) -> Result< Arc>, String @@ -655,8 +644,6 @@ impl Routine { // to ensure those params don't conflict // conlicts would throw an error - // parent_params.unwrap(). - if routine_attr.contains(&RoutineAttr::RunOnce) { return Ok(Arc::new(RwLock::new(Routine { name , @@ -687,42 +674,26 @@ impl Routine { Err("NOT IMPLEMENTED".to_string()) } - // pub async fn start(self) -> Result - // pub async fn start(self : &mut Self) -> Result pub async fn start( trg_routine_ar : Arc> // ) -> Result -) -> Result>,String> + ) -> Result>,String> { // [ ] Asyncio Spawn likely around here // [ ] & Assigns self.join_handle - // let self_rw = Arc::new(RwLock::new(self)); - // let mut self_wr_lock = self_rw.write().await; - // let self_ar = Arc::new(RwLock::new(trg_routine_ar)); + /* + GENERAL LOGIC + 1. Create a loop scenario based on routine_attr such as RunOnce + 2. Run the loop depending on how the Routine is setup + + */ if trg_routine_ar.read().await.routine_attr.contains(&RoutineAttr::RunOnce) { - // if self_wr_lock.routine_attr.contains(&RoutineAttr::RunOnce) { - // let = self_wr_lock.remaining_iterations - - // let mut self_wr_lock = self_rw.write().await; - - // let self_rw_copy = Arc::new(self); - // let self_rw_copy = Arc::clone(&self_rw); - // let mut a = *(*self_wr_lock); - // a.remaining_iterations = Some(1); - // (*self_wr_lock).remaining_iterations = Some(1); - // let routine = *self_rw_copy.read().await; - - // fn innerhelper(self_rw : Arc>) -> Option> { - // fn innerhelper(self_rw : Arc>) -> Option> { - // fn innerhelper(inroutine : &Routine) -> Option> { - // fn innerhelper(inroutine : Routine) -> Option> { - // async fn innerhelper(inroutine : Arc>) -> Option> { async fn runonce_innerhelper(inroutine : Arc>) -> JoinHandle<()> { botlog::trace( @@ -734,79 +705,6 @@ impl Routine { ); Log::flush(); - - // Some( - // tokio::spawn(async move { - - // botlog::trace( - // ">> Within Spawn", - // Some(format!( - // "Routine > start() > (In Tokio Spawn)", - // )), - // Some(&inroutine.read().await.parent_params.msg), - // ); - - // Log::flush(); - - - - // // let mut self_wr_lock = self_rw.write().await; - // // let mut remainingiter = self_wr_lock.remaining_iterations.unwrap(); - // let mut remainingiter = inroutine.write().await.remaining_iterations.unwrap_or(0); - - - - // botlog::trace( - // format!( - // "[TRACE][Routine Started] {} in {}", - // inroutine.read().await.name, - // inroutine.read().await.channel.0 - // ) - // .as_str(), - // Some(format!( - // "Routine > start() > (In Tokio Spawn) > {:?}", - // inroutine.read().await.module - // )), - // Some(&inroutine.read().await.parent_params.msg), - // ); - - // Log::flush(); - - // inroutine.write().await.start_time = Some(chrono::offset::Local::now()); - - - // // Loop iteration - // while remainingiter > 1 { - - // // execution body - // inroutine.read().await.loopbody().await; - - // // end of loop iteration - // remainingiter -= 1; - // { - // inroutine.write().await.remaining_iterations = Some(remainingiter); - // inroutine.write().await.complete_iterations += 1; - // } - - // } - - // botlog::trace( - // format!( - // "[TRACE][Routine Completed] {} in {}", - // inroutine.read().await.name, - // inroutine.read().await.channel.0 - // ) - // .as_str(), - // Some(format!( - // "Routine > start() > (In Tokio Spawn) > {:?}", - // inroutine.read().await.module - // )), - // Some(&inroutine.read().await.parent_params.msg), - // ); - - - // Log::flush(); - // })) return tokio::spawn(async move { @@ -819,131 +717,25 @@ impl Routine { ); Log::flush(); + { + let mut a = inroutine.write().await; + a.start_time = Some(chrono::offset::Local::now()); + a.complete_iterations += 1; + if let Some(i) = a.remaining_iterations{ + if i > 0 { + a.remaining_iterations = Some(i-1) + } else { + // do nothing for now + // [ ] If this was in a loop, please validate this + } + + } + } - // botlog::trace( - // &format!( - // ">> Within Spawn - Reamining Iter Eval : {:?}" - // ,inroutine.read().await.remaining_iterations), - // Some(format!( - // "Routine > start() > (In Tokio Spawn)", - // )), - // Some(&inroutine.read().await.parent_params.msg), - // ); + // execution body + inroutine.read().await.loopbody().await; - // Log::flush(); - - botlog::trace( - ">> Within Spawn >> After remaining iter eval", - Some(format!( - "Routine > start() > (In Tokio Spawn)", - )), - Some(&inroutine.read().await.parent_params.msg), - ); - - Log::flush(); - - - botlog::trace( - ">> Within Spawn >> After remaining iter eval 2 ", - Some(format!( - "Routine > start() > (In Tokio Spawn)", - )), - Some(&inroutine.read().await.parent_params.msg), - ); - - Log::flush(); - - - botlog::trace( - ">> Within Spawn >> After remaining iter eval 3 ", - Some(format!( - "Routine > start() > (In Tokio Spawn)", - )), - Some(&inroutine.read().await.parent_params.msg), - ); - - Log::flush(); - - - // let mut self_wr_lock = self_rw.write().await; - // let mut remainingiter = self_wr_lock.remaining_iterations.unwrap(); - // let mut remainingiter = inroutine.write().await.remaining_iterations.unwrap_or(0); - // let mut remainingiter = inroutine.read().await.remaining_iterations.unwrap_or(0); - // let mut remainingiter = inroutine.read().await.remaining_iterations.unwrap_or(0); - - // async fn setremain(inroutine : Arc> , number : Option) { - // inroutine.write().await.remaining_iterations = number; - // } - - // if inroutine.read().await.remaining_iterations.is_none() { - // // inroutine.write().await.remaining_iterations = Some(0); - // // setremain(inroutine.clone(),Some(0)).await; - // } - - // botlog::trace( - // format!( - // "[TRACE][Routine Started] {} in {}", - // inroutine.read().await.name, - // inroutine.read().await.channel.0 - // ) - // .as_str(), - // Some(format!( - // "Routine > start() > (In Tokio Spawn) > {:?}", - // inroutine.read().await.module - // )), - // Some(&inroutine.read().await.parent_params.msg), - // ); - - // botlog::trace( - // format!( - // "[TRACE][Routine Started] {} in {}", - // inroutine.read().await.name, - // inroutine.read().await.channel.0 - // ) - // .as_str(), - // Some(format!( - // "Routine > start() > (In Tokio Spawn) > {:?}", - // inroutine.read().await.module - // )), - // Some(&inroutine.read().await.parent_params.msg), - // ); - - // Log::flush(); - - // inroutine.write().await.start_time = Some(chrono::offset::Local::now()); - // { - // inroutine.write().await.start_time = Some(chrono::offset::Local::now()); - // } - - - // Loop iteration - // while remainingiter > 1 { - // while inroutine.read().await.remaining_iterations.unwrap_or(0) > 1 { - - // execution body - inroutine.read().await.loopbody().await; - - // end of loop iteration - - // let remain_iter = inroutine.read().await.remaining_iterations.unwrap_or(0); - - // { - // // inroutine.write().await.remaining_iterations = Some(remain_iter - 1); - // setremain(inroutine.clone(),Some(remain_iter - 1)).await; - // } - // { - // inroutine.write().await.complete_iterations += 1; - // } - - // remainingiter -= 1; - // { - // inroutine.write().await.remaining_iterations = Some(remainingiter); - // inroutine.write().await.complete_iterations += 1; - // } - - // } - botlog::trace( format!( "[TRACE][Routine Completed] {} in {}", @@ -958,6 +750,20 @@ impl Routine { Some(&inroutine.read().await.parent_params.msg), ); + botlog::trace( + format!( + "[TRACE][Routine Completed][Routine Header Test] {} in {} > Completed Iterations : {}", + inroutine.read().await.name, + inroutine.read().await.channel.0 , + inroutine.read().await.complete_iterations, + ) + .as_str(), + Some(format!( + "Routine > start() > (In Tokio Spawn) > {:?}", + inroutine.read().await.module + )), + Some(&inroutine.read().await.parent_params.msg), + ); Log::flush(); }) @@ -967,27 +773,10 @@ impl Routine { } - // let self_rw = Arc::new(RwLock::new(self)); - // let mut self_wr_lock = self_rw.write().await; - - // self_wr_lock.join_handle = innerhelper(&routine) ; - - // let mut routine = self_rw_copy.write().await; - // (**routine).join_handle = innerhelper(*routine); - // routine.join_handle = innerhelper(*routine); - // let routine = *self_rw_copy.read().await; - // self_rw_copy.write().await.join_handle = innerhelper(&routine); - // let self_ref = Arc::clone(&trg_routine_ar); - // trg_routine_ar.write().await.join_handle = innerhelper(trg_routine_ar.clone()).await; { trg_routine_ar.write().await.join_handle = Some(Arc::new(RwLock::new(runonce_innerhelper(trg_routine_ar.clone()).await))); } - // if let Some(a) = &trg_routine_ar.read().await.join_handle { - // (*a).await.unwrap(); - // }; - - // return Ok("Successfully Started Routine".to_string()); return Ok(trg_routine_ar); } @@ -997,14 +786,12 @@ impl Routine { botlog::trace( format!( "[ERROR][Routine NOT IMPLEMENTED] {} in {}", - // self_wr_lock.name,self_wr_lock.channel.0 trg_routine_ar.read().await.name, trg_routine_ar.read().await.channel.0 ) .as_str(), Some(format!( "Routine > start() > (In Tokio Spawn) > {:?}", - // self_wr_lock.module trg_routine_ar.read().await.module )), Some(&trg_routine_ar.read().await.parent_params.msg), -- 2.46.1 From 669b2da8716fa5b7516466afbd881391cd1992f7 Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Wed, 27 Mar 2024 17:03:23 -0400 Subject: [PATCH 09/23] cleanup start impl --- src/core/bot_actions.rs | 3 +- src/core/botmodules.rs | 223 ++++++++++++++++++++++------------------ 2 files changed, 124 insertions(+), 102 deletions(-) diff --git a/src/core/bot_actions.rs b/src/core/bot_actions.rs index a88e5de..9ff41b5 100644 --- a/src/core/bot_actions.rs +++ b/src/core/bot_actions.rs @@ -5,11 +5,12 @@ use tokio::sync::RwLock; use crate::core::botinstance::BotInstance; -use super::{botinstance::Channel, botmodules::{BotAction, BotModule}, identity::ChatBadge}; +use super::{botinstance::Channel, botmodules::{BotAction, BotModule, Routine}, identity::ChatBadge}; pub type BotAR = Arc>; pub type ActAR = Arc>; +pub type RoutineAR = Arc>; #[derive(Clone)] pub struct ExecBodyParams { diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index eb12cc1..68129e1 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -25,6 +25,8 @@ const OF_CMD_CHANNEL:Channel = Channel(String::new()); use core::panic; +use std::borrow::Borrow; +use std::borrow::BorrowMut; use std::collections::HashMap; use std::sync::Arc; @@ -51,6 +53,8 @@ use crate::core::bot_actions; use std::hash::{Hash, Hasher}; +use super::bot_actions::ActAR; +use super::bot_actions::RoutineAR; use super::identity::ChatBadge; @@ -617,7 +621,7 @@ pub struct Routine { pub channel : Channel , // Requiring some channel context exec_body: bot_actions::actions_util::ExecBody, parent_params : ExecBodyParams , - pub join_handle : Option>>> , + pub join_handle : Option>>> , start_time : Option> , complete_iterations : i64 , remaining_iterations : Option , @@ -685,121 +689,138 @@ impl Routine { /* - GENERAL LOGIC + UMBRELLA ROUTINE LOGIC 1. Create a loop scenario based on routine_attr such as RunOnce 2. Run the loop depending on how the Routine is setup + + START LOGIC : + 1. Ideally validate the routineattr that they're not a problem scenario (However, this should have been validated At Setup) + a. Extra helper validation function though would help in case the attributes were changes between setup + 2. Use these attributes only in Critical areas of the loop logic to determine changes in Loop logic + */ + + // Use the following to stop the function from going any further if not implemented + if !trg_routine_ar.read().await.routine_attr.contains(&RoutineAttr::RunOnce) { + + + botlog::trace( + format!( + "[ERROR][Routine Feature NOT IMPLEMENTED] {} in {}", + trg_routine_ar.read().await.name, + trg_routine_ar.read().await.channel.0 + ) + .as_str(), + Some(format!( + "Routine > start() > (In Tokio Spawn) > {:?}", + trg_routine_ar.read().await.module + )), + Some(&trg_routine_ar.read().await.parent_params.msg), + ); + + Log::flush(); + + return Err("NOT IMPLEMENTED".to_string()) + + } - if trg_routine_ar.read().await.routine_attr.contains(&RoutineAttr::RunOnce) { - - async fn runonce_innerhelper(inroutine : Arc>) -> JoinHandle<()> { - - botlog::trace( - "innerhelper() started", - Some(format!( - "Routine > start() > (In Tokio Spawn)", - )), - Some(&inroutine.read().await.parent_params.msg), - ); - - Log::flush(); - - return tokio::spawn(async move { - - botlog::trace( - ">> Within Spawn", - Some(format!( - "Routine > start() > (In Tokio Spawn)", - )), - Some(&inroutine.read().await.parent_params.msg), - ); - - Log::flush(); - { - let mut a = inroutine.write().await; - a.start_time = Some(chrono::offset::Local::now()); - a.complete_iterations += 1; - if let Some(i) = a.remaining_iterations{ - - if i > 0 { - a.remaining_iterations = Some(i-1) - } else { - // do nothing for now - // [ ] If this was in a loop, please validate this - } - - } - } - - // execution body - inroutine.read().await.loopbody().await; - - botlog::trace( - format!( - "[TRACE][Routine Completed] {} in {}", - inroutine.read().await.name, - inroutine.read().await.channel.0 - ) - .as_str(), - Some(format!( - "Routine > start() > (In Tokio Spawn) > {:?}", - inroutine.read().await.module - )), - Some(&inroutine.read().await.parent_params.msg), - ); - - botlog::trace( - format!( - "[TRACE][Routine Completed][Routine Header Test] {} in {} > Completed Iterations : {}", - inroutine.read().await.name, - inroutine.read().await.channel.0 , - inroutine.read().await.complete_iterations, - ) - .as_str(), - Some(format!( - "Routine > start() > (In Tokio Spawn) > {:?}", - inroutine.read().await.module - )), - Some(&inroutine.read().await.parent_params.msg), - ); - - Log::flush(); - }) - - - - } - - - { - trg_routine_ar.write().await.join_handle = Some(Arc::new(RwLock::new(runonce_innerhelper(trg_routine_ar.clone()).await))); - } - - return Ok(trg_routine_ar); - - } - + let trg_routine_arout = Arc::clone(&trg_routine_ar); + botlog::trace( - format!( - "[ERROR][Routine NOT IMPLEMENTED] {} in {}", - trg_routine_ar.read().await.name, - trg_routine_ar.read().await.channel.0 - ) - .as_str(), - Some(format!( - "Routine > start() > (In Tokio Spawn) > {:?}", - trg_routine_ar.read().await.module + "innerhelper() started", + Some(format!( + "Routine > start() > (In Tokio Spawn)", )), Some(&trg_routine_ar.read().await.parent_params.msg), ); Log::flush(); - Err("NOT IMPLEMENTED".to_string()) + // Spawn the task + let join_handle = tokio::spawn(async move { + + botlog::trace( + ">> Within Spawn", + Some(format!( + "Routine > start() > (In Tokio Spawn)", + )), + Some(&trg_routine_ar.read().await.parent_params.msg), + ); + + Log::flush(); + { // 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 + + + // execution body + trg_routine_ar.read().await.loopbody().await; + + + { // End of Loop iteration + let mut a = trg_routine_ar.write().await; + a.complete_iterations += 1; + if let Some(i) = a.remaining_iterations { + if i > 0 { a.remaining_iterations = Some(i-1) ; } + } + } + + // End of Loop Validation + + if trg_routine_ar.read().await.routine_attr.contains(&RoutineAttr::RunOnce) { + if trg_routine_ar.read().await.complete_iterations > 0 { break; } + } + + } + + + botlog::trace( + format!( + "[TRACE][Routine Completed] {} in {}", + trg_routine_ar.read().await.name, + trg_routine_ar.read().await.channel.0 + ) + .as_str(), + Some(format!( + "Routine > start() > (In Tokio Spawn) > {:?}", + trg_routine_ar.read().await.module + )), + Some(&trg_routine_ar.read().await.parent_params.msg), + ); + + botlog::trace( + format!( + "[TRACE][Routine Completed][Routine Header Test] {} in {} > Completed Iterations : {}", + trg_routine_ar.read().await.name, + trg_routine_ar.read().await.channel.0 , + trg_routine_ar.read().await.complete_iterations, + ) + .as_str(), + Some(format!( + "Routine > start() > (In Tokio Spawn) > {:?}", + trg_routine_ar.read().await.module + )), + Some(&trg_routine_ar.read().await.parent_params.msg), + ); + + Log::flush(); + trg_routine_ar + }); + + trg_routine_arout.write().await.join_handle = Some(Arc::new(RwLock::new(join_handle))); + + // } + + + return Ok(trg_routine_arout); + } -- 2.46.1 From 537c3565a2a3440bbc6878a8011dfdc375d4b77e Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Wed, 27 Mar 2024 17:28:47 -0400 Subject: [PATCH 10/23] custom start test fn --- src/core/botmodules.rs | 4 +-- src/custom/experimental/experiment003.rs | 45 ++++++++++++------------ 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index 68129e1..c113af5 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -620,10 +620,10 @@ pub struct Routine { pub module : BotModule , // from() can determine this if passed parents_params pub channel : Channel , // Requiring some channel context exec_body: bot_actions::actions_util::ExecBody, - parent_params : ExecBodyParams , + pub parent_params : ExecBodyParams , pub join_handle : Option>>> , start_time : Option> , - complete_iterations : i64 , + pub complete_iterations : i64 , remaining_iterations : Option , routine_attr : Vec , } diff --git a/src/custom/experimental/experiment003.rs b/src/custom/experimental/experiment003.rs index 1d76930..5537d33 100644 --- a/src/custom/experimental/experiment003.rs +++ b/src/custom/experimental/experiment003.rs @@ -89,19 +89,6 @@ async fn test3_body(params : ExecBodyParams) { async fn rtestbody(params : ExecBodyParams) { - // let bot = Arc::clone(¶ms.bot); - - // let botlock = bot.read().await; - - // // uses chat.say_in_reply_to() for the bot controls for messages - // botlock - // .botmgrs - // .chat - // .say_in_reply_to( - // ¶ms.msg.clone(), - // String::from("Inner Routine Loop Message"), - // params.clone() - // ).await; let logmsg_botact = match *params.curr_act.read().await { BotAction::C(_) => "command", @@ -110,20 +97,27 @@ async fn test3_body(params : ExecBodyParams) { } ; botlog::trace( - // format!("Params > Curr_act : {:?}", params.curr_act).as_str(), // BotAction doesn't imblement debug format!("Params > Curr_act type : {:?}", logmsg_botact).as_str(), Some("Experiments003 > test3 command body".to_string()), Some(¶ms.msg), ); Log::flush(); - for _ in 0..5 { - println!("tester"); - sleep(Duration::from_secs_f64(0.5)).await; + if let BotAction::R(arr) = &*params.curr_act.read().await { + for curriter in 0..5 { + println!("tester - Routine - Completed Iterations : {}", + arr.read().await.complete_iterations); + println!("tester - Custom Loop - Completed Iterations : {}", + curriter); + sleep(Duration::from_secs_f64(0.5)).await; + } } + } + + botlog::debug( format!("RTESTBODY : module - {:?} ; channel - {:?}", module,channel @@ -149,7 +143,8 @@ async fn test3_body(params : ExecBodyParams) { // [ ] before execute , be sure to adjust curr_act - let mut params_mut = params.clone(); + // let mut params_mut = params.clone(); + let mut params_mut = params; // let newr_ar = Arc::new(RwLock::new(newr)); let newr_ar = newr.clone(); @@ -163,6 +158,12 @@ async fn test3_body(params : ExecBodyParams) { // let mut newr_lock = newr_ar.write().await; // let rslt = newr_ar.write().await.start().await; + + + { + newr_ar.write().await.parent_params = params_mut.clone(); + } + let rslt = Routine::start(newr_ar.clone()).await; // let rslt = newr_ar.read().await.start().await; @@ -178,12 +179,12 @@ async fn test3_body(params : ExecBodyParams) { rsltstr ).as_str(), Some("experiment003 > test3_body".to_string()), - Some(¶ms.msg), + Some(¶ms_mut.msg), ); Log::flush(); - let bot = Arc::clone(¶ms.bot); + let bot = Arc::clone(¶ms_mut.bot); let botlock = bot.read().await; @@ -192,9 +193,9 @@ async fn test3_body(params : ExecBodyParams) { .botmgrs .chat .say_in_reply_to( - ¶ms.msg, + ¶ms_mut.msg, format!("Routine Result : {:?}",rsltstr), - params.clone() + params_mut.clone() ).await; // [x] Will not be handling JoinHandles here . If immediate abort() handling is required, below is an example that works -- 2.46.1 From 60fae25419294d9651b297072ba3928938d4e3a7 Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Wed, 27 Mar 2024 18:29:14 -0400 Subject: [PATCH 11/23] comments --- src/core/botmodules.rs | 170 +++++++++++++++++++++++++++++++---------- 1 file changed, 130 insertions(+), 40 deletions(-) diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index c113af5..f1997ad 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -631,8 +631,91 @@ pub struct Routine { impl Routine { + + + pub async fn validate_attr(routine_attr : &Vec) + -> Result + // [ ] => 03.27 - WIP + { + + /* + + GENERAL LOGIC : + [ ] 1. Define RoutineAttr in a broad level that are known to be implented or are work in progress + [ ] 2. Built in Logic will check these vectors, and return if Not Implemented + [ ] 3. If Implemented , then there are additional internal validation based on combination done later + + */ + + + // [x] 1. Define RoutineAttr in a broad level that are known to be implented or are work in progress + + // adjust the below for those that are work in progress or that are implemented + // - This will allow other functions to validate that it is implemented + + // WORK IN PROGRESS VECTOR - Vec<$RoutineAttr> + + let wip_attr:Vec<&RoutineAttr> = vec![ + &RoutineAttr::RunOnce + ]; + + 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)); + + if unimplemented.next().is_some() { + + botlog::trace( + "[ERROR][Routine Feature NOT IMPLEMENTED]", + Some("Routine > Validate_attr()".to_string()), + None, + ); + + Log::flush(); + + return Err("NOT IMPLEMENTED".to_string()); + } + + + + + + // [ ] 3. If Implemented , then there are additional internal validation based on combination done later + + if routine_attr.contains(&RoutineAttr::RunOnce) { + return Ok("Valid & Implemented Setup".to_string()) + } + + + + + + + botlog::trace( + "[ERROR][Routine Feature NOT IMPLEMENTED]", + Some("Routine > Validate_attr()".to_string()), + None, + ); + + Log::flush(); + + return Err("NOT IMPLEMENTED".to_string()) + + } + + pub async fn validate_self_attr(self) + -> Result + // [x] => 03.27 - COMPLETED + { + Routine::validate_attr(&self.routine_attr).await + } + // Constructor - pub fn from( + pub async fn from( name : String , module : BotModule , channel : Channel, @@ -642,35 +725,34 @@ impl Routine { ) -> Result< Arc>, String - > { + > + // [x] => 03.27 - COMPLETED + { - // [ ] Validation is made against parent_params - // to ensure those params don't conflict - // conlicts would throw an error - - if routine_attr.contains(&RoutineAttr::RunOnce) { - return Ok(Arc::new(RwLock::new(Routine { - name , - module , - channel , - exec_body , - parent_params , - join_handle : None , - start_time : None , - complete_iterations : 0 , - remaining_iterations : None , - routine_attr : routine_attr - }))) ; - } + Routine::validate_attr(&routine_attr).await?; + + return Ok(Arc::new(RwLock::new(Routine { + name , + module , + channel , + exec_body , + parent_params , + join_handle : None , + start_time : None , + complete_iterations : 0 , + remaining_iterations : None , + routine_attr : routine_attr + }))) ; - Err("NOT IMPLEMENTED".to_string()) } pub fn change_channel( &self, _channel : Channel - ) -> Result { + ) -> Result + // [ ] => 03.27 - WIP - NOT IMPLEMENTED + { // [ ] Think Ideally it should try to // change the target channel of the // internal process too if possible? @@ -682,6 +764,7 @@ impl Routine { trg_routine_ar : Arc> // ) -> Result ) -> Result>,String> + // [ ] => 03.27 - WIP { // [ ] Asyncio Spawn likely around here @@ -703,28 +786,30 @@ impl Routine { // Use the following to stop the function from going any further if not implemented - if !trg_routine_ar.read().await.routine_attr.contains(&RoutineAttr::RunOnce) { + + Routine::validate_attr(&trg_routine_ar.read().await.routine_attr).await?; + // if !trg_routine_ar.read().await.routine_attr.contains(&RoutineAttr::RunOnce) { - botlog::trace( - format!( - "[ERROR][Routine Feature NOT IMPLEMENTED] {} in {}", - trg_routine_ar.read().await.name, - trg_routine_ar.read().await.channel.0 - ) - .as_str(), - Some(format!( - "Routine > start() > (In Tokio Spawn) > {:?}", - trg_routine_ar.read().await.module - )), - Some(&trg_routine_ar.read().await.parent_params.msg), - ); + // botlog::trace( + // format!( + // "[ERROR][Routine Feature NOT IMPLEMENTED] {} in {}", + // trg_routine_ar.read().await.name, + // trg_routine_ar.read().await.channel.0 + // ) + // .as_str(), + // Some(format!( + // "Routine > start() > (In Tokio Spawn) > {:?}", + // trg_routine_ar.read().await.module + // )), + // Some(&trg_routine_ar.read().await.parent_params.msg), + // ); - Log::flush(); + // Log::flush(); - return Err("NOT IMPLEMENTED".to_string()) + // return Err("NOT IMPLEMENTED".to_string()) - } + // } let trg_routine_arout = Arc::clone(&trg_routine_ar); @@ -773,6 +858,7 @@ impl Routine { } // End of Loop Validation + // These generally may include routine_attr related checks if trg_routine_ar.read().await.routine_attr.contains(&RoutineAttr::RunOnce) { if trg_routine_ar.read().await.complete_iterations > 0 { break; } @@ -824,7 +910,8 @@ impl Routine { } - async fn loopbody(&self) + async fn loopbody(&self) + // [x] => 03.27 - COMPLETED { botlog::trace( "loopbody() started", @@ -842,6 +929,7 @@ impl Routine { } pub async fn stop(&self) -> Result + // [ ] => 03.27 - WIP - NOT IMPLEMENTED { @@ -871,6 +959,7 @@ impl Routine { &self, _force : bool ) -> Result + // [ ] => 03.27 - WIP - NOT IMPLEMENTED { // force flag aborts the routine immediately (like cancel()) @@ -897,6 +986,7 @@ impl Routine { } pub async fn cancel(&self) -> Result + // [ ] => 03.27 - WIP - NOT IMPLEMENTED { // [ ] Likely calls abort() -- 2.46.1 From e963ae250df15c4b2d56f80ad1c323df97bce450 Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Wed, 27 Mar 2024 23:00:04 -0400 Subject: [PATCH 12/23] (cont) routine methods --- src/core/botmodules.rs | 130 +++++++++++++++++++++-- src/custom/experimental/experiment003.rs | 2 +- 2 files changed, 121 insertions(+), 11 deletions(-) diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index f1997ad..bbed7fb 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -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 = vec![ + RoutineAttr::RunOnce, + RoutineAttr::ScheduledStart(chrono::offset::Local::now()), + RoutineAttr::DelayedStart, ]; - let implemented_attr:Vec<&RoutineAttr> = vec![ + let implemented_attr:Vec = 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) -> Result + { + (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 { + // 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; } diff --git a/src/custom/experimental/experiment003.rs b/src/custom/experimental/experiment003.rs index 5537d33..9b8f91e 100644 --- a/src/custom/experimental/experiment003.rs +++ b/src/custom/experimental/experiment003.rs @@ -135,7 +135,7 @@ async fn test3_body(params : ExecBodyParams) { routine_attr, exec_body, params.clone() - ); + ).await; -- 2.46.1 From 6c3a151668ae24b06e72686770667dae627f8700 Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Wed, 27 Mar 2024 23:56:34 -0400 Subject: [PATCH 13/23] impl other routine attr --- src/core/botmodules.rs | 120 ++++++++++++++++++++++++++++++++--------- 1 file changed, 94 insertions(+), 26 deletions(-) diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index bbed7fb..b5544cf 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -636,15 +636,15 @@ impl Routine { pub async fn validate_attr(routine_attr : &Vec) -> Result - // [ ] => 03.27 - WIP + // [ ] => 03.27 - REVIEW FOR COMPLETION { /* GENERAL LOGIC : - [ ] 1. Define RoutineAttr in a broad level that are known to be implented or are work in progress - [ ] 2. Built in Logic will check these vectors, and return if Not Implemented - [ ] 3. If Implemented , then there are additional internal validation based on combination done later + [x] 1. Define RoutineAttr in a broad level that are known to be implented or are work in progress + [x] 2. Built in Logic will check these vectors, and return if Not Implemented + [x] 3. If Implemented , then there are additional internal validation based on combination done later */ @@ -657,9 +657,14 @@ impl Routine { // WORK IN PROGRESS VECTOR - Vec<$RoutineAttr> let wip_attr:Vec = vec![ - RoutineAttr::RunOnce, - RoutineAttr::ScheduledStart(chrono::offset::Local::now()), RoutineAttr::DelayedStart, + RoutineAttr::ScheduledStart(chrono::offset::Local::now()), + RoutineAttr::LoopDuration(Duration::from_secs(1)), + RoutineAttr::LoopInfinitely, // Note : There's no added implementation for this + RoutineAttr::RunOnce, + RoutineAttr::MaxTimeThreshold(chrono::offset::Local::now()), + RoutineAttr::MaxIterations(1), + ]; let implemented_attr:Vec = vec![ @@ -693,18 +698,27 @@ impl Routine { - // [ ] 3. If Implemented , then there are additional internal validation based on combination done later + // [x] 3. If Implemented , then there are additional internal validation based on combination done later to ERR - if routine_attr.contains(&RoutineAttr::RunOnce) { - return Ok("Valid & Implemented Setup".to_string()) - } - - if routine_attr.contains(&RoutineAttr::RunOnce) & - routine_attr.contains(&RoutineAttr::LoopInfinitely) + // Below ensures a routine_attr containing LoopInfinitely does not contain conflicit attributes + if routine_attr.contains(&RoutineAttr::LoopInfinitely) && + ( routine_attr.contains(&RoutineAttr::RunOnce) + || routine_attr.iter().filter(|y| matches!(y,&&RoutineAttr::MaxIterations(_))).next().is_some() + || routine_attr.iter().filter(|y| matches!(y,&&RoutineAttr::MaxTimeThreshold(_))).next().is_some() + ) { return Err("Conflicting Routine Attributes".to_string()) } + // [x] if there is no RunOnce, there must be a LoopDuration + if !routine_attr.contains(&RoutineAttr::RunOnce) + && routine_attr.iter() + .filter(|x| matches!(x,&&RoutineAttr::LoopDuration(_)) ) + .next().is_none() + { + return Err("LoopDuration is required if not RunOnce".to_string()); + } + // [x] Err if DelayedStart but no LoopDuration if routine_attr.contains(&RoutineAttr::DelayedStart) && @@ -718,18 +732,44 @@ impl Routine { + // [x] 4. If all other failure checks above works, ensure one more time that the attribute is implemented + // - If not, routine NOT IMPLEMENTED error + if 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() + }) + .next() + .is_none() + { + + botlog::trace( + "[ERROR][Routine Feature NOT IMPLEMENTED]", + Some("Routine > Validate_attr()".to_string()), + None, + ); + Log::flush(); - botlog::trace( - "[ERROR][Routine Feature NOT IMPLEMENTED]", - Some("Routine > Validate_attr()".to_string()), - None, - ); + Ok("Implemented & Validated".to_string()) - Log::flush(); + } else { + + + botlog::trace( + "[ERROR][Routine Feature NOT IMPLEMENTED]", + Some("Routine > Validate_attr()".to_string()), + None, + ); + + Log::flush(); + + Err("NOT IMPLEMENTED".to_string()) + + } - return Err("NOT IMPLEMENTED".to_string()) } @@ -790,11 +830,11 @@ impl Routine { trg_routine_ar : Arc> // ) -> Result ) -> Result>,String> - // [ ] => 03.27 - WIP + // [ ] => 03.27 - REVIEW FOR COMPLETION { - // [ ] Asyncio Spawn likely around here - // [ ] & Assigns self.join_handle + // [x] Asyncio Spawn likely around here + // [x] & Assigns self.join_handle /* @@ -864,16 +904,19 @@ impl Routine { Log::flush(); - // [ ] If Scheduled Start or Delayed Start, Handle that first + // [x] If Scheduled Start or Delayed Start, Handle that first fn duration_to_datetime(future_dt: DateTime) -> Result { (future_dt - chrono::offset::Local::now()).to_std() } + + let delayduration = { + let lock = trg_routine_ar.read().await; let mut related_attrs = lock @@ -947,9 +990,17 @@ impl Routine { } - { // [x] Prior to Loop that calls Custom Routine Execution Body + { // [x] Loop Initialization - 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()); + + if let Some(&RoutineAttr::MaxIterations(iternum)) = + a.routine_attr.iter() + .filter(|x| matches!(x,RoutineAttr::MaxIterations(_))) + .next() + { + a.remaining_iterations = Some(iternum); + } } loop { // [x] Routine loop @@ -964,16 +1015,33 @@ impl Routine { a.complete_iterations += 1; if let Some(i) = a.remaining_iterations { if i > 0 { a.remaining_iterations = Some(i-1) ; } + else { break ; } // if remaining iterations is 0, exit } } - // [x]End of Loop Validation + // [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; } } + // return if max time has passed + if let Some(&RoutineAttr::MaxTimeThreshold(dt)) = trg_routine_ar.read().await.routine_attr.iter() + .filter(|x| matches!(x,&&RoutineAttr::MaxTimeThreshold(_)) ) + .next() { + if chrono::offset::Local::now() > dt { break; } + } + + // [x] Checks for Loop duration to sleep + if let Some(&RoutineAttr::LoopDuration(dur)) = trg_routine_ar.read().await.routine_attr.iter() + .filter(|x| matches!(x,&&RoutineAttr::LoopDuration(_)) ) + .next() + { + sleep(dur).await; + }; + + } -- 2.46.1 From 4637312da941defa8fd0bd94cfedee158250ec7f Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Thu, 28 Mar 2024 02:13:38 -0400 Subject: [PATCH 14/23] impl stop --- src/core/botmodules.rs | 144 +++++++++++++++++++++++++++-------------- 1 file changed, 95 insertions(+), 49 deletions(-) diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index b5544cf..08225a9 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -615,6 +615,14 @@ pub enum RoutineAttr { */ +// For some key statuses and in particular Stopping to Gracefully stop +pub enum RoutineSignal { + Stopping, // Gracefully Stopping + Stopped, // When cancelling or aborting, this also is represented by Stopped + Started, // After Routine Started + NotStarted, +} + // #[derive(Debug)] pub struct Routine { pub name : String , @@ -627,6 +635,7 @@ pub struct Routine { pub complete_iterations : i64 , remaining_iterations : Option , routine_attr : Vec , + pub internal_signal : RoutineSignal , } @@ -807,25 +816,13 @@ impl Routine { start_time : None , complete_iterations : 0 , remaining_iterations : None , - routine_attr : routine_attr + routine_attr : routine_attr , + internal_signal : RoutineSignal::NotStarted , }))) ; } - pub fn change_channel( - &self, - _channel : Channel - ) -> Result - // [ ] => 03.27 - WIP - NOT IMPLEMENTED - { - // [ ] Think Ideally it should try to - // change the target channel of the - // internal process too if possible? - - Err("NOT IMPLEMENTED".to_string()) - } - pub async fn start( trg_routine_ar : Arc> // ) -> Result @@ -1012,11 +1009,20 @@ impl Routine { { // [x] End of Loop iteration let mut a = trg_routine_ar.write().await; + + // [x] Check if Gracefully Stopping Signal was sent + if matches!(a.internal_signal,RoutineSignal::Stopping) { + a.internal_signal = RoutineSignal::Stopped; + break ; + } + + // [x] Check and adjust iterations a.complete_iterations += 1; if let Some(i) = a.remaining_iterations { if i > 0 { a.remaining_iterations = Some(i-1) ; } else { break ; } // if remaining iterations is 0, exit } + } // [x] End of Loop Validation @@ -1078,16 +1084,21 @@ impl Routine { trg_routine_ar }); - trg_routine_arout.write().await.join_handle = Some(Arc::new(RwLock::new(join_handle))); - // } + { // Recommendation to ensure a clean update is to use one write() lock that was awaited + // - We can isolate the write lock by ensuring it's in it's own block + let mut lock = trg_routine_arout.write().await; + lock.join_handle = Some(Arc::new(RwLock::new(join_handle))); + lock.internal_signal = RoutineSignal::Started; + + } + trg_routine_arout.write().await.internal_signal = RoutineSignal::Started; return Ok(trg_routine_arout); } - async fn loopbody(&self) // [x] => 03.27 - COMPLETED { @@ -1106,18 +1117,24 @@ impl Routine { ).await; } - pub async fn stop(&self) -> Result - // [ ] => 03.27 - WIP - NOT IMPLEMENTED + pub async fn stop(&mut self) -> Result + // [ ] => 03.27 - REVIEW FOR COMPLETION { let self_rw = Arc::new(RwLock::new(self)); + + { + let mut self_lock = self_rw.write().await; + self_lock.internal_signal = RoutineSignal::Stopping; + } + + let self_lock = self_rw.read().await; - botlog::trace( format!( - "[ERROR][Routine NOT IMPLEMENTED] {} in {}", + "[ROUTINE][Sent Gracefully Stopp Signal] {} in {}", self_lock.name,self_lock.channel.0 ) .as_str(), @@ -1130,37 +1147,24 @@ impl Routine { Log::flush(); - Err("NOT IMPLEMENTED".to_string()) - } + Ok("Sent Gracefully Stop Signal".to_string()) - pub async fn restart( - &self, - _force : bool - ) -> Result - // [ ] => 03.27 - WIP - NOT IMPLEMENTED - { - // force flag aborts the routine immediately (like cancel()) + // botlog::trace( + // format!( + // "[ERROR][Routine NOT IMPLEMENTED] {} in {}", + // self_lock.name,self_lock.channel.0 + // ) + // .as_str(), + // Some(format!( + // "Routine > start() > (In Tokio Spawn) > {:?}", + // self_lock.module + // )), + // Some(&self_lock.parent_params.msg), + // ); - - let self_rw = Arc::new(RwLock::new(self)); - let self_lock = self_rw.read().await; - + // Log::flush(); - botlog::trace( - format!( - "[ERROR][Routine NOT IMPLEMENTED] {} in {}", - self_lock.name,self_lock.channel.0 - ) - .as_str(), - Some(format!( - "Routine > start() > (In Tokio Spawn) > {:?}", - self_lock.module - )), - Some(&self_lock.parent_params.msg), - ); - - Log::flush(); - Err("NOT IMPLEMENTED".to_string()) + // Err("NOT IMPLEMENTED".to_string()) } pub async fn cancel(&self) -> Result @@ -1194,6 +1198,48 @@ impl Routine { Err("NOT IMPLEMENTED".to_string()) } + pub async fn restart( + &self, + _force : bool + ) -> Result + // [ ] => 03.27 - WIP - NOT IMPLEMENTED + { + // force flag aborts the routine immediately (like cancel()) + + + let self_rw = Arc::new(RwLock::new(self)); + let self_lock = self_rw.read().await; + + + botlog::trace( + format!( + "[ERROR][Routine NOT IMPLEMENTED] {} in {}", + self_lock.name,self_lock.channel.0 + ) + .as_str(), + Some(format!( + "Routine > start() > (In Tokio Spawn) > {:?}", + self_lock.module + )), + Some(&self_lock.parent_params.msg), + ); + + Log::flush(); + Err("NOT IMPLEMENTED".to_string()) + } + + pub fn change_channel( + &self, + _channel : Channel + ) -> Result + // [ ] => 03.27 - WIP - NOT IMPLEMENTED + { + // [ ] Think Ideally it should try to + // change the target channel of the + // internal process too if possible? + + Err("NOT IMPLEMENTED".to_string()) + } } -- 2.46.1 From ca9361cc935ea73bd95743dc76dcd7a96187bdc6 Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Thu, 28 Mar 2024 03:18:41 -0400 Subject: [PATCH 15/23] routine methods --- src/core/botmodules.rs | 154 +++++++++++++++++++++++++++++++++++------ 1 file changed, 131 insertions(+), 23 deletions(-) diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index 08225a9..e320e7f 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -28,6 +28,7 @@ use core::panic; use std::borrow::Borrow; use std::borrow::BorrowMut; use std::collections::HashMap; +use std::ops::DerefMut; use std::sync::Arc; use casual_logger::Log; @@ -1134,12 +1135,12 @@ impl Routine { botlog::trace( format!( - "[ROUTINE][Sent Gracefully Stopp Signal] {} in {}", + "[ROUTINE][Sent Gracefully Stop Signal] {} in {}", self_lock.name,self_lock.channel.0 ) .as_str(), Some(format!( - "Routine > start() > (In Tokio Spawn) > {:?}", + "Routine > stop() > {:?}", self_lock.module )), Some(&self_lock.parent_params.msg), @@ -1167,78 +1168,185 @@ impl Routine { // Err("NOT IMPLEMENTED".to_string()) } - pub async fn cancel(&self) -> Result - // [ ] => 03.27 - WIP - NOT IMPLEMENTED + pub async fn cancel(&mut self) -> Result + // [ ] => 03.27 - REVIEW FOR COMPLETION { // [ ] Likely calls abort() // Related : // https://docs.rs/tokio/latest/tokio/task/struct.JoinHandle.html#method.abort - - + let self_rw = Arc::new(RwLock::new(self)); let self_lock = self_rw.read().await; - + + + match &self_lock.join_handle { + None => return Err("No Join Handle on the Routine to Cancel".to_string()), + Some(a) => { + a.read().await.abort(); + { + let mut lock_mut = self_rw.write().await; + lock_mut.internal_signal = RoutineSignal::Stopped; + + } + } + } + botlog::trace( format!( - "[ERROR][Routine NOT IMPLEMENTED] {} in {}", + "[ROUTINE][Cancelled Routine] {} in {}", self_lock.name,self_lock.channel.0 ) .as_str(), Some(format!( - "Routine > start() > (In Tokio Spawn) > {:?}", + "Routine > cancel() > {:?}", self_lock.module )), Some(&self_lock.parent_params.msg), ); Log::flush(); - Err("NOT IMPLEMENTED".to_string()) + Ok("Cancelled Successfully".to_string()) + + + // botlog::trace( + // format!( + // "[ERROR][Routine NOT IMPLEMENTED] {} in {}", + // self_lock.name,self_lock.channel.0 + // ) + // .as_str(), + // Some(format!( + // "Routine > start() > (In Tokio Spawn) > {:?}", + // self_lock.module + // )), + // Some(&self_lock.parent_params.msg), + // ); + + // Log::flush(); + // Err("NOT IMPLEMENTED".to_string()) } pub async fn restart( - &self, - _force : bool + // &mut self, + self, + force : bool ) -> Result - // [ ] => 03.27 - WIP - NOT IMPLEMENTED + // [ ] => 03.27 - REVIEW FOR COMPLETION { // force flag aborts the routine immediately (like cancel()) let self_rw = Arc::new(RwLock::new(self)); - let self_lock = self_rw.read().await; + + if force + { + let mut self_lock = self_rw.write().await; + self_lock.cancel().await?; + } else { + let mut self_lock = self_rw.write().await; + self_lock.stop().await?; + } + + Routine::start(self_rw.clone()).await?; + let self_lock = self_rw.read().await; botlog::trace( format!( - "[ERROR][Routine NOT IMPLEMENTED] {} in {}", + "[ROUTINE][Restarted Routine] {} in {}", self_lock.name,self_lock.channel.0 ) .as_str(), Some(format!( - "Routine > start() > (In Tokio Spawn) > {:?}", + "Routine > restart() > {:?}", self_lock.module )), Some(&self_lock.parent_params.msg), ); Log::flush(); - Err("NOT IMPLEMENTED".to_string()) + Ok("Restarted successfully".to_string()) } - pub fn change_channel( - &self, - _channel : Channel + pub async fn change_channel( + &mut self, + channel : Channel ) -> Result - // [ ] => 03.27 - WIP - NOT IMPLEMENTED + // [ ] => 03.28 - REVIEW FOR COMPLETION { - // [ ] Think Ideally it should try to + // [x] Think Ideally it should try to // change the target channel of the // internal process too if possible? - Err("NOT IMPLEMENTED".to_string()) + self.channel = channel; + + + let self_rw = Arc::new(RwLock::new(self)); + + let self_lock = self_rw.read().await; + + botlog::trace( + format!( + "[ROUTINE][Change Channel] {} in {}", + self_lock.name,self_lock.channel.0 + ) + .as_str(), + Some(format!( + "Routine > restart() > {:?}", + self_lock.module + )), + Some(&self_lock.parent_params.msg), + ); + + Log::flush(); + + // Err("NOT IMPLEMENTED".to_string()) + Ok("Changed Successfully".to_string()) + } + + + pub async fn set_routine_attributes( + &mut self, + routine_attr : Vec + ) -> Result + // [ ] => 03.27 - WIP - NOT IMPLEMENTED + { + // This is way to custom set attributes first + // They will Be Validated before being applied + // IDEALLY the routine also be restarted afterwards externally + + Routine::validate_attr(&routine_attr).await?; + + + let self_rw = Arc::new(RwLock::new(self)); + { + let mut self_lock = self_rw.write().await; + self_lock.routine_attr = routine_attr; + } + + // let self_rw = Arc::new(RwLock::new(self)); + + let self_lock = self_rw.read().await; + + botlog::trace( + format!( + "[ROUTINE][Set Routine Attributes] {} in {}", + self_lock.name,self_lock.channel.0 + ) + .as_str(), + Some(format!( + "Routine > restart() > {:?}", + self_lock.module + )), + Some(&self_lock.parent_params.msg), + ); + + Log::flush(); + + + Ok("Changed Successfully".to_string()) } -- 2.46.1 From 2a1a7f8503e4d8273cae133b7db32c581a3f2cad Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Thu, 28 Mar 2024 04:39:03 -0400 Subject: [PATCH 16/23] ExecBody & routine addl references --- src/core/bot_actions.rs | 2 +- src/core/botinstance.rs | 5 +++ src/core/botmodules.rs | 57 +++++++++++++++++++++--- src/custom/experimental/experiment003.rs | 36 +++++++-------- 4 files changed, 74 insertions(+), 26 deletions(-) diff --git a/src/core/bot_actions.rs b/src/core/bot_actions.rs index 9ff41b5..130be94 100644 --- a/src/core/bot_actions.rs +++ b/src/core/bot_actions.rs @@ -16,7 +16,7 @@ pub type RoutineAR = Arc>; pub struct ExecBodyParams { pub bot : BotAR, pub msg : PrivmsgMessage, - // pub parent_act : ActAR , + pub parent_act : Option , pub curr_act : ActAR , } diff --git a/src/core/botinstance.rs b/src/core/botinstance.rs index 563856f..86ac8bb 100644 --- a/src/core/botinstance.rs +++ b/src/core/botinstance.rs @@ -404,6 +404,7 @@ impl BotInstance { let params = ExecBodyParams { bot : Arc::clone(&bot), msg : (*msg).clone(), + parent_act : None, curr_act : Arc::clone(&act_clone), }; @@ -461,6 +462,7 @@ impl BotInstance { let params = ExecBodyParams { bot : Arc::clone(&bot), msg : (*msg).clone(), + parent_act : None, curr_act : Arc::clone(&act_clone), }; @@ -491,6 +493,7 @@ impl BotInstance { let params = ExecBodyParams { bot : Arc::clone(&bot), msg : (*msg).clone(), + parent_act : None, curr_act : Arc::clone(&act_clone), }; @@ -516,6 +519,7 @@ impl BotInstance { c.execute(ExecBodyParams { bot : a, msg : msg.clone() , + parent_act : None, curr_act : Arc::clone(&act_clone), }).await; @@ -564,6 +568,7 @@ impl BotInstance { l.execute(ExecBodyParams { bot : a, msg : msg.clone() , + parent_act : None, curr_act : Arc::clone(&act_clone), } ).await; } diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index e320e7f..17c570a 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -637,12 +637,39 @@ pub struct Routine { remaining_iterations : Option , routine_attr : Vec , pub internal_signal : RoutineSignal , + pub self_routine_ar : Option , + pub self_act_ar : Option , } impl Routine { + // pub fn set + // pub async fn refresh_self_ref(self) { + pub async fn refresh_routine_internal(routine_ar : RoutineAR) + { + + /* + Execute after the Routine is constructed + - If not, a start() will also call this + + */ + + // 1. Update the self reference to itself + + let mut mut_lock = routine_ar.write().await; + mut_lock.self_routine_ar = Some(routine_ar.clone()); + + // 2. Update the current self_act_ar + mut_lock.self_act_ar = Some(Arc::new(RwLock::new(BotAction::R(routine_ar.clone())))); + + + + + + } + pub async fn validate_attr(routine_attr : &Vec) -> Result @@ -819,6 +846,8 @@ impl Routine { remaining_iterations : None , routine_attr : routine_attr , internal_signal : RoutineSignal::NotStarted , + self_routine_ar : None , + self_act_ar : None , }))) ; @@ -831,6 +860,10 @@ impl Routine { // [ ] => 03.27 - REVIEW FOR COMPLETION { + + // [x] Prep by updating it's own self reference + Routine::refresh_routine_internal(trg_routine_ar.clone()).await; + // [x] Asyncio Spawn likely around here // [x] & Assigns self.join_handle @@ -1005,7 +1038,8 @@ impl Routine { // [x] execution body - trg_routine_ar.read().await.loopbody().await; + // trg_routine_ar.read().await.loopbody().await; + trg_routine_ar.write().await.loopbody().await; { // [x] End of Loop iteration @@ -1100,7 +1134,7 @@ impl Routine { } - async fn loopbody(&self) + async fn loopbody(&mut self) // [x] => 03.27 - COMPLETED { botlog::trace( @@ -1112,10 +1146,23 @@ impl Routine { ); Log::flush(); - - (self.exec_body)( - self.parent_params.clone() + + let self_ar = Arc::new(RwLock::new(self)); + + { + let mut mutlock = self_ar.write().await; + + mutlock.parent_params.parent_act = Some(mutlock.parent_params.curr_act.clone()); + mutlock.parent_params.curr_act = mutlock.self_act_ar.to_owned().unwrap(); + } + + (self_ar.read().await.exec_body)( + self_ar.read().await.parent_params.clone() ).await; + + // (self.exec_body)( + // self.parent_params.clone() + // ).await; } pub async fn stop(&mut self) -> Result diff --git a/src/custom/experimental/experiment003.rs b/src/custom/experimental/experiment003.rs index 9b8f91e..343cece 100644 --- a/src/custom/experimental/experiment003.rs +++ b/src/custom/experimental/experiment003.rs @@ -141,28 +141,24 @@ async fn test3_body(params : ExecBodyParams) { if let Ok(newr) = a { + // NOTE : The below is a "Playing aound" feature + // In the below, we're unnecessarily adjusting the ExecBodyParams of the parent + + // To get the reference to the Routine or the BotAction there are now refernces to itself + // [ ] before execute , be sure to adjust curr_act - // let mut params_mut = params.clone(); - let mut params_mut = params; - // let newr_ar = Arc::new(RwLock::new(newr)); + // let mut params_mut = params; let newr_ar = newr.clone(); - params_mut.curr_act = Arc::new(RwLock::new( - BotAction::R(newr_ar.clone()) - )); - - // let a = newr_ar.read().await; - // let rslt = (&*a).start().await; - - // let mut newr_lock = newr_ar.write().await; - - // let rslt = newr_ar.write().await.start().await; + // params_mut.curr_act = Arc::new(RwLock::new( + // BotAction::R(newr_ar.clone()) + // )); - { - newr_ar.write().await.parent_params = params_mut.clone(); - } + // { + // newr_ar.write().await.parent_params = params_mut.clone(); + // } let rslt = Routine::start(newr_ar.clone()).await; @@ -179,12 +175,12 @@ async fn test3_body(params : ExecBodyParams) { rsltstr ).as_str(), Some("experiment003 > test3_body".to_string()), - Some(¶ms_mut.msg), + Some(¶ms.msg), ); Log::flush(); - let bot = Arc::clone(¶ms_mut.bot); + let bot = Arc::clone(¶ms.bot); let botlock = bot.read().await; @@ -193,9 +189,9 @@ async fn test3_body(params : ExecBodyParams) { .botmgrs .chat .say_in_reply_to( - ¶ms_mut.msg, + ¶ms.msg, format!("Routine Result : {:?}",rsltstr), - params_mut.clone() + params.clone() ).await; // [x] Will not be handling JoinHandles here . If immediate abort() handling is required, below is an example that works -- 2.46.1 From 6d3b5eee41f0600ecacf26440f1313b5fbd8649b Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Thu, 28 Mar 2024 11:50:08 -0400 Subject: [PATCH 17/23] routine assigns self reference at construct --- src/core/botmodules.rs | 62 +++++++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 19 deletions(-) diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index 17c570a..8e172f6 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -645,30 +645,30 @@ pub struct Routine { impl Routine { - // pub fn set - // pub async fn refresh_self_ref(self) { - pub async fn refresh_routine_internal(routine_ar : RoutineAR) - { + // // pub fn set + // // pub async fn refresh_self_ref(self) { + // pub async fn refresh_routine_internal(routine_ar : RoutineAR) + // { - /* - Execute after the Routine is constructed - - If not, a start() will also call this + // /* + // Execute after the Routine is constructed + // - If not, a start() will also call this - */ + // */ - // 1. Update the self reference to itself + // // 1. Update the self reference to itself - let mut mut_lock = routine_ar.write().await; - mut_lock.self_routine_ar = Some(routine_ar.clone()); + // let mut mut_lock = routine_ar.write().await; + // mut_lock.self_routine_ar = Some(routine_ar.clone()); - // 2. Update the current self_act_ar - mut_lock.self_act_ar = Some(Arc::new(RwLock::new(BotAction::R(routine_ar.clone())))); + // // 2. Update the current self_act_ar + // mut_lock.self_act_ar = Some(Arc::new(RwLock::new(BotAction::R(routine_ar.clone())))); - } + // } pub async fn validate_attr(routine_attr : &Vec) @@ -833,8 +833,8 @@ impl Routine { { Routine::validate_attr(&routine_attr).await?; - - return Ok(Arc::new(RwLock::new(Routine { + + let routine_ar = Arc::new(RwLock::new(Routine { name , module , channel , @@ -848,7 +848,31 @@ impl Routine { internal_signal : RoutineSignal::NotStarted , self_routine_ar : None , self_act_ar : None , - }))) ; + })); + + let mut mut_lock = routine_ar.write().await; + mut_lock.self_routine_ar = Some(routine_ar.clone()); + + // 2. Update the current self_act_ar + mut_lock.self_act_ar = Some(Arc::new(RwLock::new(BotAction::R(routine_ar.clone())))); + + Ok(routine_ar.clone()) + + // return Ok(Arc::new(RwLock::new(Routine { + // name , + // module , + // channel , + // exec_body , + // parent_params , + // join_handle : None , + // start_time : None , + // complete_iterations : 0 , + // remaining_iterations : None , + // routine_attr : routine_attr , + // internal_signal : RoutineSignal::NotStarted , + // self_routine_ar : None , + // self_act_ar : None , + // }))) ; } @@ -861,8 +885,8 @@ impl Routine { { - // [x] Prep by updating it's own self reference - Routine::refresh_routine_internal(trg_routine_ar.clone()).await; + // // [x] Prep by updating it's own self reference + // Routine::refresh_routine_internal(trg_routine_ar.clone()).await; // [x] Asyncio Spawn likely around here // [x] & Assigns self.join_handle -- 2.46.1 From c27dd3b86f38646bebe1d4dd20c8707171df4140 Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Thu, 28 Mar 2024 13:18:02 -0400 Subject: [PATCH 18/23] custom countdown --- src/core/botmodules.rs | 2 +- src/custom/experimental/experiment003.rs | 216 +++++++++++++++++++++++ 2 files changed, 217 insertions(+), 1 deletion(-) diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index 8e172f6..3e6aead 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -634,7 +634,7 @@ pub struct Routine { pub join_handle : Option>>> , start_time : Option> , pub complete_iterations : i64 , - remaining_iterations : Option , + pub remaining_iterations : Option , routine_attr : Vec , pub internal_signal : RoutineSignal , pub self_routine_ar : Option , diff --git a/src/custom/experimental/experiment003.rs b/src/custom/experimental/experiment003.rs index 343cece..5532dfe 100644 --- a/src/custom/experimental/experiment003.rs +++ b/src/custom/experimental/experiment003.rs @@ -16,6 +16,9 @@ const OF_CMD_CHANNEL:Channel = Channel(String::new()); use casual_logger::Log; use rand::Rng; +use rand::thread_rng; +use rand::rngs::StdRng; +use rand::seq::SliceRandom; use tokio::sync::RwLock; use std::borrow::Borrow; use std::sync::Arc; @@ -50,9 +53,222 @@ pub async fn init(mgr: Arc) { botc1.add_to_modmgr(Arc::clone(&mgr)).await; + // 1. Define the BotAction + let botc1 = BotCommand { + module: BotModule(String::from("experiments003")), + command: String::from("countdown"), // command call name + alias: vec![], // String of alternative names + exec_body: actions_util::asyncbox(countdown_chnl_v1), + help: String::from("Test Command tester"), + required_roles: vec![ + BotAdmin, + Mod(OF_CMD_CHANNEL), + ], + }; + + // 2. Add the BotAction to ModulesManager + botc1.add_to_modmgr(Arc::clone(&mgr)).await; + + + } +async fn countdown_chnl_v1(params : ExecBodyParams) { + + botlog::debug( + "[CHILDFN] countdown_chnl() triggered!", + Some("Experiments003 > countdown_chnl()".to_string()), + Some(¶ms.msg), + ); + + + /* + create a fun countdown BotCommand that allows an Elevated Chatter to + -a add channels to target a routine message + -start to start the routine with an input String, that sends a number + of messages to the targeted channels with a countdown, until it + reaches 0 when it sends a cute or funny message + + NOTE : At the moment, I don't have customizable persistence, so I would just use + counters from the Routine itself + */ + + /* + Because of some bot core features are not available, v1.0 of this could be : + [x] 1. Create a Routine & start a routine + [x] 2. Have the routine go through each joined channel randomly and countdown + [x] 3. At the end, say "0, I love you uwu~" in the last chosen channel + */ + + /* + Usage => 03.28 - skipping arguments as functinoality isn't enhanced + + -a => 03.28 - Not sure if this is possible at the moment? + + -start + + -stop => 03.28 - Not sure if this is possible at the moment? + + */ + + /* + [ ] Functional Use Case + + 1. -a adds targetted channels + + */ + + // [-] Unwraps arguments from message + + // let (arg1, arg2) = { + + // let mut argv = params.msg.message_text.split(' '); + + // argv.next(); // Skip the command name + + // let arg1 = argv.next(); + + // let arg2 = argv.next(); + + // (arg1, arg2) + // }; + + + + // [ ] 1. Create a Routine & start a routine + + // let parentmodule = params.get_parent_module().await; + let module = params.get_module().await; + let channel = params.get_channel().await; + let routine_attr = vec![ + RoutineAttr::RunOnce + ]; + // let exec_body = actions_util::asyncbox(rtestbody); + let exec_body = actions_util::asyncbox(innertester); // <-- 03.27 - when below is uncommented, this is throwing an issue + + async fn innertester(params : ExecBodyParams) { + + + + let logmsg_botact = match *params.curr_act.read().await { + BotAction::C(_) => "command", + BotAction::R(_) => "routine", + BotAction::L(_) => "listener", + } ; + + + botlog::trace( + format!("Params > Curr_act type : {:?}", logmsg_botact).as_str(), + Some("Experiments003 > countdown_chnl()".to_string()), + Some(¶ms.msg), + ); + Log::flush(); + + let bot = Arc::clone(¶ms.bot); + + let botlock = bot.read().await; + + if let BotAction::R(arr) = &*params.curr_act.read().await { + + let iterleft = arr.read().await.remaining_iterations.unwrap_or(0); + + // [ ] get joined channels + let joinedchannels = botlock.bot_channels.clone(); + + + fn pick_a_channel(chnlvec : Vec) -> Channel { + + // More Information : https://docs.rs/rand/0.7.2/rand/seq/trait.SliceRandom.html#tymethod.choose + + let mut rng = thread_rng(); + + // let joinedchannels = botlock.bot_channels.clone(); + (*chnlvec.choose(&mut rng).unwrap()).clone() + } + + let chosen_channel = pick_a_channel(joinedchannels); + + let outmsg = if iterleft == 1 { + format!("{} I love you uwu~",iterleft) + } else { format!("{}",iterleft) }; + + botlock.botmgrs.chat + .say( + // joinedchannels.choose(&mut rng).unwrap().0.clone(), + chosen_channel.0.clone(), + outmsg, + params.clone() + ).await; + + } + + + } + + + + // [ ] setup the routine + if let Ok(newr) = Routine::from( + "Routine Test".to_string(), + module, + channel.unwrap(), + routine_attr, + exec_body, + params.clone() + ).await { + let newr_ar = newr.clone(); + // [ ] start the routine + if let Ok(_) = Routine::start(newr_ar.clone()).await { + + + botlog::debug( + "Successfully started", + Some("experiment003 > countdown_chnl()".to_string()), + Some(¶ms.msg), + ); + + + Log::flush(); + + let bot = Arc::clone(¶ms.bot); + + let botlock = bot.read().await; + + // uses chat.say_in_reply_to() for the bot controls for messages + botlock + .botmgrs + .chat + .say_in_reply_to( + ¶ms.msg, + "Started Routine!".to_string(), + params.clone() + ).await; + + + + } + + + } + + + // botlock + // .botmgrs + // .chat + // .say_in_reply_to( + // ¶ms.msg, + // format!("{:?}",), + // params.clone() + // ).await; + + + +} + + + + async fn test3_body(params : ExecBodyParams) { // println!("testy triggered!"); // NOTE : This test function intends to print (e.g., to stdout) at fn call botlog::debug( -- 2.46.1 From 1b534ebeb7e190cff227217bfa5be816f6e301c8 Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Thu, 28 Mar 2024 13:46:02 -0400 Subject: [PATCH 19/23] fixed routine attr validation logic --- src/core/botmodules.rs | 126 +++++++++++++---------- src/custom/experimental/experiment003.rs | 4 +- 2 files changed, 72 insertions(+), 58 deletions(-) diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index 3e6aead..3c28937 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -691,45 +691,71 @@ impl Routine { // adjust the below for those that are work in progress or that are implemented // - This will allow other functions to validate that it is implemented - // WORK IN PROGRESS VECTOR - Vec<$RoutineAttr> + // // WORK IN PROGRESS VECTOR - Vec<$RoutineAttr> - let wip_attr:Vec = vec![ - RoutineAttr::DelayedStart, - RoutineAttr::ScheduledStart(chrono::offset::Local::now()), - RoutineAttr::LoopDuration(Duration::from_secs(1)), - RoutineAttr::LoopInfinitely, // Note : There's no added implementation for this - RoutineAttr::RunOnce, - RoutineAttr::MaxTimeThreshold(chrono::offset::Local::now()), - RoutineAttr::MaxIterations(1), + // let wip_attr:Vec = vec![ + // RoutineAttr::DelayedStart, + // RoutineAttr::ScheduledStart(chrono::offset::Local::now()), + // RoutineAttr::LoopDuration(Duration::from_secs(1)), + // RoutineAttr::LoopInfinitely, // Note : There's no added implementation for this + // RoutineAttr::RunOnce, + // RoutineAttr::MaxTimeThreshold(chrono::offset::Local::now()), + // RoutineAttr::MaxIterations(1), - ]; + // ]; - let implemented_attr:Vec = vec![ - ]; + // let implemented_attr:Vec = vec![ + // ]; // [x] 2. Built in Logic will check these vectors, and return if Not Implemented - 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() + // 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() + // } + // ); + + + for given_routine in routine_attr { + + if !matches!(given_routine,RoutineAttr::DelayedStart) + && !matches!(given_routine,RoutineAttr::ScheduledStart(_)) + && !matches!(given_routine,RoutineAttr::LoopDuration(_)) + && !matches!(given_routine,RoutineAttr::LoopInfinitely) + && !matches!(given_routine,RoutineAttr::RunOnce) + && !matches!(given_routine,RoutineAttr::MaxTimeThreshold(_)) + && !matches!(given_routine,RoutineAttr::MaxIterations(_)) + { + botlog::trace( + "[ERROR][Routine Feature NOT IMPLEMENTED]", + Some("Routine > Validate_attr()".to_string()), + None, + ); + + Log::flush(); + + return Err("NOT IMPLEMENTED".to_string()); } - ); - if unimplemented.next().is_some() { + }; - botlog::trace( - "[ERROR][Routine Feature NOT IMPLEMENTED]", - Some("Routine > Validate_attr()".to_string()), - None, - ); + + + // if unimplemented.next().is_some() { + + // botlog::trace( + // "[ERROR][Routine Feature NOT IMPLEMENTED]", + // Some("Routine > Validate_attr()".to_string()), + // None, + // ); - Log::flush(); + // Log::flush(); - return Err("NOT IMPLEMENTED".to_string()); - } + // return Err("NOT IMPLEMENTED".to_string()); + // } @@ -772,40 +798,26 @@ impl Routine { // [x] 4. If all other failure checks above works, ensure one more time that the attribute is implemented // - If not, routine NOT IMPLEMENTED error - if 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() - }) - .next() - .is_none() - { + // if 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() + // }) + // .next() + // .is_none() + // { - botlog::trace( - "[ERROR][Routine Feature NOT IMPLEMENTED]", - Some("Routine > Validate_attr()".to_string()), - None, - ); + botlog::trace( + "[ERROR][Routine Feature NOT IMPLEMENTED]", + Some("Routine > Validate_attr()".to_string()), + None, + ); - Log::flush(); + Log::flush(); - Ok("Implemented & Validated".to_string()) + Ok("Implemented & Validated".to_string()) - } else { - - - botlog::trace( - "[ERROR][Routine Feature NOT IMPLEMENTED]", - Some("Routine > Validate_attr()".to_string()), - None, - ); - - Log::flush(); - - Err("NOT IMPLEMENTED".to_string()) - - } } diff --git a/src/custom/experimental/experiment003.rs b/src/custom/experimental/experiment003.rs index 5532dfe..66f4f81 100644 --- a/src/custom/experimental/experiment003.rs +++ b/src/custom/experimental/experiment003.rs @@ -142,7 +142,9 @@ async fn countdown_chnl_v1(params : ExecBodyParams) { let module = params.get_module().await; let channel = params.get_channel().await; let routine_attr = vec![ - RoutineAttr::RunOnce + // RoutineAttr::RunOnce + RoutineAttr::MaxIterations(5), + RoutineAttr::LoopDuration(Duration::from_secs(1)) ]; // let exec_body = actions_util::asyncbox(rtestbody); let exec_body = actions_util::asyncbox(innertester); // <-- 03.27 - when below is uncommented, this is throwing an issue -- 2.46.1 From 26f67787d7ce54157a16ba454c3760abc4c67019 Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Thu, 28 Mar 2024 15:07:24 -0400 Subject: [PATCH 20/23] addl debugging --- src/core/botmodules.rs | 2 +- src/custom/experimental/experiment003.rs | 49 ++++++++++++++++++++++-- 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index 3c28937..3da6122 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -795,7 +795,7 @@ impl Routine { - // [x] 4. If all other failure checks above works, ensure one more time that the attribute is implemented + // [x] 4. If all other failure checks above works, ensure one more time that the atstribute is implemented // - If not, routine NOT IMPLEMENTED error // if routine_attr.iter() diff --git a/src/custom/experimental/experiment003.rs b/src/custom/experimental/experiment003.rs index 66f4f81..d40d7ab 100644 --- a/src/custom/experimental/experiment003.rs +++ b/src/custom/experimental/experiment003.rs @@ -21,6 +21,7 @@ use rand::rngs::StdRng; use rand::seq::SliceRandom; use tokio::sync::RwLock; use std::borrow::Borrow; +use std::borrow::BorrowMut; use std::sync::Arc; use crate::core::bot_actions::ExecBodyParams; @@ -173,24 +174,63 @@ async fn countdown_chnl_v1(params : ExecBodyParams) { if let BotAction::R(arr) = &*params.curr_act.read().await { - let iterleft = arr.read().await.remaining_iterations.unwrap_or(0); + botlog::trace( + "Before loading remaining iterations", + Some("Experiments003 > countdown_chnl()".to_string()), + None, + ); + Log::flush(); + + + // let iterleft = arr.read().await.remaining_iterations.unwrap_or(0); + + // let iterleft = if arr.read().await.remaining_iterations.is_none() { 0i64 } + // else { arr.read().await.remaining_iterations.unwrap() }; + let iterleft = match arr.read().await.remaining_iterations { + None => 0, + Some(a) => a, + }; + + + botlog::trace( + "after loading remaining iterations", + Some("Experiments003 > countdown_chnl()".to_string()), + None, + ); + Log::flush(); // [ ] get joined channels let joinedchannels = botlock.bot_channels.clone(); fn pick_a_channel(chnlvec : Vec) -> Channel { + + + botlog::trace( + "In Pick_a_Channel()", + Some("Experiments003 > countdown_chnl()".to_string()), + None, + ); + Log::flush(); // More Information : https://docs.rs/rand/0.7.2/rand/seq/trait.SliceRandom.html#tymethod.choose let mut rng = thread_rng(); - // let joinedchannels = botlock.bot_channels.clone(); + // let joinedchannels = botlock.bot_channels.clone(); (*chnlvec.choose(&mut rng).unwrap()).clone() } + let chosen_channel = pick_a_channel(joinedchannels); + botlog::trace( + format!("Picked a channel: {:?}", chosen_channel).as_str(), + Some("Experiments003 > countdown_chnl()".to_string()), + Some(¶ms.msg), + ); + Log::flush(); + let outmsg = if iterleft == 1 { format!("{} I love you uwu~",iterleft) } else { format!("{}",iterleft) }; @@ -247,7 +287,10 @@ async fn countdown_chnl_v1(params : ExecBodyParams) { params.clone() ).await; - + // let jhandle = newr.clone().read().await.join_handle.clone().unwrap(); + // let a = jhandle.write().await; + // a. + // sleep(Duration::from_secs(300)).await; } -- 2.46.1 From 5c35ad114a7df9628046775a4334ad930e19c83f Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Thu, 28 Mar 2024 17:52:43 -0400 Subject: [PATCH 21/23] ISSUE - commented out problem code? --- src/custom/experimental/experiment003.rs | 32 ++++++++++++------------ 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/custom/experimental/experiment003.rs b/src/custom/experimental/experiment003.rs index d40d7ab..c881d90 100644 --- a/src/custom/experimental/experiment003.rs +++ b/src/custom/experimental/experiment003.rs @@ -184,12 +184,12 @@ async fn countdown_chnl_v1(params : ExecBodyParams) { // let iterleft = arr.read().await.remaining_iterations.unwrap_or(0); - // let iterleft = if arr.read().await.remaining_iterations.is_none() { 0i64 } - // else { arr.read().await.remaining_iterations.unwrap() }; - let iterleft = match arr.read().await.remaining_iterations { - None => 0, - Some(a) => a, - }; + // // let iterleft = if arr.read().await.remaining_iterations.is_none() { 0i64 } + // // else { arr.read().await.remaining_iterations.unwrap() }; + // let iterleft = match arr.read().await.remaining_iterations { + // None => 0, + // Some(a) => a, + // }; botlog::trace( @@ -231,17 +231,17 @@ async fn countdown_chnl_v1(params : ExecBodyParams) { ); Log::flush(); - let outmsg = if iterleft == 1 { - format!("{} I love you uwu~",iterleft) - } else { format!("{}",iterleft) }; + // let outmsg = if iterleft == 1 { + // format!("{} I love you uwu~",iterleft) + // } else { format!("{}",iterleft) }; - botlock.botmgrs.chat - .say( - // joinedchannels.choose(&mut rng).unwrap().0.clone(), - chosen_channel.0.clone(), - outmsg, - params.clone() - ).await; + // botlock.botmgrs.chat + // .say( + // // joinedchannels.choose(&mut rng).unwrap().0.clone(), + // chosen_channel.0.clone(), + // outmsg, + // params.clone() + // ).await; } -- 2.46.1 From 66195138f83cc6443dbaccd349d0fdf2183609d3 Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Thu, 28 Mar 2024 20:21:49 -0400 Subject: [PATCH 22/23] corrected error with validate_attr --- src/core/botmodules.rs | 61 +++++++++++++++++------- src/custom/experimental/experiment003.rs | 10 ++++ 2 files changed, 55 insertions(+), 16 deletions(-) diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index 3da6122..2cfbb77 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -580,7 +580,7 @@ impl BotActionTrait for Listener { } // #[derive(Debug, PartialEq, Eq, Hash, Clone)] -#[derive(PartialEq, Eq, Hash)] +#[derive(Debug, PartialEq, Eq, Hash)] pub enum RoutineAttr { DelayedStart, ScheduledStart(DateTime), // Scheduled Date (if any) after which, if not started, may trigger @@ -718,31 +718,60 @@ impl Routine { // } // ); + let mut attribute_supported = false; for given_routine in routine_attr { - if !matches!(given_routine,RoutineAttr::DelayedStart) - && !matches!(given_routine,RoutineAttr::ScheduledStart(_)) - && !matches!(given_routine,RoutineAttr::LoopDuration(_)) - && !matches!(given_routine,RoutineAttr::LoopInfinitely) - && !matches!(given_routine,RoutineAttr::RunOnce) - && !matches!(given_routine,RoutineAttr::MaxTimeThreshold(_)) - && !matches!(given_routine,RoutineAttr::MaxIterations(_)) + // if !matches!(given_routine,RoutineAttr::DelayedStart) + // && !matches!(given_routine,RoutineAttr::ScheduledStart(_)) + // && !matches!(given_routine,RoutineAttr::LoopDuration(_)) + // && !matches!(given_routine,RoutineAttr::LoopInfinitely) + // && !matches!(given_routine,RoutineAttr::RunOnce) + // && !matches!(given_routine,RoutineAttr::MaxTimeThreshold(_)) + // && !matches!(given_routine,RoutineAttr::MaxIterations(_)) + if matches!(given_routine,RoutineAttr::DelayedStart) + || matches!(given_routine,RoutineAttr::ScheduledStart(_)) + || matches!(given_routine,RoutineAttr::LoopDuration(_)) + || matches!(given_routine,RoutineAttr::LoopInfinitely) + || matches!(given_routine,RoutineAttr::RunOnce) + || matches!(given_routine,RoutineAttr::MaxTimeThreshold(_)) + || matches!(given_routine,RoutineAttr::MaxIterations(_)) + { - botlog::trace( - "[ERROR][Routine Feature NOT IMPLEMENTED]", - Some("Routine > Validate_attr()".to_string()), - None, - ); - Log::flush(); + attribute_supported = true; - return Err("NOT IMPLEMENTED".to_string()); } }; + if !attribute_supported { + botlog::trace( + "[ERROR][Routine Feature NOT IMPLEMENTED]", + Some("Routine > Validate_attr()".to_string()), + None, + ); + + Log::flush(); + + botlog::trace( + format!( + "[ERROR][Routine Feature NOT IMPLEMENTED] > Problem Routine - {:?}" + ,routine_attr).as_str(), + Some("Routine > Validate_attr()".to_string()), + None, + ); + + Log::flush(); + + return Err("NOT IMPLEMENTED".to_string()); + } + + + + + // if unimplemented.next().is_some() { @@ -809,7 +838,7 @@ impl Routine { // { botlog::trace( - "[ERROR][Routine Feature NOT IMPLEMENTED]", + "[OK][Implemented & Validated]", Some("Routine > Validate_attr()".to_string()), None, ); diff --git a/src/custom/experimental/experiment003.rs b/src/custom/experimental/experiment003.rs index c881d90..a37066f 100644 --- a/src/custom/experimental/experiment003.rs +++ b/src/custom/experimental/experiment003.rs @@ -191,6 +191,16 @@ async fn countdown_chnl_v1(params : ExecBodyParams) { // Some(a) => a, // }; + // let routine_lock = arr.read().await; + // if let Some(a) = routine_lock.remaining_iterations.clone() { + // println!("Remaining iterations > {}",a) + // } + + { + let routine_lock = arr.write().await; + let a = routine_lock.remaining_iterations; + println!("remaining iterations : {:?}", a); +} botlog::trace( "after loading remaining iterations", -- 2.46.1 From b5e95668a514fd7e59190b5d161a1cb346947848 Mon Sep 17 00:00:00 2001 From: ModulatingForce <116608425+modulatingforce@users.noreply.github.com> Date: Fri, 29 Mar 2024 09:03:16 -0400 Subject: [PATCH 23/23] ISSUE - potential lock issue --- src/core/botmodules.rs | 4 +- src/custom/experimental/experiment003.rs | 127 +++++++++++++++-------- 2 files changed, 87 insertions(+), 44 deletions(-) diff --git a/src/core/botmodules.rs b/src/core/botmodules.rs index 2cfbb77..f4dfb18 100644 --- a/src/core/botmodules.rs +++ b/src/core/botmodules.rs @@ -1104,7 +1104,9 @@ impl Routine { // [x] execution body // trg_routine_ar.read().await.loopbody().await; - trg_routine_ar.write().await.loopbody().await; + { + trg_routine_ar.write().await.loopbody().await; + } { // [x] End of Loop iteration diff --git a/src/custom/experimental/experiment003.rs b/src/custom/experimental/experiment003.rs index a37066f..41c1d65 100644 --- a/src/custom/experimental/experiment003.rs +++ b/src/custom/experimental/experiment003.rs @@ -152,34 +152,44 @@ async fn countdown_chnl_v1(params : ExecBodyParams) { async fn innertester(params : ExecBodyParams) { - + { + let curract_guard = params.curr_act.read().await; + - let logmsg_botact = match *params.curr_act.read().await { - BotAction::C(_) => "command", - BotAction::R(_) => "routine", - BotAction::L(_) => "listener", - } ; + // let logmsg_botact = match *params.curr_act.read().await { + + let logmsg_botact = match *curract_guard { + BotAction::C(_) => "command", + BotAction::R(_) => "routine", + BotAction::L(_) => "listener", + } ; - botlog::trace( - format!("Params > Curr_act type : {:?}", logmsg_botact).as_str(), - Some("Experiments003 > countdown_chnl()".to_string()), - Some(¶ms.msg), - ); - Log::flush(); - - let bot = Arc::clone(¶ms.bot); - - let botlock = bot.read().await; - - if let BotAction::R(arr) = &*params.curr_act.read().await { - botlog::trace( - "Before loading remaining iterations", + format!("Params > Curr_act type : {:?}", logmsg_botact).as_str(), Some("Experiments003 > countdown_chnl()".to_string()), - None, + Some(¶ms.msg), ); Log::flush(); + } + + { + let bot = Arc::clone(¶ms.bot); + let botlock = bot.read().await; + + let curract_guard = params.curr_act.write().await; + + // let routine_lock = arr.write().await; + + if let BotAction::R(arr) = &*curract_guard { + // if let BotAction::R(arr) = &*params.curr_act.read().await { + + botlog::trace( + "Before loading remaining iterations", + Some("Experiments003 > countdown_chnl()".to_string()), + None, + ); + Log::flush(); // let iterleft = arr.read().await.remaining_iterations.unwrap_or(0); @@ -197,10 +207,10 @@ async fn countdown_chnl_v1(params : ExecBodyParams) { // } { - let routine_lock = arr.write().await; - let a = routine_lock.remaining_iterations; - println!("remaining iterations : {:?}", a); -} + let routine_lock = arr.write().await; + let a = routine_lock.remaining_iterations; + println!("remaining iterations : {:?}", a); + } botlog::trace( "after loading remaining iterations", @@ -251,9 +261,12 @@ async fn countdown_chnl_v1(params : ExecBodyParams) { // chosen_channel.0.clone(), // outmsg, // params.clone() + + // ).await; } + } } @@ -361,27 +374,55 @@ async fn test3_body(params : ExecBodyParams) { async fn rtestbody(params : ExecBodyParams) { - let logmsg_botact = match *params.curr_act.read().await { - BotAction::C(_) => "command", - BotAction::R(_) => "routine", - BotAction::L(_) => "listener", - } ; + let guard = params.curr_act.read().await; + { + let logmsg_botact = match *guard { + BotAction::C(_) => "command", + BotAction::R(_) => "routine", + BotAction::L(_) => "listener", + } ; - botlog::trace( - format!("Params > Curr_act type : {:?}", logmsg_botact).as_str(), - Some("Experiments003 > test3 command body".to_string()), - Some(¶ms.msg), - ); - Log::flush(); + botlog::trace( + format!("Params > Curr_act type : {:?}", logmsg_botact).as_str(), + Some("Experiments003 > test3 command body".to_string()), + Some(¶ms.msg), + ); + Log::flush(); + } - if let BotAction::R(arr) = &*params.curr_act.read().await { - for curriter in 0..5 { - println!("tester - Routine - Completed Iterations : {}", - arr.read().await.complete_iterations); - println!("tester - Custom Loop - Completed Iterations : {}", - curriter); - sleep(Duration::from_secs_f64(0.5)).await; + + { + let logmsg_botact = match *guard { + BotAction::C(_) => "command 2", + BotAction::R(_) => "routine 2", + BotAction::L(_) => "listener 2", + } ; + + botlog::trace( + format!("Params > Curr_act type : {:?}", logmsg_botact).as_str(), + Some("Experiments003 > test3 command body".to_string()), + Some(¶ms.msg), + ); + Log::flush(); + } + + + { + println!("Critical code area start"); // <= 03.29 - This is printed + if let BotAction::R(c) = &*guard { + println!("{:?}",c.read().await.channel); } + println!("Critical code area end"); // <= 03.29 - ISSUE This is NOT printed + + // if let BotAction::R(arr) = &*params.curr_act.read().await { + // for curriter in 0..5 { + // println!("tester - Routine - Completed Iterations : {}", + // arr.read().await.complete_iterations); + // println!("tester - Custom Loop - Completed Iterations : {}", + // curriter); + // sleep(Duration::from_secs_f64(0.5)).await; + // } + // } } } -- 2.46.1