GithubHelp home page GithubHelp logo

carljm / django-transaction-hooks Goto Github PK

View Code? Open in Web Editor NEW
108.0 8.0 16.0 85 KB

Django database backends with post-transaction-commit hooks. Merged into Django 1.9; please report bugs or make feature requests in core Django, not here.

Home Page: https://docs.djangoproject.com/en/1.9/topics/db/transactions/#django.db.transaction.on_commit

License: BSD 3-Clause "New" or "Revised" License

Makefile 0.29% Python 99.71%

django-transaction-hooks's Introduction

django-transaction-hooks

This project has been merged into Django and is now core functionality in all supported versions of Django. Use the version built-in to Django; this standalone app is unmaintained.

django-transaction-hooks's People

Contributors

aaugustin avatar bertrandbordage avatar carljm avatar ianlee1521 avatar nsb avatar pelme avatar thedrow avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

django-transaction-hooks's Issues

Where to `connection.on_commit()` for every model save?

I read the docs, but I'm still unclear as to where to put the on_commit() call if I wanted it to run for every save of a model...

I'm guessing that you would add a model.post_save receiver to models.py and inside the receiver add the on_commit?

Maximum recursion depth error when save object in on_commit hooks on Mysql

I use MySQL database and I have ATOMIC_REQUESTS enabled in database settings. What I wanted to try is to modify some DB object in on_commit hook but this caused infinite loop and maximum recursion depth error was raised. Here is a simple code of my view to reproduce it:

def hooktest(request):

    def oncommit():
        print 'ON COMMIT'
        o = DbObject.objects.get(id=1)
        o.name = "test3"
        o.save()

    print "BEFORE"
    connection.on_commit(oncommit)
    print "AFTER"

    print DbObject.objects.all()
    return HttpResponse('OK')
  • django version is 1.6.5, mysql version is 5.5.37

Can't open a transaction within an on-commit hook on SQLite.

This is because opening a transaction on SQLite in autocommit-off raises an error, but we don't have a way to hook into the point when autocommit is turned back on (atomic doesn't call set_autocommit(True) for SQLite, it just manually sets connection.autocommit = True).

This test is currently marked xfail for SQLite.

Django test handling

Since Django tests start a new transaction and never commit it, any on_commit hooks will never get a chance to run in test mode. We've worked around this by writing a test utility that simply calls all registered on_commit hooks, but sometimes this isn't enough.

What do you think about the idea of running on_commit hooks when a SAVEPOINT is committed, but only if we are in test mode? I know there are probably some false positives, but it would simplify testing quite a bit for us.

I'd love to discuss this idea more.

Add a postgis backend

I know that’s super easy to do, but couldn’t there be a postgis backend included in django-transaction-hooks?

Thanks!

Not safe to run database queries in on_commit hooks on Postgres

At the time an outer Atomic calls connection.commit(), it has not yet set the connection back into autocommit mode (that happens in a finally block at the end of Atomic.__exit__. Thus, if database queries are executed in an on-commit hook, they will open a new implicit transaction (since autocommit is still off), and then when Atomic does attempt to restore autocommit, it will fail on Postgres with "autocommit cannot be used inside a transaction."

On SQLite, which always autocommits, or MySQL, which apparently implicitly commits the implicit transaction when asked to go back to autocommit mode, this is not a problem.

I can think of two solutions:

  1. Have run_and_clear_commit_hooks set autocommit on, then run the hooks, then restore autocommit to whatever it was previously set to. This has the disadvantage that in the typical success case, after the transaction is committed, autocommit will be turned on, then back off, then back on again.
  2. Add a run_commit_hooks_on_set_autocommit_on flag to the connection. Instead of running the hooks in commit(), just have commit() set this flag to True, and if this flag is True, run the hooks the next time set_autocommit(True) is called (and reset the flag). (For SQLite, we will still run the hooks directly in commit(), since Atomic never calls set_autocommit(True)). This has the downside that it's depending rather more heavily than I like on details of the implementation of Atomic. I think this is ok (I've documented that django-transaction-hooks is only tested to work with autocommit mode and transaction.atomic), but I don't love it.

(If transaction-hooks become part of core, it would also be possible to have Atomic explicitly notify the connection after successful commit and full reset back to autocommit mode. This is a variant of option (2) -- it means the on_commit implementation is still dependent on Atomic, but the dependence is a bit less muddy.)

I think of these options (2) is superior, but I'm still thinking about whether there are alternatives I've missed.

on_commit values stuck at the last one in a loop

I'm using connect.on_commit(lambda: send_mail(.....)) inside a loop to notify a bunch of users. I found out that all emails were sent to the last user in the loop with identical content - for the last user too. I traced the code in pycharm and found that there were indeed separate lambdas with different memory addresses but somehow they did identical things. I ended up writing a function to loop through all recipients and using that function inside of on_commit instead of having on_commit inside the loop.

While this particular problem is solved, it makes me hesitant about using on_commit because I may accidentally have a loop around some function that has on_commit in it and I don't know if it's going to work correctly or get stuck on the last iteration's values. Also can someone explain why this happens in the first place? Is this the intended behavior? Are there any guidelines on loops? Thanks.

Getting celery task ID

Hi, I'm wrapping my function to on_commit function from this project.
I had an issue to get celery task ID from this transaction hook.

auto = connection.on_commit(
    lambda: auto_received.apply_async(
        args=[rent_order.id],
        eta=booking.return_date + timedelta(hours=49)
    )
)

the auto variable is None, and I want to get the celery task id.

Thank in advance

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.