Claude Agent Skill · by Waynesutton

Convex Cron Jobs

Install Convex Cron Jobs skill for Claude Code from waynesutton/convexskills.

convexcronschedulingbackground-jobsautomation
Install
Terminal · npx
$npx skills add https://github.com/waynesutton/convexskills --skill convex-cron-jobs
Works with Paperclip

How Convex Cron Jobs fits into a Paperclip company.

Convex Cron Jobs drops into any Paperclip agent that handles convex and cron work. Assign it to a specialist inside a pre-configured PaperclipOrg company and the skill becomes available on every heartbeat — no prompt engineering, no tool wiring.

S
SaaS FactoryPaired

Pre-configured AI company — 18 agents, 18 skills, one-time purchase.

$27$59
Explore pack
Source file
SKILL.md604 lines
Expand
---name: convex-cron-jobsdisplayName: Convex Cron Jobsdescription: Scheduled function patterns for background tasks including interval scheduling, cron expressions, job monitoring, retry strategies, and best practices for long-running tasksversion: 1.0.0author: Convextags: [convex, cron, scheduling, background-jobs, automation]--- # Convex Cron Jobs Schedule recurring functions for background tasks, cleanup jobs, data syncing, and automated workflows in Convex applications. ## Documentation Sources Before implementing, do not assume; fetch the latest documentation: - Primary: https://docs.convex.dev/scheduling/cron-jobs- Scheduling Overview: https://docs.convex.dev/scheduling- Scheduled Functions: https://docs.convex.dev/scheduling/scheduled-functions- For broader context: https://docs.convex.dev/llms.txt ## Instructions ### Cron Jobs Overview Convex cron jobs allow you to schedule functions to run at regular intervals or specific times. Key features: - Run functions on a fixed schedule- Support for interval-based and cron expression scheduling- Automatic retries on failure- Monitoring via the Convex dashboard ### Basic Cron Setup ```typescript// convex/crons.tsimport { cronJobs } from "convex/server";import { internal } from "./_generated/api"; const crons = cronJobs(); // Run every hourcrons.interval(  "cleanup expired sessions",  { hours: 1 },  internal.tasks.cleanupExpiredSessions,  {}); // Run every day at midnight UTCcrons.cron(  "daily report",  "0 0 * * *",  internal.reports.generateDailyReport,  {}); export default crons;``` ### Interval-Based Scheduling Use `crons.interval` for simple recurring tasks: ```typescript// convex/crons.tsimport { cronJobs } from "convex/server";import { internal } from "./_generated/api"; const crons = cronJobs(); // Every 5 minutescrons.interval(  "sync external data",  { minutes: 5 },  internal.sync.fetchExternalData,  {}); // Every 2 hourscrons.interval(  "cleanup temp files",  { hours: 2 },  internal.files.cleanupTempFiles,  {}); // Every 30 seconds (minimum interval)crons.interval(  "health check",  { seconds: 30 },  internal.monitoring.healthCheck,  {}); export default crons;``` ### Cron Expression Scheduling Use `crons.cron` for precise scheduling with cron expressions: ```typescript// convex/crons.tsimport { cronJobs } from "convex/server";import { internal } from "./_generated/api"; const crons = cronJobs(); // Every day at 9 AM UTCcrons.cron(  "morning notifications",  "0 9 * * *",  internal.notifications.sendMorningDigest,  {}); // Every Monday at 8 AM UTCcrons.cron(  "weekly summary",  "0 8 * * 1",  internal.reports.generateWeeklySummary,  {}); // First day of every month at midnightcrons.cron(  "monthly billing",  "0 0 1 * *",  internal.billing.processMonthlyBilling,  {}); // Every 15 minutescrons.cron(  "frequent sync",  "*/15 * * * *",  internal.sync.syncData,  {}); export default crons;``` ### Cron Expression Reference ```┌───────────── minute (0-59)│ ┌───────────── hour (0-23)│ │ ┌───────────── day of month (1-31)│ │ │ ┌───────────── month (1-12)│ │ │ │ ┌───────────── day of week (0-6, Sunday=0)│ │ │ │ │* * * * *``` Common patterns:- `* * * * *` - Every minute- `0 * * * *` - Every hour- `0 0 * * *` - Every day at midnight- `0 0 * * 0` - Every Sunday at midnight- `0 0 1 * *` - First day of every month- `*/5 * * * *` - Every 5 minutes- `0 9-17 * * 1-5` - Every hour from 9 AM to 5 PM, Monday through Friday ### Internal Functions for Crons Cron jobs should call internal functions for security: ```typescript// convex/tasks.tsimport { internalMutation, internalQuery } from "./_generated/server";import { v } from "convex/values"; // Cleanup expired sessionsexport const cleanupExpiredSessions = internalMutation({  args: {},  returns: v.number(),  handler: async (ctx) => {    const oneHourAgo = Date.now() - 60 * 60 * 1000;        const expiredSessions = await ctx.db      .query("sessions")      .withIndex("by_lastActive")      .filter((q) => q.lt(q.field("lastActive"), oneHourAgo))      .collect();     for (const session of expiredSessions) {      await ctx.db.delete(session._id);    }     return expiredSessions.length;  },}); // Process pending tasksexport const processPendingTasks = internalMutation({  args: {},  returns: v.null(),  handler: async (ctx) => {    const pendingTasks = await ctx.db      .query("tasks")      .withIndex("by_status", (q) => q.eq("status", "pending"))      .take(100);     for (const task of pendingTasks) {      await ctx.db.patch(task._id, {        status: "processing",        startedAt: Date.now(),      });            // Schedule the actual processing      await ctx.scheduler.runAfter(0, internal.tasks.processTask, {        taskId: task._id,      });    }     return null;  },});``` ### Cron Jobs with Arguments Pass static arguments to cron jobs: ```typescript// convex/crons.tsimport { cronJobs } from "convex/server";import { internal } from "./_generated/api"; const crons = cronJobs(); // Different cleanup intervals for different typescrons.interval(  "cleanup temp files",  { hours: 1 },  internal.cleanup.cleanupByType,  { fileType: "temp", maxAge: 3600000 }); crons.interval(  "cleanup cache files",  { hours: 24 },  internal.cleanup.cleanupByType,  { fileType: "cache", maxAge: 86400000 }); export default crons;``` ```typescript// convex/cleanup.tsimport { internalMutation } from "./_generated/server";import { v } from "convex/values"; export const cleanupByType = internalMutation({  args: {    fileType: v.string(),    maxAge: v.number(),  },  returns: v.number(),  handler: async (ctx, args) => {    const cutoff = Date.now() - args.maxAge;        const oldFiles = await ctx.db      .query("files")      .withIndex("by_type_and_created", (q) =>         q.eq("type", args.fileType).lt("createdAt", cutoff)      )