Setup Delayed Background Task Using Google App Engine Deferred

Jan 16, 2018

Task Queue is usually used to execute background task, where you can even setup Cron Jobs.

But if you have a small task which you intent to run in background after each request, do consider using deferred. Sample use cases are:

  • Send email or sms after each request (avoid blocking the request)
  • Post for FB/Twitter after 5 minutes delay (allow user window to make edits)

The following code will execute defer_post in background after the request complete.

import loggingfrom google.appengine.ext import ndb, deferreddef defer_post(item_key=None):    try:        item = item_key.get()        # do something    except Exception as e:        # this to avoid         logging.info('item_key: %s', item_key.urlsafe())        logging.exception(e)        raise deferred.PermanentTaskFailure()@app.route('/test_refer/<item_key>')def test_defer(item_key):    item_key = ndb.Key(urlsafe=item_key)    deferred.defer(defer_post, item_key=item_key)    return "defer_post queued"

NOTE: implementing deferred.PermanentTaskFailure is optional, where it will keep on retrying after specific intervals.

NOTE: deferred function must be a module function, not inner function or anonymous function.

You can delay the execution using _countdown parameter.

# wait 60s then run in backgrounddeferred.defer(defer_post, item_key=item_key, _countdown=60)

If you setup a Push Queue to specify the processing rate, you can specify the queue name.

NOTE: Queue name must match pattern ^[a-zA-Z0-9-]{1,100}$

# wait 60s then run in backgrounddeferred.defer(defer_post, item_key=item_key, _countdown=60, _queue="my-defer-queue")

There are a few gotchas using deferred, mainly:

  • Don't pass entities as parameter (the entity might be stale by the time background task execute), use entity key.
  • Avoid permanent repeated failure by raising deferred.PermanentTaskFailure.
  • If you are using modules imported using sys.path.append, make sure you include them in the current module.
  • All argument must be pickable.
  • Don't pass in nested function, methods of nested classes, lambda function, static method. Deferred function must be a module function, not inner function or anonymous function.
  • Use this for small task only.

References:

❤️ Is this article helpful?

Buy me a coffee ☕ or support my work via PayPal to keep this space 🖖 and ad-free.

Do send some 💖 to @d_luaz or share this article.

✨ By Desmond Lua

A dream boy who enjoys making apps, travelling and making youtube videos. Follow me on @d_luaz

👶 Apps I built

Travelopy - discover travel places in Malaysia, Singapore, Taiwan, Japan.