Hyrex supports scheduling tasks to run at regular intervals using cron expressions.

Basic Cron Task

Define a scheduled task using the cron configuration:
import { HyrexRegistry } from '@hyrex/hyrex';

const hy = new HyrexRegistry();

const dailyReport = hy.task({
    name: 'dailyReport',
    config: {
        cron: '0 9 * * *',  // Every day at 9 AM
        queue: 'scheduled',
        timeoutSeconds: 300
    },
    func: async () => {
        console.log('Generating daily report...');
        const report = await generateReport();
        await emailReport(report);
        return { sent: true };
    }
});

Cron Expression Format

Hyrex uses standard 5-field cron expressions:
┌───────────── minute (0 - 59)
│ ┌───────────── hour (0 - 23)
│ │ ┌───────────── day of the month (1 - 31)
│ │ │ ┌───────────── month (1 - 12)
│ │ │ │ ┌───────────── day of the week (0 - 7) (0 or 7 is Sun)
│ │ │ │ │
│ │ │ │ │
* * * * *

Common Patterns

// Every minute
config: { cron: '* * * * *' }

// Every hour at minute 0
config: { cron: '0 * * * *' }

// Every day at midnight
config: { cron: '0 0 * * *' }

// Every Monday at 9 AM
config: { cron: '0 9 * * 1' }

// Every 15 minutes
config: { cron: '*/15 * * * *' }

// Business hours (9 AM - 5 PM on weekdays)
config: { cron: '0 9-17 * * 1-5' }

// First day of every month at noon
config: { cron: '0 12 1 * *' }

Cron Validation

The TypeScript SDK validates cron expressions when tasks are registered:
// This will throw an error at registration time
const invalidCron = hy.task({
    name: 'invalidCron',
    config: {
        cron: 'invalid expression'  // Error: Cron expr 'invalid expression' is invalid.
    },
    func: async () => {
        return { done: true };
    }
});

Cron Task Examples

Heartbeat Monitor

const heartbeatTask = hy.task({
    name: 'heartbeat',
    config: {
        queue: 'monitoring',
        cron: '* * * * *',  // Every minute
        timeoutSeconds: 10,
    },
    func: async () => {
        console.log(`Heartbeat at ${new Date().toISOString()}`);
        
        // Check system health
        const health = await checkSystemHealth();
        
        if (!health.isHealthy) {
            await alertOps(health.issues);
        }
        
        return { status: 'healthy', timestamp: new Date() };
    }
});

Data Cleanup

const cleanupTask = hy.task({
    name: 'cleanup',
    config: {
        cron: '0 2 * * *',  // Every day at 2 AM
        queue: 'maintenance',
        maxRetries: 1
    },
    func: async () => {
        const cutoffDate = new Date();
        cutoffDate.setDate(cutoffDate.getDate() - 30);
        
        // Clean old data
        const deleted = await deleteOldRecords(cutoffDate);
        
        // Clean KV store
        const kvKeysDeleted = await cleanupKVStore(cutoffDate);
        
        return {
            recordsDeleted: deleted,
            kvKeysDeleted,
            ranAt: new Date()
        };
    }
});

Scheduled Reports

const weeklyReportTask = hy.task({
    name: 'weeklyReport',
    config: {
        cron: '0 9 * * 1',  // Every Monday at 9 AM
        queue: 'reports',
        timeoutSeconds: 600
    },
    func: async () => {
        const endDate = new Date();
        const startDate = new Date();
        startDate.setDate(startDate.getDate() - 7);
        
        const reportData = await gatherWeeklyMetrics(startDate, endDate);
        const report = await generateReport(reportData);
        
        await sendEmail({
            to: 'team@company.com',
            subject: `Weekly Report - ${endDate.toLocaleDateString()}`,
            body: report
        });
        
        return { sent: true, week: startDate };
    }
});

Data Sync

const syncTask = hy.task({
    name: 'dataSync',
    config: {
        cron: '*/30 * * * *',  // Every 30 minutes
        queue: 'sync',
        maxRetries: 2,
        idempotencyKey: 'sync-external-data'
    },
    func: async () => {
        const lastSync = await HyrexKV.get('last-sync-timestamp')
            .catch(() => '0');
        
        const newData = await fetchExternalData(parseInt(lastSync));
        
        if (newData.length > 0) {
            await processNewData(newData);
            await HyrexKV.set('last-sync-timestamp', Date.now().toString());
        }
        
        return {
            itemsSynced: newData.length,
            timestamp: new Date()
        };
    }
});

Cron with Other Features

Cron with Retries

const resilientCron = hy.task({
    name: 'resilientScheduled',
    config: {
        cron: '0 */4 * * *',  // Every 4 hours
        maxRetries: 5,         // Retry failed executions
        queue: 'critical'
    },
    func: async () => {
        // Critical scheduled operation with retries
        return await criticalOperation();
    }
});

Cron with Workflows

// Trigger a workflow on schedule
const scheduledWorkflowTrigger = hy.task({
    name: 'triggerWorkflow',
    config: {
        cron: '0 0 * * 0',  // Every Sunday at midnight
        queue: 'orchestration'
    },
    func: async () => {
        // Start weekly processing workflow
        const workflowRunId = await weeklyProcessingWorkflow.send({
            week: new Date().toISOString()
        });
        
        return { triggered: true, workflowRunId };
    }
});

Monitoring Cron Tasks

Track cron execution through Hyrex Studio:
  • View scheduled tasks and their cron expressions
  • Monitor execution history
  • Check for missed executions
  • Review task success/failure rates

Best Practices

  1. Use Descriptive Names
    // Good
    name: 'dailyUserDigest'
    name: 'hourlyMetricsCollection'
    
    // Avoid
    name: 'cron1'
    name: 'scheduled'
    
  2. Set Appropriate Timeouts
    config: {
        cron: '* * * * *',      // Runs frequently
        timeoutSeconds: 30      // Short timeout
    }
    
    config: {
        cron: '0 0 * * *',      // Daily task
        timeoutSeconds: 3600    // Longer timeout
    }
    
  3. Handle Overlapping Executions
    const exclusiveCron = hy.task({
        name: 'exclusiveCron',
        config: {
            cron: '*/5 * * * *',
            idempotencyKey: 'exclusive-cron'  // Prevents overlaps
        },
        func: async () => {
            // Long-running task that shouldn't overlap
            return await longOperation();
        }
    });
    
  4. Log Cron Executions
    const loggedCron = hy.task({
        name: 'loggedCron',
        config: { cron: '0 * * * *' },
        func: async () => {
            const startTime = Date.now();
            console.log(`Starting hourly task at ${new Date().toISOString()}`);
            
            try {
                const result = await hourlyProcess();
                console.log(`Completed in ${Date.now() - startTime}ms`);
                return result;
            } catch (error) {
                console.error('Hourly task failed:', error);
                throw error;
            }
        }
    });
    

Limitations

  • No seconds precision: Cron expressions use 5 fields (minute precision)
  • Fixed schedule: Cannot dynamically change cron expression after registration
  • No timezone support: Cron runs in server timezone
  • Platform mode: Cron scheduler doesn’t run when using HYREX_API_KEY (platform handles scheduling)

Next Steps