-
Notifications
You must be signed in to change notification settings - Fork 235
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
Upgrading to version 3.3.0 causes a KeyError on initialising connection to neo4j DB #378
Comments
Hello @jdalydt Thanks for letting us know about this. No, it is not a known issue so far and I am sorry if it has caused a headache to you guys. Can you please confirm if This is related to the way neomodel creates a mapping between labels and native classes to be able to properly instantiate a class given a generic All the best P.S.: Can I please ask @Winawer, @mstefaniak10 and @manoadamro to confirm if they also receive a similar error and let us know if the fix that is suggested in this post fixed it? |
Adding The full stack trace is:
|
@aanastasiou I can also confirm that this fix had no effect. |
@manoadamro & @jdalydt thank you very much for such a quick response. At this point, I do not have enough information to give you something more useful. The module passes its tests and it is also used actively in a project I am working on which has not produced any such errors. So, there is not much to work with at my end I am afraid. Can I please ask you to create a small test case demonstrating how this fails? In the meantime, the exception is thrown because neomodel has retrieved a Node with a subset of labels that does not match the subset of labels inferred from the (model) class hierarchy (if that is of any help). Would like to hear more about this so we can fix it however. All the best |
@aanastasiou That's not going to be easy. |
@manoadamro I understand. When I said "...small test case..." I meant something like this. That repo outlines how we got to this change really. I have not tried accessing the database across versions as you describe, but there should not be a problem as long as the labels that are inferred from the class hierarchy match the labels of the nodes in the database. This is why, I cannot really tell you, what might be going wrong. I will give it a try to setup "cross-version access" myself, but in the meantime, if you can isolate the problem in a small test script that would be helpful too. |
I have started a repo, will let you know how it goes 👍 |
Thanks for letting me know, BTW, have you run |
yeah we have this: |
@manoadamro Quick question, related to my earlier comment: Do you have anywhere in your code, something like:
And within that file not having imported If yes, can you please try this:
And let me know if that improved the situation? |
@aanastasiou currently trying to get my head around another error at the moment. the write_transaction decorator is failing every second time with: when 🤷♂️ |
@manoadamro Thanks for letting me know. Wish I could be more helpful but without knowing a bit more about your setup, it is difficult to comment on the exception snippets :/ |
@aanastasiou I have managed to fix one occurrence of the error with your suggested fix (not all though) this causes unused imports and forces bad code style :( |
@manoadamro That is great, thank you for letting me know. I am not advocating bad code style with my suggestion but since that worked, I now have something to work with on my end and a better idea of how to go about fixing the problem. If you come up with any specific fixes in the meantime, please let me know or go ahead with a PR. All the best |
Background:
The issue:
Temporary Fix: Now, is the solution for I have not thought about this yet, maybe the fix ends up being a combination of the two. As a temporary solution however, I would suggest that you examine your Can I please ask you to confirm if this fixes the issue for you? |
@aanastasiou |
Hey @aanastasiou thanks for looking into this. From my recollection the full module path gets stored in the relationship definition. we just need to check if that exists in |
Hi @robinedwards, I have not looked much into resolving it yet but thanks for pointing this out, it really helps. All the best |
@manoadamro Quick note as I am going through this to automate the loading of a potential class: The relationship's end-point model can well be a class. Which then does not lead to any unused imports. We can make this clearer in the documentation. |
I am also running into this issue in a different context which may be of use. I'm attempting to use neomodel from a django environment via django-neomodel. In this environment I have even less control over the ordering of import statements or the threading context in which neomodel is imported. I'm not very well versed on django internals, but it looks as though the global During django startup I see the It's worth mentioning that neomodel works perfectly fine when invoked from a normal django shell EDIT: I can confirm that reverting to 3.2.9 solves the problem. |
Hey, thanks a lot for contributing your experience, this is very useful. Please see below:
That should not be a problem because
This is a problem. The short term answer to that is to make sure that all the models that the view is likely to use have been imported to the view (please see earlier discussion in this thread). We are working on a better solution for that.
That might be the case but I do not feel that we have enough data to decide categorically on that yet. For example, it is not necessary for the whole model to be loaded to the registry for the resolution to work. Only the part that will be required is necessary. And this does not require a global context.
I have not worked very much with All the best |
Thank you for the quick reply and apologies if I came across as critical of your efforts. It is true that I have a small fear and skepticism towards a global db instance being hidden inside of a module at import time. But it's far outweighed by the simplicity and ease of use of the neomodel interface. It was incredibly easy to start using, and the model definitions so far seem super concise and lightweight. I'm grateful for this! |
@theterg Hi, no need for apologies, don't worry about it. One thing we have not done about this issue is to create a script that replicates the problematic behaviour. At the moment, I am working along the lines of this and this is why I said that I do not have experience in using Can I please ask you the following:
All the best |
Update: Neo4j-community edition 3.4.9, neomodel 3.3.0, Flask 1.0.2, Python 3.5.2. The only modification that I did was to add:
...at the end of the script and run it with Update 2: No it doesn't :/ The script fails when the application really tries to access the database and THAT is how the problem reveals itself because the I am not very familiar with the internals of Flask but this could be resolved by somehow preserving the Please let me know if any of you think otherwise but I think that this should be mentioned explicitly in the documentation. Essentially, prior to |
@robertlagrant Then it sounds that a new issue should be created. Can you please do this and remove the previous comment to keep this thread focused on 378? (EDIT: It would be interesting to see a description of the "cluster problem" because I have used In brief, the situation (about issue 378) is described further below but also, if you scroll back in this discussion you will find additional details about specific issues that I might omit in the following general description:
This is where we are at the moment. If you would like to help, I would appreciate it if you provided web-framework specific views on how to deal with preserving state, especially for Django. At the moment I am trying to see how to do this with There is a bit more work that has taken place in the background, you can see gists and repos further up but overall this is where we are at the moment. All the best |
@jonadaly @manoadamro @theterg @mzgajner @mostafa @mjmare @MardanovTimur @phoebebright @robertlagrant @robinedwards Here is a minimal Gist to show:
All the best |
@aanastasiou AFAIK in Django you have a The schema definition is the Django Model definition itself (as created by the user and ensured consistency with the schema in the database by schema migrations once during server startup) and a One may choose to re-use the connection, but that is most of the time not the case (never in development, optional in production) to reduce the number of simultaneous connections 'open' to the database. Better to open, do transaction, close. Is neomodel assuming a single open connection? I am curious to see how |
My question was specifically about how Django's middleware uses
I am assuming you mean one connection that needs to remain connected to the server. If that is the case, then no.
Please see this gist which is also linked in my last post. This is a very crude outline of how the problem is dealt with in Flask and it shows how to "save" the state between calls. I have not looked any further details into this but I am fairly confident that applications can be isolated from each other so that it is possible to run different applications on the same server, all using neomodel but over different connections and schemata. As mentioned above, I think that this is going to have to be solved on a "per-framework" basis. Django has its own middleware infrastructure so does Pyramid and other frameworks. I think that it would help if there was a repository that demonstrated how Django models integrate with All the best |
@aanastasiou two stupid questions:
|
@robertlagrant Thanks for your comment. There are no stupid questions. I do not have a problem with accepting any misunderstanding on my part and I would be glad to get any deeper insight by anyone who would like to offer it.
|
@aanastasiou The repo can be found here: https://github.com/jberends/django_neo_3.3.0 Indeed it seems that the _NODE_CLASS_REGISTRY is not populated inside the request stream. I use Pycharm and I included a 'run' command that may be used to run/debug the server once loaded. What I found out is:
update 1445 - Found a possible solutionI am sure it is the design of the 'singleton' of the Database object. The object definition of the
Once I subclass from A patch would look like: --- neomodel/util.py
+++ neomodel/util.py
@@ -42,7 +42,7 @@
db.cypher_query("MATCH (a) DETACH DELETE a")
-class Database(local):
+class Database(object):
def __init__(self):
self._active_transaction = None
self.url = None |
@jberends Thank you very much for this, the respository is very useful anyway. Regarding the rest of it, it is as you describe it. The The bit that is going to be complicated then is this one. In other words, multi-threading application transactions are pushed under the same "unit of work" but across processes a new connection is created. This change would mean that even multi-thread calls would create a new connection. Does anyone see any problems with that (?) Edit: @jberends Just to be clear about something: When people have been talking about integration with Django so far, I assumed that it was about getting Django models to work together with |
Even 'threads' re-instantiate the Database object, not only processes.
This might be tricky indeed. If I understand correctly:
If this is the case, one would think to separate the concept of storing the ' So maybe the Conclusion: Factor out the
Sure, I get that. However neomodel does already provide a nice way to define the model and deal with NodeSet results. A more integrated solution with more 'django-feel' would help traction of adoption of neo4j in django-land IMHO, but that is more for Update 17:00I made a small POC implementation on https://github.com/KE-works/neomodel/tree/feature_class_registry_singleton and that works, except 2 tests that alter the registry directly. I did not have time to fix those. This is an ugly POC using globals to provide a dict. A class implementation may be wiser. Also credits to my collegue @oikonomou with which I had an extensive discussion on the topic. 🤝 |
Well, a bit more work has taken place around this and a "batched" operations feature (but if possible via multiple units of work and batches of units of work). I have left it as a long term TODO because I was trying to solve it via By the way, if in the meantime someone comes up with a meta-class based solution faster, please submit a pull request.
Alright, I will see what I can do, but at the moment, I cannot say that I will have this ready by XYZ deadline. If anyone else would like to go towards that direction, please go ahead.
Thanks, I appreciate getting into the trouble of creating the repository and because of this I thought I'd clarify that the way that case fails is clear (to me) and it would not need further demonstration. |
I've tested the @oikonomou changes, but to no avail! The issue persists! |
@robertlagrant A possible way forward if |
What is your setup? We've been testing it in Python 3.6 with latest django 2.1 and it works, also on more evolved cases. Furthermore other testcases (in py27) passes. |
@jonadaly @manoadamro @theterg @mzgajner @mostafa @mjmare @MardanovTimur @phoebebright @robertlagrant @robinedwards @jberends @oikonomou Can I please ask you guys to give it a go and test this branch? It incorporates a number of pull requests the most important of which for this issue is the one by @oikonomou that so far seems to have solved this issue:
@mjmare, @robertlagrant talked about Pylons / Pyramid before so it would be nice to hear from you if it works there too, although, I do not see why it should not. Looking forward to hearing from you |
@aanastasiou I can confirm that the branch you provided works without flaws. |
@jberends Thanks for taking the time to perform any additional tests, just bear with me as I am going through a number of other contributions at the moment prior to making the next release please. |
@aanastasiou The changes appears to work:
Subsequent switching between the versions has the behaviour you would expect (3.2.9 and the above branch work; 3.3.0 results in the node registry problems). |
@jonadaly Thank you for taking the time to do this. |
We've had it running in dev for a couple of weeks and it seems stable to us. |
@aanastasiou Given that this seems to be working, when can we expect to see a release with this fix included? (Appreciate the hard work from all parties investigating and fixing - it's just this has been an issue for a while now so would be good to get it resolved ASAP!) |
Hello everyone, the release was made last Friday. We are now on 3.3.1. I am sorry I did not make a special announcement. I would also like to thank everyone who took the time to look into any aspect of this issue and give us feedback or suggestions. All the best |
Did you write any changelog or other releasenotes? Next time I can help with that if you like. |
@jberends Yes, I did:
Will make sure that these changes are reflected in the repository too. |
We have a neo4j instance, populated with the help of neomodel v3.2.9. The v3.3.0 of neomodel breaks when attempting to initialise the connection to the database:
This appears to be as a result of the self._NODE_CLASS_REGISTRY changes included in v3.3.0, which appear to be breaking. Is this a known issue? Given that this is a minor version bump, we would not expect breaking changes to be included.
The text was updated successfully, but these errors were encountered: