Skip to content

Worker - actionsToRun[] - determine actions needing run#4

Open
sweetmantech wants to merge 1 commit intomainfrom
sweetmantech/myc-2267-worker-actionstorun-determine-actions-needing-run
Open

Worker - actionsToRun[] - determine actions needing run#4
sweetmantech wants to merge 1 commit intomainfrom
sweetmantech/myc-2267-worker-actionstorun-determine-actions-needing-run

Conversation

@sweetmantech
Copy link
Copy Markdown
Collaborator

@sweetmantech sweetmantech commented Jun 17, 2025

Summary by CodeRabbit

  • Refactor

    • Improved scheduling logic for running actions, resulting in more accurate and reliable execution of scheduled tasks.
  • Chores

    • Added a new dependency to enhance cron expression parsing capabilities.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Jun 17, 2025

Walkthrough

The scheduling logic in CronController.ts was refactored by introducing a helper function to determine if a scheduled action should run, based on various conditions and improved cron schedule parsing. Additionally, the cron-parser package was added to package.json to support enhanced cron expression handling.

Changes

File(s) Change Summary
controllers/CronController.ts Refactored scheduling logic; added shouldRunAction helper for action run determination using cron parsing.
package.json Added cron-parser dependency for improved cron expression parsing.

Poem

A hop, a skip, a scheduled run,
With cron-parser, the work is fun!
Actions filtered, logs anew,
Rabbits keep the timing true.
Refactored code, dependencies grow—
On schedule now, we always go!
🐇⏰

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
package.json (1)

17-18: Consider redundancy between node-cron and cron-parser.

Unless another module still depends on node-cron, the new logic only relies on cron-parser. Maintaining two cron libraries increases bundle size and cognitive load.
Audit the codebase and keep only the one actually used.

controllers/CronController.ts (2)

7-15: Duplicate “enabled” check is unnecessary noise.

getScheduledActions() already filters enabled = true.
Removing the extra guard simplifies the helper and reduces branching:

-function shouldRunAction(action: ScheduledAction, now: Date): boolean {
-  if (!action.enabled) return false;
+function shouldRunAction(action: ScheduledAction, now: Date): boolean {

48-53: High-volume optimisation: avoid parsing identical schedules repeatedly.

If many actions share the same cron string, cron-parser is invoked N times per tick.
Cache parseExpression results keyed by schedule during a single run:

const cache = new Map<string, parser.CronExpression>();
function getCron(schedule: string) {
  if (!cache.has(schedule)) cache.set(schedule, parser.parseExpression(schedule));
  return cache.get(schedule)!;
}

Small change, significant CPU savings at scale.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c6d3689 and a3bfcb8.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (2)
  • controllers/CronController.ts (1 hunks)
  • package.json (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
controllers/CronController.ts (1)
lib/supabase/scheduled_actions/getScheduledActions.ts (2)
  • ScheduledAction (4-5)
  • getScheduledActions (10-21)
🔇 Additional comments (1)
package.json (1)

17-18: Add typings or verify bundled types for cron-parser.

cron-parser ships with TypeScript typings only on versions ≥ 4.10.0. You added ^4.9.0, which still requires the separate @types/cron-parser package.
Without them, parser will be typed as any, losing compile-time checks in CronController.ts.

-    "cron-parser": "^4.9.0"
+    "cron-parser": "^4.10.1",          // bundled types
+    "@types/cron-parser": "^4.6.3"     // remove when upgrading ≥4.10

Choose either upgrade to ≥ 4.10 or add the @types dev-dependency.

Comment on lines +11 to +24
// If never run, and next_run is now or earlier, run it
if (!action.last_run) {
if (!action.next_run) return true; // If next_run and last_run are null, run it
return new Date(action.next_run) <= now;
}

// If next_run is now or earlier, and last_run is before next_run, run it
if (action.next_run && new Date(action.next_run) <= now) {
if (
!action.last_run ||
new Date(action.last_run) < new Date(action.next_run)
) {
return true;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Repeated Date construction is wasteful & can cause subtle TZ mis-parsing.

new Date(action.next_run) is invoked multiple times and assumes the DB string includes a timezone.
If Supabase returns "2025-06-21 12:00:00" (no TZ), Node treats it as local time, whereas cron-parser defaults to system TZ, leading to silent drift on servers not in UTC.

-  if (!action.last_run) {
-    if (!action.next_run) return true; // If next_run and last_run are null, run it
-    return new Date(action.next_run) <= now;
+  if (!action.last_run) {
+    if (!action.next_run) return true;
+    const nextRun = new Date(`${action.next_run}Z`); // force UTC
+    return nextRun <= now;
   }

Cache the parsed dates once per action (const nextRun = …; const lastRun = …) to avoid repeated parsing and make the TZ handling explicit.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// If never run, and next_run is now or earlier, run it
if (!action.last_run) {
if (!action.next_run) return true; // If next_run and last_run are null, run it
return new Date(action.next_run) <= now;
}
// If next_run is now or earlier, and last_run is before next_run, run it
if (action.next_run && new Date(action.next_run) <= now) {
if (
!action.last_run ||
new Date(action.last_run) < new Date(action.next_run)
) {
return true;
}
// If never run, and next_run is now or earlier, run it
if (!action.last_run) {
if (!action.next_run) return true;
const nextRun = new Date(`${action.next_run}Z`); // force UTC
return nextRun <= now;
}
// If next_run is now or earlier, and last_run is before next_run, run it
if (action.next_run && new Date(action.next_run) <= now) {
if (
!action.last_run ||
new Date(action.last_run) < new Date(action.next_run)
) {
return true;
}
🤖 Prompt for AI Agents
In controllers/CronController.ts around lines 11 to 24, multiple calls to new
Date() on action.next_run and action.last_run cause repeated parsing and
potential timezone inconsistencies. Fix this by parsing action.next_run and
action.last_run once each into constants (e.g., nextRun and lastRun) at the
start of the function or block, then use these constants throughout the logic to
avoid repeated Date construction and clarify timezone handling.

Comment on lines +27 to +36
// Fallback: use cron-parser to check if a run is due
try {
const interval = parser.parseExpression(action.schedule, {
currentDate: now,
});
const prev = interval.prev().toDate();
// If last_run is before the previous scheduled time, it's due
if (!action.last_run || new Date(action.last_run) < prev) {
return true;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

prev() + strict < risks skipping on-time executions.

cron-parser’s prev() returns the previous schedule excluding the currentDate by default.
Scenario: schedule * * * * * (every minute); now is exactly on the minute and last_run is 59 s ago.
prev() yields the previous minute, so last_run < prev is false, and the job is skipped even though it should run.

Either use interval.prev(true) (inclusive) or compare against interval.next():

-const prev = interval.prev().toDate();
-if (!action.last_run || new Date(action.last_run) < prev) {
+const next = interval.next().toDate();
+if (!action.last_run || new Date(action.last_run) < next) {
   return true;
 }

This guarantees an execution whenever now aligns with the cron expression.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Fallback: use cron-parser to check if a run is due
try {
const interval = parser.parseExpression(action.schedule, {
currentDate: now,
});
const prev = interval.prev().toDate();
// If last_run is before the previous scheduled time, it's due
if (!action.last_run || new Date(action.last_run) < prev) {
return true;
}
// Fallback: use cron-parser to check if a run is due
try {
const interval = parser.parseExpression(action.schedule, {
currentDate: now,
});
const next = interval.next().toDate();
// If last_run is before the next scheduled time, it's due
if (!action.last_run || new Date(action.last_run) < next) {
return true;
}
🤖 Prompt for AI Agents
In controllers/CronController.ts around lines 27 to 36, the use of
interval.prev() with a strict less-than comparison risks skipping executions
that are exactly on schedule. To fix this, change the call to
interval.prev(true) to make it inclusive, or alternatively compare last_run
against interval.next() instead. This ensures that jobs scheduled exactly at the
current time are not skipped.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant