UNPKG

perplexity-mcp-server

Version:

A Perplexity API Model Context Protocol (MCP) server that unlocks Perplexity's search-augmented AI capabilities for LLM agents. Features robust error handling, secure input validation, and transparent reasoning with the showThinking parameter. Built with

151 lines (150 loc) 4.96 kB
/** * @fileoverview Provides a singleton service for scheduling and managing cron jobs. * This service wraps the 'node-cron' library to offer a unified interface for * defining, starting, stopping, and listing recurring tasks within the application. * @module src/utils/scheduling/scheduler */ import cron, { createTask } from "node-cron"; import { logger } from "../internal/index.js"; import { requestContextService } from "../internal/requestContext.js"; /** * A singleton service for scheduling and managing cron jobs. */ export class SchedulerService { /** @private */ constructor() { this.jobs = new Map(); logger.info("SchedulerService initialized.", { requestId: "scheduler-init", timestamp: new Date().toISOString(), }); } /** * Gets the singleton instance of the SchedulerService. * @returns The singleton SchedulerService instance. */ static getInstance() { if (!SchedulerService.instance) { SchedulerService.instance = new SchedulerService(); } return SchedulerService.instance; } /** * Schedules a new job. * * @param id - A unique identifier for the job. * @param schedule - The cron pattern for the schedule (e.g., '* * * * *'). * @param taskFunction - The function to execute on schedule. It receives a RequestContext. * @param description - A description of the job. * @returns The newly created Job object. */ schedule(id, schedule, taskFunction, description) { if (this.jobs.has(id)) { throw new Error(`Job with ID '${id}' already exists.`); } if (!cron.validate(schedule)) { throw new Error(`Invalid cron schedule: ${schedule}`); } const task = createTask(schedule, async () => { const job = this.jobs.get(id); if (job && job.isRunning) { logger.warning(`Job '${id}' is already running. Skipping this execution.`, { requestId: `job-skip-${id}`, timestamp: new Date().toISOString(), }); return; } if (job) { job.isRunning = true; } const context = requestContextService.createRequestContext({ jobId: id, schedule, }); logger.info(`Starting job '${id}'...`, context); try { await Promise.resolve(taskFunction(context)); logger.info(`Job '${id}' completed successfully.`, context); } catch (error) { logger.error(`Job '${id}' failed.`, error, context); } finally { if (job) { job.isRunning = false; } } }); const newJob = { id, schedule, description, task, isRunning: false, }; this.jobs.set(id, newJob); logger.info(`Job '${id}' scheduled: ${description}`, { requestId: `job-schedule-${id}`, timestamp: new Date().toISOString(), }); return newJob; } /** * Starts a scheduled job. * @param id - The ID of the job to start. */ start(id) { const job = this.jobs.get(id); if (!job) { throw new Error(`Job with ID '${id}' not found.`); } job.task.start(); logger.info(`Job '${id}' started.`, { requestId: `job-start-${id}`, timestamp: new Date().toISOString(), }); } /** * Stops a scheduled job. * @param id - The ID of the job to stop. */ stop(id) { const job = this.jobs.get(id); if (!job) { throw new Error(`Job with ID '${id}' not found.`); } job.task.stop(); logger.info(`Job '${id}' stopped.`, { requestId: `job-stop-${id}`, timestamp: new Date().toISOString(), }); } /** * Removes a job from the scheduler. The job is stopped before being removed. * @param id - The ID of the job to remove. */ remove(id) { const job = this.jobs.get(id); if (!job) { throw new Error(`Job with ID '${id}' not found.`); } job.task.stop(); this.jobs.delete(id); logger.info(`Job '${id}' removed.`, { requestId: `job-remove-${id}`, timestamp: new Date().toISOString(), }); } /** * Gets a list of all scheduled jobs. * @returns An array of all Job objects. */ listJobs() { return Array.from(this.jobs.values()); } } /** * The singleton instance of the SchedulerService. * Use this instance for all job scheduling operations. */ export const schedulerService = SchedulerService.getInstance();