feat(schedule): optimize set_schedule with update-first approach

Changed the set_schedule function to first attempt updating existing records before inserting new ones. This improves efficiency by avoiding unnecessary insert conflicts and subsequent updates. The logic now:
1. Tries to update matching existing schedule first
2. Only performs insert if no matching record was found
3. Maintains same functionality but with better performance
This commit is contained in:
Rodrigo Rodriguez (Pragmatismo) 2025-11-05 09:05:25 -03:00
parent 02c36a8888
commit 72f7081acb
3 changed files with 43 additions and 4 deletions

10
migrations/6.0.6.sql Normal file
View file

@ -0,0 +1,10 @@
-- Migration 6.0.6: Add unique constraint for system_automations
-- Fixes error: "there is no unique or exclusion constraint matching the ON CONFLICT specification"
ALTER TABLE public.system_automations
ADD CONSTRAINT system_automations_bot_kind_param_unique
UNIQUE (bot_id, kind, param);
-- Add index for the new constraint
CREATE INDEX IF NOT EXISTS idx_system_automations_bot_kind_param
ON public.system_automations (bot_id, kind, param);

19
migrations/6.0.7.sql Normal file
View file

@ -0,0 +1,19 @@
-- Migration 6.0.7: Fix clicks table primary key
-- Required by Diesel before we can run other migrations
-- Create new table with proper structure
CREATE TABLE IF NOT EXISTS public.new_clicks (
id SERIAL PRIMARY KEY,
campaign_id text NOT NULL,
email text NOT NULL,
updated_at timestamptz DEFAULT now() NULL,
CONSTRAINT new_clicks_campaign_id_email_key UNIQUE (campaign_id, email)
);
-- Copy data from old table
INSERT INTO public.new_clicks (campaign_id, email, updated_at)
SELECT campaign_id, email, updated_at FROM public.clicks;
-- Drop old table and rename new one
DROP TABLE public.clicks;
ALTER TABLE public.new_clicks RENAME TO clicks;

View file

@ -38,10 +38,11 @@ pub fn execute_set_schedule(
is_active.eq(true),
);
let result = diesel::insert_into(system_automations)
.values(&new_automation)
.on_conflict((bot_id, kind, param))
.do_update()
// First try to update existing record
let update_result = diesel::update(system_automations)
.filter(bot_id.eq(bot_uuid))
.filter(kind.eq(TriggerKind::Scheduled as i32))
.filter(param.eq(script_name))
.set((
schedule.eq(cron),
is_active.eq(true),
@ -49,6 +50,15 @@ pub fn execute_set_schedule(
))
.execute(&mut *conn)?;
// If no rows were updated, insert new record
let result = if update_result == 0 {
diesel::insert_into(system_automations)
.values(&new_automation)
.execute(&mut *conn)?
} else {
update_result
};
Ok(json!({
"command": "set_schedule",
"schedule": cron,