StepwiseRPA: Schedule Processing and Bot Run Creation
1. Overview
This document details the process of Bot Run Creation in the StepwiseRPA application, based on existing schedules.
The provided code does not cover the creation of the schedule records themselves (e.g., via a UI or admin panel). Instead, it describes a backend process responsible for:
- Triggering the processing of schedules via an API endpoint.
- Fetching active schedules from the database.
- Calculating upcoming run times based on recurrence rules.
- Creating (inserting) the individual
bot_runrecords into the database.
This process is what "materializes" a Schedule (a definition) into BotRun instances (concrete jobs to be executed).
Core Components & Libraries
- Next.js API Route (
/api/bot-runs): The main entrypoint for the process, likely triggered by an external scheduler (e.g., a cron job). - Supabase: The database provider. The code interacts with it via RPC calls (
get_schedules_for_bot_runs) and standard table operations (insert,delete). rrule.js: A library used to parse and compute recurrence rules from iCalendar RRULE strings (stored inschedule.schedule_data).luxon: A library for all date, time, and timezone management. This is critical for handling schedules across different timezones.
2. Process Flow: From Trigger to Run Creation
The process begins when a request is made to the API endpoint and flows through the server-side action functions.
Step 1: API Endpoint Trigger
The entire process is initiated by a GET request to the /api/bot-runs endpoint.
File: app/api/bot-runs/route.ts
- Authentication: The endpoint is designed to be protected by an API key (
x-api-key).Note: The API key check is currently bypassed in the provided code (
if (1 === 1)). In a production environment, this would beif (!apiKey || apiKey !== expectedApiKey). - Fetch Schedules: It calls the Supabase RPC
get_schedules_for_bot_runs. This function (whose definition is not in the files) is assumed to return a list of all active schedules that are due for processing. - Iterate and Delegate: The code loops through each
schedulereturned from the RPC.- If
schedule.is_recurringistrue, it callscreateRecurringBotRunsForSchedule(schedule). - The logic for non-recurring schedules (
createOneTimeBotRunForSchedule) is currently commented out in this file.
- If
Step 2: Processing Recurring Schedules
This is the core logic for generating bot_run instances from a recurring schedule.
File: app/actions/bot-runs/bot-run-actions.ts
Function: createRecurringBotRunsForSchedule(scheduleForBotRun)
-
Guard Clauses: The function first checks if the schedule is valid and active. It will exit immediately if:
scheduleForBotRunis null.scheduleForBotRun.is_activeisfalse.scheduleForBotRun.is_recurringisfalse.
-
Define Time Window: It calculates a "look-ahead" window to generate runs for.
nowPlus4: The current time.tomorrow: The start of the day, two days from now (nowPlus4.plus({ days: 2 }).startOf('day')).- Result: The window effectively covers "today" and "tomorrow", ensuring runs are created in advance.
-
Idempotency (Delete Future Runs): To prevent duplicate
bot_runrecords if this script runs multiple times, it first deletes any existingbot_runsfor this schedule within the calculated window.await supabase.from('bot_runs').delete() .eq('schedule_id', scheduleForBotRun.id) .gte('date_scheduled', nowPlus4.toISO()!); -
Parse Recurrence Rule: It parses the
schedule.schedule_datastring (e.g.,FREQ=DAILY;BYHOUR=10;BYMINUTE=0) into anRRuleobject.const rrule = RRule.fromString(scheduleForBotRun.schedule_data); -
Get Base Events: It uses the
rruleobject to find all "base" run times within the calculated time window.const events = rrule.between(nowPlus4.toJSDate(), tomorrow.toJSDate(), true);Example: If the rule is "every day at 10:00 AM,"
eventswill contain aDateobject for 10:00 AM today and 10:00 AM tomorrow (if they fall within the window). -
Create Runs (Outer Loop): The code iterates through each
eventfound. -
Handle Intra-Day Repetition (Inner Loop): A schedule can have a base event (e.g., "run at 9:00 AM") and also a "repeat" setting (e.g., "repeat every 15 minutes for 2 hours"). This is handled by an inner
whileloop.startTimeForIteration: Initialized to theeventtime, respecting the schedule'stimezone.endTime: Calculated by addingschedule.repeat_hoursto thestartTimeForIteration.- The
while (startTimeForIteration <= endTime)loop continues to generate runs.
-
Insert Bot Run: Inside the inner loop, a
botRunobject is constructed.status: Set to'scheduled'.date_scheduled: Set to thestartTimeForIteration.date_expire: Calculated by addingschedule.runs_expire_value(in minutes) to thestartTimeForIteration.- This object is then inserted into the
bot_runstable.
-
Increment for Next Repetition: If
schedule.repeat_minutesis set, it is added to thestartTimeForIteration, and the innerwhileloop runs again. Ifrepeat_minutesis not set, the loopbreaks, and the code moves to the next baseevent.
3. Other Key Functions
The provided files contain other functions related to bot runs.
createBotRunForSingleRunSchedule
This function is similar to createRecurringBotRunsForSchedule but is much simpler.
- It's designed for schedules where
is_recurringisfalse. - It deletes all existing runs for that
schedule_id. - It creates exactly one
bot_runrecord based on theschedule.start_datetimez. - Note: This function is not currently called by the
/api/bot-runsroute.
expandAndUpsertRuns
This function is present but not called by the API route. It represents an alternative (and likely more robust) strategy for creating runs.
- It also calculates a window (
windowStart,windowEnd). - It also gets base events from the
RRule. - Key Difference: Instead of deleting and re-inserting runs in the application code, it passes the list of calculated event times (
p_base_events) to a Supabase RPC namedschedule_expand_and_upsert. - This database function is likely responsible for handling the "upsert" logic, (e.g., "insert this run if it doesn't exist"), which can be more efficient and safer from race conditions than the "delete-then-insert" pattern.
Data-Fetching and Ad-Hoc Creation
getBotRunsForBot/getBotRunsForMultipleBots: These are standard data-fetching functions used by the application frontend to display lists and details of past and scheduled bot runs, with support for filtering and pagination.createSingleBotRun: This function is used to create a single, ad-hoc bot run that is not associated with a schedule (schedule_id: null). This is likely used for a "Run Now" button in the UI.