AppEngine Deferred module improved
==================================

This is forked from FreshPlanet's improved `App Engine Deferred module <https://github.com/freshplanet/AppEngine-Deferred>`_.
and has the added functionality of having a Django View along with the webapp2 handler so that it can be used in
either project type.

The AppEngine Python SDK has a great module when it comes to easily run some code "later": `the deferred library <https://developers.google.com/appengine/articles/deferred>`_
(if you are unfamiliar with this library, please have a look at its documentation first).

However the library has a few drawbacks that we solve here:

- No asynchronous method (`issue 9530 <https://code.google.com/p/googleappengine/issues/detail?id=9530>`_)
- The internal request handler inherits from webapp instead of webapp2 which can be an issue when using some webapp2 features (like webapp2.get_request)
- It uses pickle instead of leveraging cPickle available with the Python 2.7 runtime.
- The Route it uses is internal and will skip your middlewares unless you define them in a special appengine_config.py module.
- Task could fail to properly execute when hitting a fresh instance which did not had all code loaded
- Logging is a bit verbose: it uses the INFO level to show task headers that are redundant with what we can see by default in the AppEngine logs

We also added a couple of features to it:

- Explicit URLs for tasks: instead of just seeing */_ah/queue/deferred* in your logs you will see something like */_cb/deferred/app.module.name/funcName*
- Possibility to spread tasks over several queues in case of high throughput
- Improved logging in case of error
- Possibility to tie it to a *background* module to optimize serving requests

And some helpers:
- is_from_task_queue(): Check if we are currently running from a task queue
- get_retry_count(): Returns the current number of times the current task is being retried
- log_as_retried(): Depending on # of times the task is being retried, we will increase the logging level.

Our module still makes use of the deferred exceptions types ```SingularTaskFailure``` and ```PermanentTaskFailure``` to be compatible with existing code.

Installation
~~~~~~~~~~~~

1. pip install fh-django-gae-tasks
2. Load the app in your Django project's settings.py

.. code-block:: python

    INSTALLED_APPS = (
        'gae_tasks'
    )

3. Load the URL for the app

.. code-block:: python

    urlpatterns = [
        url(r'^', include('gae_tasks.urls')),
    ]

4. Optionally, better integrate with your application by updating the tasks settings:

.. code-block:: python

    GAE_TASKS_DISABLE: False
    GAE_TASKS_WARMUP_MODULE: None
    GAE_TASKS_DEFAULT_QUEUES: ['default']
    GAE_TASKS_BACKGROUND_MODULE: None

(See the tasks module for more details)
