-
-
Notifications
You must be signed in to change notification settings - Fork 804
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix DatabaseSyncToAsync #1290
Fix DatabaseSyncToAsync #1290
Conversation
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fix lint pease!
@auvipy |
yes of course, but should the errors of most of the python version is failing... I am not familiar with the error messages, could you have another look? |
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems good.
I've moved the call to And then to its own class, since it seems to be only relevant for tests after all?! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, so this probably needs a note in the testing topics doc. (And probably a cross-link from the databases topic too, whilst we're there...)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, so two questions:
- If I'm using
database_sync_to_async()
in my code, which I'm then testing, is this going to help? - As a testing tool, wouldn't this be better off in
pytest-django
?
You can use a conditional import based on
Well, maybe - but it affects test runners in general, not just pytest. Therefore it makes sense to ship it with channels. |
JFI: I would like to get feedback from @adamhooper (via #1091 (comment)) before doing anything here. |
Also I consider this to be a hack really, and there is hopefully a better way. |
Added tests. There are two issues here: with conn_max_age=0 (the default) it does not run into "sqlite3.OperationalError: database table is locked" or postgresql not being able to teardown the db, but it will not rollback the changes (due to |
btw: just found this: https://github.com/blueyed/asgiref/blob/1c23eb6832b39e94628fd7600c0bc1baf3105dbe/asgiref/local.py#L22-L27 I could not grasp how/where it is being used though. |
6118ed6
to
656afce
Compare
I've removed DatabaseSyncToAsyncForTests, fixing DatabaseSyncToAsync itself. |
Okay, thanks @blueyed. I shall have a look at this (finally) over the next period. |
As a user of Django-Channels, this complexity scares me, outside of a unit-test framework. @blueyed: outside of unit tests, how can a main-thread database connection enter an atomic block? My understanding is that the main thread should never connect to the database, period. (An exception is Django-Channels unit tests, evidently.) Django saved my neck while I was first delving into Django-Channels: it raised a I see considerable risk. For one thing, your implementation never calls More broadly, imagine a user accidentally uses the main-thread connection. (In my experience, this is a very common error.) Currently, that erroneous main-thread connection won't cycle like it should: the user will get a "lost connection" error once in a while, but the site will stay up. But with the code in this pull request, any database operation that starts while the (buggy) main-thread connection is in an atomic block will replace the worker thread's database connection with the main-thread connection, irreversibly. Now that two threads are using the same database connection, that doubles the risk of the problem spreading to another thread. Soon, all worker threads will use the main-thread database connection. This produces undefined behavior. Ironically, this is exactly what I'm not a Channels maintainer; but could my concerns please be addressed? I'd be much more comfortable if this code -- which seems specially made to help Django-Channels unit tests pass -- were to part of the unit test framework. Shouldn't DatabaseSyncToAsync be left alone? |
@adamhooper
It is for tests only, yeah (IIRC).
I agree that it is scary - not sure about |
- copy/use connections from the main thread, which are in an atomic block (used in tests) - do not close connections in atomic blocks Ref: django#1091 (comment)
Use _inherit_main_thread_connections in thread_handler directly.
Move it to DatabaseSyncToAsyncForTests
XXX: Django still uses its broken method for request_started/request_finished though.
Required since django/django@a415ce70b (Django 3.0).
This does not work on Django 3.0 anymore, when |
I just looked at this bug in depth and wrote my findings in this comment: #1091 (comment) I think much of this PR is not really relevant any more:
Thank you for digging in here @blueyed . It seems the fix in asgiref has changed the nature of this bug slightly, and should make it easier for us to write a fix. |
I believe #2101 will fix this bug, if anyone on this thread would mind checking I would appreciate it |
block (used in tests)
Ref: #1091 (comment)