views:

357

answers:

3

Is there any way to run some code after transaction commit in Django?

I need to send some messages to a rabbitmq server for offline processing, but the message gets to the consumer before the Django transaction is commited.

My message is sent in the post_save signal of the model. What I'm looking for is a similar mechanism, using signals or something else, that would execute code after the commit (and do nothing if the transaction fails).

I haven't found any generic way of doing it in Django. Do you have any ideas?

+1  A: 

One possibility would be to subclass the transaction middleware so that it sends a custom signal on commit. Your code could listen for that signal, rather than post_save.

Daniel Roseman
Thanks, I think that I will go with some middleware (I will probably add another middleware and not subclass the transaction middleware).I have a concern about signals though. Are they thread safe? If another thread throws a signal, may the current thread catch it?
Grégoire Cachet
I still have an issue with middlewares : if the application is running from a management command, it won't execute my callbacks.
Grégoire Cachet
I don't think your thread question really makes sense. Signals don't do anything special with regard to threads. A signal sent in one thread will call receivers in that same thread only. Built-in signal objects are module-global, however, so a signal handler registered for post_save in one thread is registered in all threads. (I think it might be possible to have signal objects in your own code that are not global, haven't looked at it carefully).
Carl Meyer
Thanks for the explanation.
Grégoire Cachet
+2  A: 

I don't believe there is a clean way to do this; at least I can't think of one. You could monkeypatch django.db.transaction.commit to send a custom signal; not pretty but I think it would work.

Might also be interesting to raise this use-case on the django-developers mailing list. The devs are generally averse to adding new signals, but you might have a good case here (and a rebuttal from a core dev might include a useful suggestion of how to resolve your situation). You're more likely to get responses if you wait until after 1.1 comes out, though.

Carl Meyer
I have to work on some other parts of my app before, but I will follow this path. When it's ready, I'm going to drop an e-mail to django-developers and add a bug report with the patch.
Grégoire Cachet
A: 

I have implemented transaction signals (post_commit and post_rollback) by monkey patching django: http://gist.github.com/247844

Grégoire Cachet