Navidht
Navidht

Reputation: 1

Run a java function every n second in Google App Engine

What is the best way in Google App Engine to run a certain function every 5 seconds (which requires database insertion)?

Upvotes: 0

Views: 1079

Answers (4)

Alex
Alex

Reputation: 5286

You could use cron https://cloud.google.com/appengine/docs/standard/python/config/cronref

I think fastest schedule you can have every 5 minutes, but that 5 minute task could add a bunch tasks to the task queue of staggered to launch every 5 seconds.

cron.yaml

cron:
- description: "task name"
  url: /do-thing
  schedule: every 5 minutes

request handler

from google.appengine.ext.deferred import deferred

def do_thing():
    pass

# request handler for "/do-thing"
class CronRequestHandler(webapp2.RequestHandler):
    def get(self):
        for seconds in xrange(0,300,5):  # 0, 5, 10, ... 295]
            deferred.defer(do_thing, _countdown=seconds)

You could also have a dedicated manual scaling instance that does something like this:

import time

# request handler for '/_ah/start'
class Start(webapp2.RequestHandler):

    def get(self):
        while True:
            time.sleep(5)
            do_thing()

Upvotes: 1

Dan Cornilescu
Dan Cornilescu

Reputation: 39834

To avoid sleeping inside a request handler (which is generally not a good use of GAE) you could use a self-enqueueing push queue task deferred by 5 seconds:

  • when receiving a task request the task handler would first enqueue another deferred task (which will be the one executing at the next iteration) then proceed to actually performing the work to be done at the current time
  • you could use a cron job to create and enqueue the first such task (or after the self-generating task sequence is interrupted for whatever reason), after which each task will take care of enqueuing the subsequent one
  • you need to disable automatic task retrying - to prevent accidentally ending up with multiple groups of self-generating tasks which will run simultaneously giving you less than 5s between execution

Alternatively you could use a 1 min cron job to enqueue 12 separate push tasks:

  • first one with no delay
  • each subsequent one deferred with progressively 5s longer delay

This would produce a more precise timing than the method above since the delays between enqueuing won't be compounded.

Not sure if the Java runtime allows creating deferred tasks by specifying the absolute execution time rather than just a delta delay, if so that could be a better approach, again with more precise timing: the absolute execution time for each of the 12 tasks can be precisely computed based on the current cron job's time with minute precision, which would also minimize the impact of the cron execution time skew.

Upvotes: 1

user1455719
user1455719

Reputation: 1065

Google app engine provides a scheduler facility called Cron to run repeated tasks in a specified interval period. These tasks are commonly known as cron jobs. These cron jobs are automatically triggered by the App Engine Cron Service. For instance, you might use a cron job to send out an email report on a daily basis, or to update some cached data every 10 minutes, or refresh summary information once an hour.

In your case, You can create a REST operation that inserts a new record into the database. And this REST operation is accessible via URL. And you can create a cron service that get will run in a specified period and invoke the rest insert operation via the REST URL.

Please refer to https://cloud.google.com/appengine/docs/standard/java/config/cron for more information.

Upvotes: 0

N.F.
N.F.

Reputation: 4202

You can do it by cron in combination with a little bit code.

The minimum interval of cron is 1 minutes. What you have to do is invoke a cron job every 1 minutes and invoke your function 12 times with 5 seconds sleep inside the cron job.

cron.xml

<cronentries>
  <cron>
    <url>/path/to/your/job</url>
    <description>your job</description>
    <schedule>every 1 minutes</schedule>
  </cron>
</cronentries>

yourcronjob.java

public class YourCronJob extends HttpServlet {

    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException {
        for (int i=0; i<12; i++) {
            yourFunction();
            Thread.sleep(5000);
        }
    }
}

Upvotes: 1

Related Questions