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
Transaction API #2248
Comments
Option 3 looks better. |
Option 3 looks good |
I like option 3 |
I like option 3 too |
I vote for option 3 too |
Vote for option 3! |
Is there any coding progress? I'm REALLY interested in using MongoDB's transactions.... so interested that I'd offer to code it but I'm still fairly new to Python. |
Thanks for your interest @coughlinjake so far, I've only do a small proof of concept. I was in fact waiting to have some decisions from the maintainer (ping @wojcikstefan). I'm pretty busy now but if I manage to start at some point on this, I'll check if we can share the workload |
I can help you there. If you are ok I can share the load. Do we have any design or spec available or need to write one?
Get Outlook for iOS<https://aka.ms/o0ukef>
…________________________________
From: Jason Coughlin <notifications@github.com>
Sent: Thursday, August 6, 2020 5:22:10 AM
To: MongoEngine/mongoengine <mongoengine@noreply.github.com>
Cc: Das, Ajitesh <ajitesh_das@hotmail.com>; Comment <comment@noreply.github.com>
Subject: Re: [MongoEngine/mongoengine] Transaction API (#2248)
Is there any coding progress? I'm REALLY interested in using MongoDB's transactions.... so interested that I'd offer to code it but I'm still fairly new to Python.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub<#2248 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AO6S4FH7KMHPIKNJBSM5YSDR7KN7FANCNFSM4KI3XZAQ>.
|
looks like, we have some helps at our disposals. If we have decided on the approach, we can go ahead start the project.
Who takes the decision here? Can he please fill in.
Thanks!
Ajitesh
…--
A person should not be too straight or too honest. Straight trees are cut first and honest people are screwed first.
-Chanakya
________________________________
From: Henry <notifications@github.com>
Sent: Monday, July 13, 2020 10:29 PM
To: MongoEngine/mongoengine <mongoengine@noreply.github.com>
Cc: Das, Ajitesh <ajitesh_das@hotmail.com>; Comment <comment@noreply.github.com>
Subject: Re: [MongoEngine/mongoengine] Transaction API (#2248)
Vote for option 3!
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub<#2248 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AO6S4FAL6WRWG64I2MVK7I3R3PUKBANCNFSM4KI3XZAQ>.
|
Hi @bagerard , I am not sure if I am on right track or not, but I modified the library for transaction support. Following is the snippet for using the session.
P.S.:
|
Is there any coding progress? Hope to realize this feature. Thanks |
option 3 will be gooooooood |
This allows for the use of the update and modify MongoEngine functions to use a transaction. Relevant: MongoEngine#2248
Will this feature be merged? |
option 2 looks good for me |
The session argument in the `save` function allows document insertions and updates within a transaction that go through the `save` method. Note this does not enable transactions for the `update`, `modify`, and `delete` methods on the Document class. Relevant: MongoEngine#2248
The session attribute is used in _cursor_args to pass a transaction session to PyMongo whenever a queryset is iterated over. It also replaces the session argument to the update and modify functions. This means the following functions now support transactions: `insert, update, modify, __iter__, in_bulk`. `delete` does not support sessions yet. Relevant: MongoEngine#2248
The session attribute is used in _cursor_args to pass a transaction session to PyMongo whenever a queryset is iterated over. It also replaces the session argument to the update and modify functions. This means the following functions now support transactions: `insert, update, modify, __iter__, in_bulk`. `delete` does not support sessions yet. Relevant: MongoEngine#2248
A TransactionSession can be used as a context manager to wrap a series of statements that need to be performed as part of a transaction. It will automatically commit upon exiting the context successfully or rollback if an error is encountered. Recommended usage is ``` with TransactionSesssion() as session: User.objects.session(session).update(...) ``` Related: MongoEngine#2248
I've been playing around with an implementation for option 3, without getting very deep into the guts of mongoengine (yet 😈 ) and I have some interface/usage thoughts/questions based on poking I've done. Transactions are fine to run across multiple DBs. from mongoengine import *
conn1 = connect()
db1 = conn1.db1
db1.test1.insert_one({'foo1': 'bar1'})
db2 = conn1.db2
db2.test2.insert_one({'foo2': 'bar2'})
with conn1.start_session() as session:
with session.start_transaction():
db1.test1.insert_one({'foo1-1': 'bar1-1'}, session=session)
db2.test2.insert_one({'foo2-2': 'bar2-2'}, session=session) The primary go/no-go point is the client instance (aka connection). So if you tried to run a transaction against two collections/databases across two completely different client instances - no good: from mongoengine import *
conn1 = connect()
db1 = conn1.db1
db1.test1.insert_one({'foo1': 'bar1'})
conn2 = connect(alias='other-default', port=27018)
db2 = conn2.db2
db2.test2.insert_one({'foo2': 'bar2'})
with conn1.start_session() as session:
with session.start_transaction():
db1.test1.insert_one({'foo1-1': 'bar1-1'}, session=session)
db2.test2.insert_one({'foo2-2': 'bar2-2'}, session=session)
InvalidOperation: Can only use session with the MongoClient that started it So that's good - internally, there are already checks that sessions are "consistent." Fun fact - this doesn't raise an exception and goes through fine: with conn1.start_session() as session:
with session.start_transaction():
db1.test1.insert_one({'foo1-1': 'bar1-1'}, session=session)
db2.test2.insert_one({'foo2-2': 'bar2-2'}, session=None) Implementation samplesGlobal
|
I deleted my last comment regrading coupling of databases/connections 🤦 - missed something simple and I went down a rabbit hole - sorry for the noise ❤️ |
@juannyG I would just like to push a very pragmatic, almost non technical argument :
So, while it certainly will be needed in the future, it’s not as important to manage connections as having a transaction API. You’ll know best if the effort is worth it, I just saw you were wondering about implementing it in your PR, so this is just to say that I think that, yes session-by-connection will be asked for, but it’s a corner case |
My vote would be for 3) as well but instead of a global session, consider using a ContextVar so that multiple threads can execute transactions concurrently: from contextvars import ContextVar
_session = ContextVar("_session", default=None)
def _set_session(session):
if _session.get():
raise InvalidOperation("nested run_in_transaction calls are not allowed")
return _session.set(session)
def _get_session():
return _session.get()
... You may also want to consider using the ClientSession.with_transaction api because it handles retries automatically. |
My 2 cents: Are these options mutually exclusive? I think you would like have option 2 anyways and it's quite easy to implement. It goes in line with pymongo==mongo interfaces and is a lot less magical. I suggested that this would be done first. If some one would do this would be open to merging it in? As this issue has ben open for almost three years we could just implement the simple one? Option 3 is the more complex and magical and I can image there are many pitfalls that are not instantly obvious. Accidentially wrapping too much in one session etc. |
One more point. Sometimes you don't need transaction, but just explicit session. Right now it's not possible run long queries with mongoengine at all as cursor will timeout after 30 minutes even with no_cursor_timeout=True.
|
Hi everyone, it's already 2024 and this seems to be a forgotten topic, any updates on this? |
I'd like to open the discussion on the interface that we want to use for supporting the use of transactions/sessions within MongoEngine.
Items to keep in mind:
switch_database
)Assuming a test class like
I see 3 options:
session
object to each and every queryset/queriesPros:
Cons:
Person.objects(name='test', session=session)
looks a bit weirdPerson.objects(name='test', session=session1).update(name='test2', session=session2)
Document.objects().session(session)
Pros:
Cons:
Person.objects().session(session).insert(Person())
looks quite uglyPros:
Cons:
repository pattern / unit of work
approachOf course, we would provide a decorator in addition to the context manager.
Personally I initially thought that 2) would be the best but I quickly came across a few examples that looked unnatural, so I'd suggest to go for 3)
Let me know what you think! (especially @wojcikstefan @erdenezul but happy to gather more feedbacks)
The text was updated successfully, but these errors were encountered: