Mark James
Mark James

Reputation: 568

cron jobs on firebase cloud functions

I have two cloud functions

  1. One cloud function is for set or updating existing scheduled job

  2. Canceling an existing scheduled job

I am using import * as the schedule from 'node-schedule'; to manage Scheduling a jobs

The problem is cus createJob function is triggered and jobId is returned, but later when I triger cancelJob function all prev scheduled cron jobs do not exist cus node-schedule lives in memory and I can't access the jobs:

this will return empty object: const allJobs = schedule.scheduledJobs;

Does anyone have some solution on this situation?

UTILS this is the main logic that is called when some of my cloud functions are triggered

// sendgrid
import * as sgMail from '@sendgrid/mail';
import * as schedule from 'node-schedule';
sgMail.setApiKey(
  'apikey',
);


import {
  FROM_EMAIL,
  EMAIL_TEMPLATE_ID,
  MESSAGING_SERVICE_SID,
} from './constants';

export async function updateReminderCronJob(data: any) {
  try {
    const {
      to,
      ...
    } = data;
    const message = {
      to,
      from: FROM_EMAIL,
      templateId: EMAIL_TEMPLATE_ID,
     
    };

   

    const jobReferences: any[] = [];

    // Stop existing jobs
    if (jobIds && jobIds.length > 0) {
      jobIds.forEach((j: any) => {
        const job = schedule.scheduledJobs[j?.jobId];
        if (job) {
          job.cancel();
        }
      });
    }

    // Create new jobs
    timestamps.forEach((date: number) => {
      const job = schedule.scheduleJob(date, () => {
        if (selectedEmail) {
          sgMail.send(message);
        }
      
      });

      if (job) {
        jobReferences.push({
          jobId: job.name,
        });
      }
    });

    console.warn('jobReferences', jobReferences);

    return jobReferences;
  } catch (error) {
    console.error('Error updateReminderCronJob', error);
    return null;
  }
}

export async function cancelJobs(jobs: any) {
  const allJobs = schedule.scheduledJobs;
  jobs.forEach((job: any) => {
    if (!allJobs[job?.jobId]) {
      return;
    }
    allJobs[job.jobId].cancel();
  });
}


Upvotes: 0

Views: 532

Answers (1)

Doug Stevenson
Doug Stevenson

Reputation: 317808

node-schedule will not work effectively in Cloud Functions because it requires that the scheduling and execution all be done on a single machine that stays running without interruption. Cloud Functions does not fully support this behavior, as it will dynamically scale up and down to zero the number of machines servicing requests (even if you set min instances to 1, it may still reduce your active instances to 0 in some cases). You will get unpredictable behavior if you try to schedule this way.

The only way you can get reliable scheduling using Cloud Functions is with pub/sub functions as described in the documentation. Firebase scheduled functions make this a bit easier by managing some of the details. You will not be able to dynamically control repeating jobs, so you will need to build some way to periodically run a job and check to see if it should run at that moment.

Upvotes: 2

Related Questions