Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Periodic tasks in Django/Celery - How to notify the user on screen?

I have now succesfully setup Django-celery to check after my existing tasks to remind the user by email when the task is due:

@periodic_task(run_every=datetime.timedelta(minutes=1))  
def check_for_tasks():      
    tasks = mdls.Task.objects.all()
    now = datetime.datetime.utcnow().replace(tzinfo=utc,second=00, microsecond=00)
    for task in tasks:
        if task.reminder_date_time == now:
            sendmail(...)

So far so good, however what if I wanted to also display a popup to the user as a reminder?

Twitter bootstrap allows creating popups and displaying them from javascript:

$(this).modal('show');

The problem is though, how can a celery worker daemon run this javascript on the user's browser? Maybe I am going a complete wrong way and this is not possible at all. Therefore the question remains can a cronjob on celery ever be used to achieve a ui notification on the browser?

like image 516
Houman Avatar asked Nov 30 '12 17:11

Houman


2 Answers

Well, you can't use the Django messages framework, because the task has no way to access the user's request, and you can't pass request objects to the workers neither, because they're unpickable.

But you could definitely use something like django-notifications. You could create notifications in your task and attach them to the user in question. Then, you could retrieve those messages from your view and handle them in your templates to your liking. The user would see the notification on their next request (or you could use AJAX polling for real-time-ish notifications or HTML5 websockets for real real-time [see django-websocket]).

like image 191
Chewie Avatar answered Oct 05 '22 15:10

Chewie


Yes it is possible but it is not easy. Ways to do/emulate server to client communication:

polling The most trivial approach would be polling the server from javascript. Your celery task could create rows in your database that can be fetched by a url like /updates which checks for new updates, marks the rows as read and returns them.

long polling Often referred to as comet. The client does a request to the server which pends until the server decides to return something. See django-comet for example.

websocket To enable true server to client communication you need an open connection from the client to the server. django-socketio and django-websocket are examples of reusable apps that make this possible.

My advice judging by your question's context: either do some basic polling or stick with the emails.

like image 35
Jesse the Game Avatar answered Oct 05 '22 14:10

Jesse the Game