Skip to content
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

SCAL-104: Implement db transactions in mongoengine #4

Merged
merged 8 commits into from
Mar 30, 2021

Conversation

jonasanso
Copy link
Contributor

No description provided.

@jonasanso jonasanso changed the base branch from master to fix-dec-on-v23 March 16, 2021 19:18
@jonasanso jonasanso force-pushed the SCAL-104-implement-db-transactions branch 6 times, most recently from 3495ef6 to b90455e Compare March 17, 2021 16:30
@@ -11,17 +11,12 @@ on:
tags:
- 'v[0-9]+\.[0-9]+\.[0-9]+*'
env:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed as we do not need to support old version of pymongo nor mongoDB and it would get more complicated to do so. We can do that later

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems likely that upstream would want these cases handled before merging back in, but if this PR is just for our use then I don't see a problem with it for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I do not think we will be able to just take this PR and merge it in mongoengine, there are a lot of small details in the support for transactions in the different versions of the DBs.
Of course, they could also decide to increase the major version and say, it works only in MongoDB 4.4+ but I do not think that will be the case

@@ -506,7 +506,7 @@ def to_mongo(self, value):
def prepare_query_value(self, op, value):
return self.to_mongo(value)

def validate(self, value):
def validate(self, value, clean=True):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warnings of my IDE, using the same function signature as in super

@@ -18,6 +21,49 @@
)


class run_in_transaction(contextlib.ContextDecorator, contextlib.ExitStack):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The context manager and decorator

"""
super().__enter__()
self.conn = get_connection(self.db_alias)
self.session = self.enter_context(self.conn.start_session())
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now I am not testing or worrying about nested transactions or reuse of the session

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I am using the pymongo context manager for start_session I believe every session is closed


from mongoengine.connection import DEFAULT_CONNECTION_NAME, get_connection

sessions = local()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code to handle the sessions, I might clean it up and I accept suggestions about alternatives to this global

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is a poor idea to create this globally. Modules shouldnt really have side-effects on import and globals are discouraged.

I would prefer a thread_local_session class which creates a local() and binds a new session to it when asked, then has the free functions below as methods.

I am unsure quite how we'd pass existing sessions down to nested transactions, but there is probably a way to do that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is the thing I was not able to do, I want to have something that I can access with an import, if not I need to store an instance somewhere :)
A singleton would also be nice, but I quite do not know how to do it.
I will investigate more about it

@jonasanso jonasanso force-pushed the SCAL-104-implement-db-transactions branch from b90455e to 25d8d29 Compare March 18, 2021 07:09
Jonas and others added 3 commits March 18, 2021 14:51
Reset fork to v.23 and fix validation of inc and dec for an IntField with min_value
@@ -1173,6 +1186,9 @@ def allow_disk_use(self, enabled):

:param enabled: whether or not temporary files on disk are used
"""
if not IS_PYMONGO_GTE_311:
return self

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you explain this change please?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The property allow_disk is not accepted in pymongo 3.11 and it was making a test fail, so I return the existing qs to avoid a failure.
Not sure if it is the right solution, but I wanted my tests green :)

tests/test_session.py Show resolved Hide resolved
tests/document/test_instance.py Outdated Show resolved Hide resolved

with run_in_transaction():
person.save()
person.to_dbref()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing an assert?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not know, it is like the test above but running inside a transaction.
I added it to be sure it was working properly even in a transaction, but I do not know how it should work :)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I had a look at the to_dbref function and I don't know what could be added to the test either :/


person.reload()
assert person.name == "Mr Test User"
assert person.age == 21

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to be done twice?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not know, I copied the test above, maybe there is a reason, I have no clue 😂

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd remove it and see if the test still passes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

surely it will pass, removing assertions would not make it fail, if you want me to remove it I do not have a problem
I simply do not know why it was duplicated in the test above.
I will remove it :)

@jonasanso
Copy link
Contributor Author

Thanks for reviewing @clembrival any questions or suggestions on the main logic and their tests, am I missing something?

mongoengine/context_managers.py Show resolved Hide resolved
tests/document/test_dynamic.py Show resolved Hide resolved
mongoengine/context_managers.py Show resolved Hide resolved

from mongoengine.connection import DEFAULT_CONNECTION_NAME, get_connection

sessions = local()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is a poor idea to create this globally. Modules shouldnt really have side-effects on import and globals are discouraged.

I would prefer a thread_local_session class which creates a local() and binds a new session to it when asked, then has the free functions below as methods.

I am unsure quite how we'd pass existing sessions down to nested transactions, but there is probably a way to do that.


person.reload()
assert person.name == "Mr Test User"
assert person.age == 21
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd remove it and see if the test still passes.

mongoengine/context_managers.py Show resolved Hide resolved
Copy link

@Samathy Samathy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Theres more than one test with a lot going on in the transaction contexts, I think the code in transaction contexts should be limited to just the code performing database queries that need a transaction, and not include prints, asserts or other stuff.

tests/document/test_dynamic.py Outdated Show resolved Hide resolved
@jonasanso jonasanso merged commit ced97a5 into fix-dec-on-v23 Mar 30, 2021
@jonasanso jonasanso deleted the SCAL-104-implement-db-transactions branch March 30, 2021 04:41
@jonasanso jonasanso restored the SCAL-104-implement-db-transactions branch March 30, 2021 04:42
@jonasanso jonasanso deleted the SCAL-104-implement-db-transactions branch March 30, 2021 11:34
@jonasanso jonasanso restored the SCAL-104-implement-db-transactions branch March 30, 2021 11:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants