Skip to main content

convex-cron-jobs

Scheduled function patterns for background tasks including interval scheduling, cron expressions, job monitoring, retry strategies, and best practices for long-running tasks

설치로 이동

소스 정보

저장소
waynesutton/convexskills
최근 소스 활동
2026년 2월 3일 04:58
감지된 SKILL.md 언어
영어
스타
404
포크
32

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

파일 탐색기
4 개 파일

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
convex-cron-jobs
displayName
Convex Cron Jobs
description
Scheduled function patterns for background tasks including interval scheduling, cron expressions, job monitoring, retry strategies, and best practices for long-running tasks
version
1.0.0
author
Convex
tags
["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.ts import { cronJobs } from "convex/server"; import { internal } from "./_generated/api"; const crons = cronJobs(); // Run every hour crons.interval( "cleanup expired sessions", { hours: 1 }, internal.tasks.cleanupExpiredSessions, {} ); // Run every day at midnight UTC crons.cron( "daily report", "0 0 * * *", internal.reports.generateDailyReport, {} ); export default crons; ``` ### Interval-Based Scheduling Use `crons.interval` for simple recurring tasks: ```typescript // convex/crons.ts import { cronJobs } from "convex/server"; import { internal } from "./_generated/api"; const crons = cronJobs(); // Every 5 minutes crons.interval( "sync external data", { minutes: 5 }, internal.sync.fetchExternalData, {} ); // Every 2 hours crons.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.ts import { cronJobs } from "convex/server"; import { internal } from "./_generated/api"; const crons = cronJobs(); // Every day at 9 AM UTC crons.cron( "morning notifications", "0 9 * * *", internal.notifications.sendMorningDigest, {} ); // Every Monday at 8 AM UTC crons.cron( "weekly summary", "0 8 * * 1", internal.reports.generateWeeklySummary, {} ); // First day of every month at midnight crons.cron( "monthly billing", "0 0 1 * *", internal.billing.processMonthlyBilling, {} ); // Every 15 minutes crons.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.ts import { internalMutation, internalQuery } from "./_generated/server"; import { v } from "convex/values"; // Cleanup expired sessions export 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 tasks export 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.ts import { cronJobs } from "convex/server"; import { internal } from "./_generated/api"; const crons = cronJobs(); // Different cleanup intervals for different types crons.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.ts import { 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) ) .collect(); for (const file of oldFiles) { await ctx.storage.delete(file.storageId); await ctx.db.delete(file._id); } return oldFiles.length; }, }); ``` ### Monitoring and Logging Add logging to track cron job execution: ```typescript // convex/tasks.ts import { internalMutation } from "./_generated/server"; import { v } from "convex/values"; export const cleanupWithLogging = internalMutation({ args: {}, returns: v.null(), handler: async (ctx) => { const startTime = Date.now(); let processedCount = 0; let errorCount = 0; try { const expiredItems = await ctx.db .query("items") .withIndex("by_expiresAt") .filter((q) => q.lt(q.field("expiresAt"), Date.now())) .collect(); for (const item of expiredItems) { try { await ctx.db.delete(item._id); processedCount++; } catch (error) { errorCount++; console.error(`Failed to delete item ${item._id}:`, error); } } // Log job completion await ctx.db.insert("cronLogs", { jobName: "cleanup", startTime, endTime: Date.now(), duration: Date.now() - startTime, processedCount, errorCount, status: errorCount === 0 ? "success" : "partial", }); } catch (error) { // Log job failure await ctx.db.insert("cronLogs", { jobName: "cleanup", startTime, endTime: Date.now(), duration: Date.now() - startTime, processedCount, errorCount, status: "failed", error: String(error), }); throw error; } return null; }, }); ``` ### Batching for Large Datasets Handle large datasets in batches to avoid timeouts: ```typescript // convex/tasks.ts import { internalMutation } from "./_generated/server"; import { internal } from "./_generated/api"; import { v } from "convex/values"; const BATCH_SIZE = 100; export const processBatch = internalMutation({ args: { cursor: v.optional(v.string()), }, returns: v.null(), handler: async (ctx, args) => { const result = await ctx.db .query("items") .withIndex("by_status", (q) => q.eq("status", "pending")) .paginate({ numItems: BATCH_SIZE, cursor: args.cursor ?? null }); for (const item of result.page) { await ctx.db.patch(item._id, { status: "processed", processedAt: Date.now(), }); } // Schedule next batch if there are more items if (!result.isDone) { await ctx.scheduler.runAfter(0, internal.tasks.processBatch, { cursor: result.continueCursor, }); } return null; }, }); ``` ### External API Calls in Crons Use actions for external API calls: ```typescript // convex/sync.ts "use node"; import { internalAction } from "./_generated/server"; import { internal } from "./_generated/api"; import { v } from "convex/values"; export const syncExternalData = internalAction({ args: {}, returns: v.null(), handler: async (ctx) => { // Fetch from external API const response = await fetch("https://api.example.com/data", { headers: { Authorization: `Bearer ${process.env.API_KEY}`, }, }); if (!response.ok) { throw new Error(`API request failed: ${response.status}`); } const data = await response.json(); // Store the data using a mutation await ctx.runMutation(internal.sync.storeExternalData, { data, syncedAt: Date.now(), }); return null; }, }); export const storeExternalData = internalMutation({ args: { data: v.any(), syncedAt: v.number(), }, returns: v.null(), handler: async (ctx, args) => { await ctx.db.insert("externalData", { data: args.data, syncedAt: args.syncedAt, }); return null; }, }); ``` ```typescript // convex/crons.ts import { cronJobs } from "convex/server"; import { internal } from "./_generated/api"; const crons = cronJobs(); crons.interval( "sync external data", { minutes: 15 }, internal.sync.syncExternalData, {} ); export default crons; ``` ## Examples ### Schema for Cron Job Logging ```typescript // convex/schema.ts import { defineSchema, defineTable } from "convex/server"; import { v } from "convex/values"; export default defineSchema({ cronLogs: defineTable({ jobName: v.string(), startTime: v.number(), endTime: v.number(), duration: v.number(), processedCount: v.number(), errorCount: v.number(), status: v.union( v.literal("success"), v.literal("partial"), v.literal("failed") ),
GitHub에서 보기
이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기