Skip to Content

Use App Engine task queues to schedule Cloud Functions

Take advantage of App Engine's cron capabilities to schedule Cloud Functions invocations

Posted on 4 mins read

Cloud Functions offers developers a serverless environment, to let them build and connect cloud services together, one function at a time. As of today, there’s one aspect still missing: it’s the ability to schedule function invocations.

Say you want to get a function invoked at a regular interval: every hour, some reporting function should be run, to tell you about the status of your orders. How can you achieve this? Our solution in this article: we’ll take advantage of App Engine’s cron capabilities to forward requests to Cloud Functions.

Exposing an HTTP-triggered Cloud Function

In the first place, I created a Google Cloud project with Cloud Functions enabled, where I’ve deployed a simple hello world function:

exports.helloWorld = function helloWorld(req, res) {
  // Example input: {"message": "Hello!"}
  if (req.body.message === undefined) {
    // This is an error case, as "message" is required.
    console.log("No message received");
    res.status(400).send('No message defined!');
  } else {
    // Everything is okay.
    console.log(req.body.message);
    res.status(200).send('Success: ' + req.body.message);
  }
};

This helloWorld function is a synchronous function, responding to HTTP triggers.

To invoke it (for testing purpose), one can issue CURL calls as follows:

curl -X POST https://<REGION>-<PROJECT_ID>.cloudfunctions.net/helloWorld \
     -H "Content-Type: application/json" \
     --data '{"message": "Happy New Year!"}'

And the function will reply with:

Success: Happy New Year!

Now let’s see how to take advantage of App Engine’s task queues and cron capabilities.

Configuring a small App Engine app with a cron definition

For the purpose of this demo, I am using App Engine Standard with the Java 8 runtime.

Note: My application is using the Gaelyk web framework for App Engine, with the Apache Groovy programming language. But the choice of web framework or language is not critical in this tip, and you can very well just use any web framework or language supported by App Engine. However, in my case, my project runs on App Engine Standard and its recent Java 8 runtime. This aspect is important, as the way to configure the cron capabilities vary depending on which runtime you chose. On the Java runtime, the cron definitions will be using an XML format (instead of YAML for other runtimes like Go.)

We need to do two things to schedule a Cloud Function invocation:

  • First, we create a cron.xml file in WEB-INF that defines a URL local to our App Engine app, that will forward incoming requests to our function. The cron.xml file specifies the schedule (ie. every 10 minutes), as well as an optional retry policy.
  • Then, we configure our App Engine app to forward requests to the URL from cron.xml to the function.

Here is my cron.xml file:

<cronentries>
  <cron>
    <url>/redirect-hello</url>
    <description>Redirect to the helloWorld function</description>
    <schedule>every 10 minutes</schedule>
  </cron>
</cronentries>

My function will be invoked every 10 minutes. But you can learn more about the possible scheduling options in the documentation.

Now, I define a new routing rule for my web framework of choice to do the forward. The route definitions are configured in WEB-INF/routes.groovy in the Gaelyk framework:

all "/call-hello", forward: "/callHello.groovy"

We defined the path call-hello that will call the callHello.groovy controller, which is located in WEB-INF/groovy. Let’s now have a look at this controller (also called a groovlet), and see how it calls the Cloud Function:

out <<
    new URL('https://us-central1-fn-gae-cron.cloudfunctions.net/helloWorld')
        .post(payload: request.inputStream.bytes, 
              headers: ['Content-type': 'application/json'])
        .text

The controller makes a POST request to our Cloud Function, passing any payload that would have been sent to App Engine (although in our case, cron calls don’t pass any payload), and we return the text output of the functino call.

When looking at the logs of my function in Stackdriver logging, I’ll see every 10 minutes that the function has indeed been called, and a message saying No message defined!is printed (because my App Engine cron call doesn’t send any message.)

More information

For this artcile, I was inspired by this post from Valerii Iatsko, showing how to use App Engine for Python for scheduling Cloud Functions calls.

You can learn more about App Engine Java’s cron configuration in the documentation.

If you are also interested in Apache Groovy and Gaelyk, you can refer to:

  • the Apache Groovy documentation
  • the Gaelyk framework documentation (and in particular all the nice shortcuts offered to simplify the use of App Engine)
comments powered by Disqus