Schedule a cron job with schedule expression from onRequest cloud function parameter

Viewed 95

Keeping a cron job pub/sub function (functions.pubsub.schedule), within a cloud function (functions.https.OnRequest) and exporting it, does not execute.

A complete example is as follows:

export const sayHelloWhen = functions.https.onRequest((request, response) => {
    cors(request, response,  () => {
        const scheduleExpression = request.body.data.scheduleExpression;
        functions.logger.log(`Called sayHelloWhen with ${scheduleExpression}`);
        functions.pubsub.schedule(scheduleExpression).onRun((context) => {
            functions.logger.log(`Executed sayHelloWhen with ${scheduleExpression}`)
        });
        response.send({
            status: "success",
            data: `scheduled at ${scheduleExpression}`
        })
    })
})

The problem is pub/sub does not trigger. Other codes are executed.

I would like to have HTTP request body scheduleExpression bring into pubsub.schedule's parameter. I don't want a static schedule expression in corn job.

In client, I would like to define a schedule expression in client side as follows:

function scheduleFunction() {
  const functions = getFunctions();
  const sayHello = httpsCallable(functions, "sayHelloWhen");
  sayHello({ scheduleExpression: "every 1 minute" }).then((result) => {
    // const data = result.data;
    console.log("Result:", result);
  });
}

The example below works only for a static schedule expression, meaning that a cloud function itself has a fixed schedule expression:

exports.scheduledFunction = functions.pubsub.schedule('every 5 minutes').onRun((context) => {
  console.log('This will be run every 5 minutes!');
  return null;
});

It can be exported as cron job trigger and it executes.

But keeping pub/sub cron job function, within onRequest cloud function, as in the first code example, does not execute.

1 Answers

I think it is very interesting what you are trying to do, but I would like to point out that you are missing some steps that could cause your app not to execute the way you need it to.

First, you need to Terminate your HTTP functions

Always end an HTTP function with send(), redirect(), or end(). Otherwise, your function might continue to run and be forcibly terminated by the system. See also Sync, Async and Promises.

When you do not terminate them, you might end up in a deeper level in which the following code will not execute unless the previous code has finished. I would also like to say I have not found any application with nested functions like you are doing.


In the Sync, async, and promises page you can find a very explicative video to understand the lifecycle of your functions, and in the How promises work with functions section we have:

When you return a JavaScript promise to a function, that function keeps running until the promise is resolved or rejected. To indicate that a function has completed its work successfully, the promise should be resolved. To indicate an error, the promise should be rejected. This means you only need to handle errors that you want to.

In addition to all this, I would suggest using a separate file to Organize multiple functions for a more organized code, but this is only a suggestion not really necessary.


Finally, I am concerned about the scheduledExpression parameter, I think if none of the above works, you might want to check and share what this value is.

Related