feat: add bot_id to system_automations and enhance schedule handling
- Introduced `bot_id` column in `system_automations` table (migration 6.0.0.sql) and updated the Diesel schema/model to include it. - Adjusted migrations to remove the hard‑coded “Update Summary” automation and only create an index on the `name` column. - Extended the `SET_SCHEDULE` keyword: - Added a second string argument for the script name. - Passed the invoking user's `bot_id` to the database layer. - Updated function signature to accept a full `UserSession` instead of discarding it. - Modified `execute_set_schedule` to store `bot_id`, script name, and activation flag; added conflict handling on `(bot_id, param)` to update schedule and reset trigger state. - Updated imports and logging to reflect new parameters. These changes enable per‑bot automation management, allow specifying the script to run, and improve idempotent schedule updates.
This commit is contained in:
parent
0f842adf69
commit
d2ee695d8b
6 changed files with 41 additions and 28 deletions
|
|
@ -55,6 +55,7 @@ CREATE INDEX idx_organizations_slug ON public.organizations USING btree (slug);
|
||||||
|
|
||||||
CREATE TABLE public.system_automations (
|
CREATE TABLE public.system_automations (
|
||||||
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
id uuid DEFAULT gen_random_uuid() NOT NULL,
|
||||||
|
bot_id uuid NOT NULL,
|
||||||
kind int4 NOT NULL,
|
kind int4 NOT NULL,
|
||||||
"target" varchar(32) NULL,
|
"target" varchar(32) NULL,
|
||||||
schedule bpchar(12) NULL,
|
schedule bpchar(12) NULL,
|
||||||
|
|
|
||||||
|
|
@ -6,20 +6,5 @@
|
||||||
-- Add name column to system_automations if it doesn't exist
|
-- Add name column to system_automations if it doesn't exist
|
||||||
ALTER TABLE public.system_automations ADD COLUMN IF NOT EXISTS name VARCHAR(255);
|
ALTER TABLE public.system_automations ADD COLUMN IF NOT EXISTS name VARCHAR(255);
|
||||||
|
|
||||||
-- Insert update-summary automation (runs every minute)
|
|
||||||
-- kind = 3 (Scheduled trigger)
|
|
||||||
-- schedule format: minute hour day month weekday
|
|
||||||
-- "* * * * *" = every minute
|
|
||||||
INSERT INTO public.system_automations (name, kind, target, param, schedule, is_active)
|
|
||||||
VALUES (
|
|
||||||
'Update Summary',
|
|
||||||
0,
|
|
||||||
NULL,
|
|
||||||
'update-summary.bas',
|
|
||||||
'* * * * *',
|
|
||||||
true
|
|
||||||
)
|
|
||||||
ON CONFLICT DO NOTHING;
|
|
||||||
|
|
||||||
-- Create index on name column for faster lookups
|
-- Create index on name column for faster lookups
|
||||||
CREATE INDEX IF NOT EXISTS idx_system_automations_name ON public.system_automations(name);
|
CREATE INDEX IF NOT EXISTS idx_system_automations_name ON public.system_automations(name);
|
||||||
|
|
|
||||||
11
migrations/6.0.9.sql
Normal file
11
migrations/6.0.9.sql
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
-- Migration 6.0.9: Add bot_id column to system_automations
|
||||||
|
-- Description: Introduces a bot_id column to associate automations with a specific bot.
|
||||||
|
-- The column is added as UUID and indexed for efficient queries.
|
||||||
|
|
||||||
|
-- Add bot_id column if it does not exist
|
||||||
|
ALTER TABLE public.system_automations
|
||||||
|
ADD COLUMN IF NOT EXISTS bot_id UUID NOT NULL;
|
||||||
|
|
||||||
|
-- Create an index on bot_id for faster lookups
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_system_automations_bot_id
|
||||||
|
ON public.system_automations (bot_id);
|
||||||
|
|
@ -3,22 +3,23 @@ use log::info;
|
||||||
use rhai::Dynamic;
|
use rhai::Dynamic;
|
||||||
use rhai::Engine;
|
use rhai::Engine;
|
||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::shared::models::TriggerKind;
|
use crate::shared::models::TriggerKind;
|
||||||
use crate::shared::models::UserSession;
|
use crate::shared::models::UserSession;
|
||||||
use crate::shared::state::AppState;
|
use crate::shared::state::AppState;
|
||||||
|
|
||||||
pub fn set_schedule_keyword(state: &AppState, _user: UserSession, engine: &mut Engine) {
|
pub fn set_schedule_keyword(state: &AppState, user: UserSession, engine: &mut Engine) {
|
||||||
let state_clone = state.clone();
|
let state_clone = state.clone();
|
||||||
|
|
||||||
engine
|
engine
|
||||||
.register_custom_syntax(&["SET_SCHEDULE", "$string$"], true, {
|
.register_custom_syntax(&["SET_SCHEDULE", "$string$", "$string$"], true, {
|
||||||
move |context, inputs| {
|
move |context, inputs| {
|
||||||
let cron = context.eval_expression_tree(&inputs[0])?.to_string();
|
let cron = context.eval_expression_tree(&inputs[0])?.to_string();
|
||||||
let param = format!("cron_{}.rhai", cron.replace(' ', "_"));
|
let script_name = context.eval_expression_tree(&inputs[1])?.to_string();
|
||||||
|
|
||||||
let mut conn = state_clone.conn.lock().unwrap();
|
let mut conn = state_clone.conn.lock().unwrap();
|
||||||
let result = execute_set_schedule(&mut *conn, &cron, ¶m)
|
let result = execute_set_schedule(&mut *conn, &cron, &script_name, user.bot_id)
|
||||||
.map_err(|e| format!("DB error: {}", e))?;
|
.map_err(|e| format!("DB error: {}", e))?;
|
||||||
|
|
||||||
if let Some(rows_affected) = result.get("rows_affected") {
|
if let Some(rows_affected) = result.get("rows_affected") {
|
||||||
|
|
@ -34,29 +35,40 @@ pub fn set_schedule_keyword(state: &AppState, _user: UserSession, engine: &mut E
|
||||||
pub fn execute_set_schedule(
|
pub fn execute_set_schedule(
|
||||||
conn: &mut diesel::PgConnection,
|
conn: &mut diesel::PgConnection,
|
||||||
cron: &str,
|
cron: &str,
|
||||||
param: &str,
|
script_name: &str,
|
||||||
|
bot_uuid: Uuid,
|
||||||
) -> Result<Value, Box<dyn std::error::Error>> {
|
) -> Result<Value, Box<dyn std::error::Error>> {
|
||||||
info!(
|
info!(
|
||||||
"Starting execute_set_schedule with cron: {}, param: {}",
|
"Starting execute_set_schedule with cron: {}, script: {}, bot_id: {:?}",
|
||||||
cron, param
|
cron, script_name, bot_uuid
|
||||||
);
|
);
|
||||||
|
|
||||||
use crate::shared::models::system_automations;
|
use crate::shared::models::system_automations::dsl::*;
|
||||||
|
|
||||||
let new_automation = (
|
let new_automation = (
|
||||||
system_automations::kind.eq(TriggerKind::Scheduled as i32),
|
bot_id.eq(bot_uuid),
|
||||||
system_automations::schedule.eq(cron),
|
kind.eq(TriggerKind::Scheduled as i32),
|
||||||
system_automations::param.eq(param),
|
schedule.eq(cron),
|
||||||
|
param.eq(script_name),
|
||||||
|
is_active.eq(true),
|
||||||
);
|
);
|
||||||
|
|
||||||
let result = diesel::insert_into(system_automations::table)
|
let result = diesel::insert_into(system_automations)
|
||||||
.values(&new_automation)
|
.values(&new_automation)
|
||||||
|
.on_conflict((bot_id, param))
|
||||||
|
.do_update()
|
||||||
|
.set((
|
||||||
|
schedule.eq(cron),
|
||||||
|
is_active.eq(true),
|
||||||
|
last_triggered.eq(None::<chrono::DateTime<chrono::Utc>>),
|
||||||
|
))
|
||||||
.execute(&mut *conn)?;
|
.execute(&mut *conn)?;
|
||||||
|
|
||||||
Ok(json!({
|
Ok(json!({
|
||||||
"command": "set_schedule",
|
"command": "set_schedule",
|
||||||
"schedule": cron,
|
"schedule": cron,
|
||||||
"param": param,
|
"script": script_name,
|
||||||
|
"bot_id": bot_uuid.to_string(),
|
||||||
"rows_affected": result
|
"rows_affected": result
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,7 @@ impl TriggerKind {
|
||||||
#[diesel(table_name = system_automations)]
|
#[diesel(table_name = system_automations)]
|
||||||
pub struct Automation {
|
pub struct Automation {
|
||||||
pub id: Uuid,
|
pub id: Uuid,
|
||||||
|
pub bot_id: Uuid,
|
||||||
pub kind: i32,
|
pub kind: i32,
|
||||||
pub target: Option<String>,
|
pub target: Option<String>,
|
||||||
pub schedule: Option<String>,
|
pub schedule: Option<String>,
|
||||||
|
|
@ -265,6 +266,7 @@ pub mod schema {
|
||||||
diesel::table! {
|
diesel::table! {
|
||||||
system_automations (id) {
|
system_automations (id) {
|
||||||
id -> Uuid,
|
id -> Uuid,
|
||||||
|
bot_id -> Uuid,
|
||||||
kind -> Int4,
|
kind -> Int4,
|
||||||
target -> Nullable<Text>,
|
target -> Nullable<Text>,
|
||||||
schedule -> Nullable<Text>,
|
schedule -> Nullable<Text>,
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
SET_SCHEDULE "* * * * *"
|
||||||
|
|
||||||
|
|
||||||
let text = GET "announcements.gbkb/news/news.pdf"
|
let text = GET "announcements.gbkb/news/news.pdf"
|
||||||
let resume = LLM "Resume this document, in a table (DO NOT THINK) no_think: " + text
|
let resume = LLM "Resume this document, in a table (DO NOT THINK) no_think: " + text
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue