We have two cron jobs that hit two different dynamic backends and both are having the same problem. I’m able to duplicate the issue by navigating to the URLs that the cron jobs execute directly in the browser.
Our app has a fairly high cold start time. When I navigate to the URL that uses backends, I see the following error
Error: Server Error
The service you requested is not available yet.
Please try again in 30 seconds.
In the logs, I see the request to /_ah/start (we don’t have a specific handler for this) for the backend with this message:
This request caused a new process to be started for your application, and thus caused your application code to be loaded for the first time. This request may thus take longer and use more CPU than a typical request for your application.
Then what I did was refresh the backend URL and it worked fine.
So my theory is that the cron job would work fine if the backend was already loaded. If it’s not, it doesn’t wait long enough to see if the backend will load up.
Assuming that’s correct, is there a way to have the cron job wait until /_ah/start has finished?
Two other options are to use a resident instance which we’d rather not do, or to improve our cold startup time which is on the todo list but hasn’t been an issue for us until now (we use a resident instance for the frontend).
The backend is a B1. Suppose we could upgrade this but again, being a cash-strapped startup, I’d rather not.
Cron doesn’t have a retry feature which taskqueue has, so I’d recommend using frontend cron in order to put a task onto a Task Queue with a dynamic backend instance. That way, cron request itself will be handled by a vacant frontend instance, which is more reliable than what you’re doing now, and your backend task execution will be retried when in failure.
For making the first cron call robuster, you can make the cron request several times for one particular backend task, and upon putting a task, name a task something associated to a particular task(e.g. 20120430-task1 or something), catch errors for task duplication(and do nothing in the catch clause except for logging).
For more details about named task, please see:
https://developers.google.com/appengine/docs/java/taskqueue/overview#Task_Names