Re: Transaction APIs do not consult the DB router to choose DB connection

2021-05-27 Thread charettes
Ticket that directed to the mailing list for wider feedback 
https://code.djangoproject.com/ticket/32788

---

Can you think of places where this db_for_transaction hook would differ in 
any way from what db_for_write returns? That's what Django uses internally 
in such instances

   1. ​
   
https://github.com/django/django/blob/0d67481a6664a1e66d875eef59b96ed489060601/django/db/models/base.py#L745-L760
 
   

 
   2. ​
   
https://github.com/django/django/blob/0d67481a6664a1e66d875eef59b96ed489060601/django/db/models/base.py#L950
 
   

 
   3. ​
   
https://github.com/django/django/blob/0d67481a6664a1e66d875eef59b96ed489060601/django/db/models/deletion.py#L400
 
   

 

I get that your asking for a way to avoid explicitly passing atomic(using) 
all over the place but I'm having a hard time figuring out in which cases a 
db_for_transaction hook, which cannot be provided any contextual details 
like other router methods do, can take an an advised decision without 
relying on contextual/global state.

Is there a reason you can't replace your wide spread internal uses of 
atomic by something along these lines

def routed_atomic(savepoint=True, durable=False):

using = get_global_using()

return transaction.atomic(using, savepoint=savepoint, durable=durable)

Cheers,

Simon
Le jeudi 27 mai 2021 à 12:18:50 UTC-4, gojeta...@gmail.com a écrit :

> From the Django docs, for any ORM query made, the DB alias to use is 
> determined by the following rules:
>
>- Checks if the using keyword is used either as a parameter in the 
>function call or chained with QuerySet.
>- Consults the DB routers in order until a match is found.
>- Falls back to the default router which always returns default as the 
>alias.
>
> Using the router scheme works perfectly for ORM queries. However, when it 
> comes to using transaction APIs ​(like the transaction.atomic construct), 
> it becomes mandatory to specify the *using* kwarg explicitly in all of 
> its publicly exposed APIs if a DB other than the default alias has to be 
> chosen.
>
> To illustrate why this is a problem, consider the following scenario:
>
>- A DB router exists such that it directs queries to a specific 
>database based on a value set in *thread-local* storage by a 
>middleware.
>- When ORM queries from within the view are fired, they automatically 
>get forwarded to the right DB *without explicitly citing* the using 
> keyword 
>owing to the router.
>- But if the transaction.atomic construct is used, the using keyword 
>would have to be explicitly specified each time. While this might seem 
>fine, it creates the following problems:
>   1. For large code bases, it becomes highly unwieldy to make sure 
>   that the *using* keyword has been mentioned in every transaction 
>   API call. Also, if one tries to implement the above scheme in an 
> already 
>   existing code base, it would be impractical to add the using keyword in 
> all 
>   lines calling the transaction APIs.
>   2. It doesn't gel well with the the routers framework.
>
> A proposed workaround could to be to add a separate method named 
> *db_for_transaction* to the routers framework which would be consulted by 
> the transaction APIs first, before falling back to using the default DB 
> alias.
>
>
>1. Having a separate method for transaction is good because it need 
>not be mangled up with the other methods i.e db_for_read / db_for_write as 
>they clearly indicate certain operational semantics which aren't tied to a 
>transaction since it can have both reads and writes within it. 
>2. Also, if in the future, there is some special info that can be 
>delivered to the transaction based on which a decision regd which DB to 
> use 
>could be made, then it would be cleanly isolated into its own method.
>
>
> If we can finalise on this, I could submit a PR for the same.
>

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/3e3feb3a-5189-4384-b660-ded1b87385c1n%40googlegroups.com.


Transaction APIs do not consult the DB router to choose DB connection

2021-05-27 Thread N Aditya


>From the Django docs, for any ORM query made, the DB alias to use is 
determined by the following rules:

   - Checks if the using keyword is used either as a parameter in the 
   function call or chained with QuerySet.
   - Consults the DB routers in order until a match is found.
   - Falls back to the default router which always returns default as the 
   alias.

Using the router scheme works perfectly for ORM queries. However, when it 
comes to using transaction APIs ​(like the transaction.atomic construct), 
it becomes mandatory to specify the *using* kwarg explicitly in all of its 
publicly exposed APIs if a DB other than the default alias has to be chosen.

To illustrate why this is a problem, consider the following scenario:

   - A DB router exists such that it directs queries to a specific database 
   based on a value set in *thread-local* storage by a middleware.
   - When ORM queries from within the view are fired, they automatically 
   get forwarded to the right DB *without explicitly citing* the using keyword 
   owing to the router.
   - But if the transaction.atomic construct is used, the using keyword 
   would have to be explicitly specified each time. While this might seem 
   fine, it creates the following problems:
  1. For large code bases, it becomes highly unwieldy to make sure that 
  the *using* keyword has been mentioned in every transaction API call. 
  Also, if one tries to implement the above scheme in an already existing 
  code base, it would be impractical to add the using keyword in all lines 
  calling the transaction APIs.
  2. It doesn't gel well with the the routers framework.
   
A proposed workaround could to be to add a separate method named 
*db_for_transaction* to the routers framework which would be consulted by 
the transaction APIs first, before falling back to using the default DB 
alias.


   1. Having a separate method for transaction is good because it need not 
   be mangled up with the other methods i.e db_for_read / db_for_write as they 
   clearly indicate certain operational semantics which aren't tied to a 
   transaction since it can have both reads and writes within it. 
   2. Also, if in the future, there is some special info that can be 
   delivered to the transaction based on which a decision regd which DB to use 
   could be made, then it would be cleanly isolated into its own method.


If we can finalise on this, I could submit a PR for the same.

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/b62206d5-b001-413c-a58e-e78c08596497n%40googlegroups.com.