Home

Deno Task Scheduler: Simple Time-Based Cron Implementation

78 views

Implementing a simple task scheduling service in Deno can be done using its time-based APIs, such as setTimeout and setInterval, as well as some basic logic to parse cron-like strings. Below is an example of how you can set this up.

Step-by-Step Implementation

  1. Setting up a Deno Project

    First, ensure you have Deno installed on your system. You can check this by running:

    deno --version
    
  2. Create a Scheduler Module

    Create a file named scheduler.ts for our scheduler logic.

    // scheduler.ts
    
    interface Task {
      id: string;
      execute: () => void;
    }
    
    class Scheduler {
      private tasks: Map<string, number> = new Map();
    
      scheduleOnce(task: Task, delayMs: number) {
        const timeoutId = setTimeout(() => {
          task.execute();
          this.tasks.delete(task.id);
        }, delayMs);
        this.tasks.set(task.id, timeoutId);
      }
    
      scheduleRecurring(task: Task, intervalMs: number) {
        const intervalId = setInterval(() => {
          task.execute();
        }, intervalMs);
        this.tasks.set(task.id, intervalId);
      }
    
      cancelTask(taskId: string) {
        const id = this.tasks.get(taskId);
        if (id !== undefined) {
          clearInterval(id);
          clearTimeout(id);
          this.tasks.delete(taskId);
        }
      }
    }
    
    export { Scheduler, Task };
    
  3. Adding a Cron-like Functionality

    We will create a simple parser for cron-like expressions. For simplicity, we'll handle basic minute and hour components.

    // cronParser.ts
    
    function parseCron(cron: string): [number, number] {
      const [minute, hour] = cron.split(' ').map(Number);
      if (
        isNaN(minute) || minute < 0 || minute > 59 ||
        isNaN(hour) || hour < 0 || hour > 23
      ) {
        throw new Error('Invalid cron format');
      }
      return [minute, hour];
    }
    
    export function cronToDelay(cron: string): number {
      const [targetMinute, targetHour] = parseCron(cron);
    
      const now = new Date();
      now.setSeconds(0, 0); // Ignore seconds and milliseconds
    
      const target = new Date();
      target.setHours(targetHour, targetMinute, 0, 0);
    
      if (target <= now) {
        target.setDate(target.getDate() + 1);
      }
    
      return target.getTime() - now.getTime();
    }
    
  4. Usage Example

    Now create a main.ts to demonstrate the scheduler.

    // main.ts
    import { Scheduler, Task } from './scheduler.ts';
    import { cronToDelay } from './cronParser.ts';
    
    const scheduler = new Scheduler();
    
    // Define a task
    const logTimeTask: Task = {
      id: 'logTime',
      execute: () => {
        console.log('Current time:', new Date().toLocaleTimeString());
      },
    };
    
    // Schedule a task to run in 10 seconds
    scheduler.scheduleOnce(logTimeTask, 10000);
    
    // Schedule a cron-like task to run every day at a specific time, e.g., 14:30
    const cronExpression = '30 14';
    const delay = cronToDelay(cronExpression);
    
    // For demo purposes, run once
    scheduler.scheduleOnce(logTimeTask, delay);
    
    // For recurring job (every day this would need to be set on a daily interval after first execution)
    setTimeout(() => {
      scheduler.scheduleRecurring(logTimeTask, 24 * 60 * 60 * 1000);
    }, delay);
    
  5. Run the Project

    Use Deno to run the project:

    deno run --allow-net --allow-read main.ts
    

Explanation

  • Scheduler Class: Manages scheduling and cancelling of tasks using Deno’s timing functions (setTimeout, setInterval).
  • Cron Parser: Converts simple cron-like time expressions into millisecond delays.
  • Task Execution: Demonstrates scheduling immediate, one-time, and daily recurring tasks.

This example provides a basic framework. For more complex cron parsing, consider using external libraries or further expanding the parsing logic.