Closed adam-codeberg closed 8 years ago
Did some debugging today.
Pyramid function invoke_subrequest in routes.py @LN185 is receiving the expected route instance "Request at 0x2db2490 POST http://localhost:6543/api/contacts/1/emails" but @LN217 "response = handle_request(request)" it returns a 400 response error.
I'm taking a wild guess, but looks like ramses isn't giving the pyramid router the parameters in the format it wants or something.
Worth highlighting, GETs work fine, but POSTs return 400. Maybe the ramses generator.py. I noticed a conditional statement there that cleans the URL for elastic search on POSTs.
Worked back to LN 162 in "response = view_callable(context, request)" in Pyramids router.py
The exception is behind there somewhere.
There is an issue with 2+ (or is it 3+) levels of nesting. This is something we need to work on in a future release. @postatum can you confirm if this is related to a story that's already in our backlog?
Spent some time yesterday trying to get my head around Ramses workflow. Probably only worked out 40% of it so far. Do you have any docs/notes hidden away that may help?
I'm stuck at the moment, the document dicts look fine. Can't work out why its its failing at the time of processing the _bulk_body as it tries to POST data to the table linked via foreign key.
A wild guess would be that its running the POST against the wrong table, but haven't found the object/variable used in _bulk_body that holds the target table data yet.
@adam-codeberg thanks for reporting the issue. I can confirm that with 2+ objects API nesting it may not work properly.
@jstoiko yes, we have a story related to this issue in our backlog.
Thanks @postatum any recommendations on which Module (Ramses, Nefertari, Nefertari-SQL) I should focus my efforts in looking at to dig up the cause?
@adam-codeberg to get a meaningful traceback of what is happening, comment this line https://github.com/brandicted/ramses/blob/master/ramses/__init__.py#L21.
When nefertari.view
is included, it registers error views, which wrap all errors in JSON responses. Unfortunately for those hacking Ramses this also hides useful tracebacks from console.
@postatum Thanks for the info, appreciated!
Haven't had much luck solving this one. Hopefully you have more luck than I did.
@postatum in an effort to narrow down the problem. Has Nefertari + Nefertari_SQL been proven able to manage nested /collection/item/collections? If so I can focus on Ramses. If not then I can focus on Nefertari + _SQL.
hey @adam-codeberg
Has Nefertari + Nefertari_SQL been proven able to manage nested /collection/item/collections?
Nefertari contains of building blocks and it doesn't have any default implementation of DB collections/items fetching(except BaseView.get_collection_es). It is possible to register nested collections using Nefertari, but the views which will implement the logic of getting collection/item will have to be implemented by target project developer. So right now it will be developers' responsibility to make sure Book objects returned by shop/{id}/books
belong to Shop with Id=1.
I think the issue here is in Ramses since Ramses implements views. I remember working on nested collection/item GET requests but I didn't have a chance to look into making it work with all requests.
@postatum thanks so much for the information. That will be a great help. No guarantees I will find the cause, just hope to improve my chances :)
Thanks for help @adam-codeberg :) Feel free to ask if you have more questions.
I spent some time checking out views.py in Ramses today.
One thing I noticed was that in https://github.com/brandicted/ramses/blob/master/ramses/views.py#L447 "model_cls._nesting_depth" always returns 1
Side note nesting counter appears to start at 1 not 0
"parent_resource.uid" in https://github.com/brandicted/ramses/blob/master/ramses/generators.py#L61 seems to check out and returns the correct relationship.
Was wondering if "model_cls._nesting_depth" is used in an iteration somewhere when applying database changes to a resource. If ramses is failing to iterate to the next resource and uses the same resource twice, it would explain why nefertari cant find contacts_id.
Reference RAML example https://github.com/adam-codeberg/ramses-templates/tree/master/addressbook
Haven't found an iteration of this type yet, I'm looking around to see how "model_cls._nesting_depth" is used in ramses.
@adam-codeberg model_cls._nesting_depth
is only used when returning JSON response. It is used in nefertari and nefertari-sqla/mongodb I think.
To see how nested GETs work now you may want to look into get_collection[_es]
and get_item[_es]
methods of ramses views.
@postatum I should mention that GETs are working fine with the nested RAML example.
Its POST that is broken.
It succeeds up until towards the end of the POST process. This is where it tries to apply the one to many relationship key to the parent table in postgresql. It fails to find the field "contacts_id". From what I can see/guess, it can't find the "contacts_id" table because it hasn't switched its focus from the child table (emails) to the parent table (contacts). Alternatively the focused table may be None or something.
@postatum I've exported the ramses request when model.save is invoked, you can check it out here https://www.diffchecker.com/9xe65ywz
If you ignore the different memory references, there's not much difference between them except for matchdict{} so im guessing that matchdict{} is malformed or not being processed correctly.
Let me know if you have any suggestions.
@adam-codeberg please post full error traceback here (with commented include(nefertari.view)
when you POST
@postatum sure, here it is (working/unnested : broken/nested) https://www.diffchecker.com/nvnvobkw
@adam-codeberg I meant a traceback with this line commented https://github.com/brandicted/ramses/blob/master/ramses/__init__.py#L21 Thanks :)
@postatum yes, sorry about that. Have commented it out and reposted the link https://www.diffchecker.com/nvnvobkw
Forgot about doing that. Its really nice to see the queries instead of digging through classes to get them :)
Looks like the problem is down with the transaction call to sqlalchemy. Maybe it doesn't like a variable its being given?
@adam-codeberg I think you should ipdb here https://github.com/brandicted/ramses/blob/master/ramses/views.py#L184 and look at obj
to see if it's looks ok. You can also try saving it manually and/or committing transaction after it to find a place where it fails.
Actually, looks like this is ramses views / nefertari bug.
Part if your recent traceback:
File "/home/adam/.pyenv/versions/cb-software-licensing-system/lib/python2.7/site-packages/pyramid/renderers.py", line 428, in render_view
return self.render_to_response(response, system, request=request)
File "/home/adam/.pyenv/versions/cb-software-licensing-system/lib/python2.7/site-packages/pyramid/renderers.py", line 451, in render_to_response
result = self.render(value, system_values, request=request)
File "/home/adam/.pyenv/versions/cb-software-licensing-system/lib/python2.7/site-packages/pyramid/renderers.py", line 447, in render
result = renderer(value, system_values)
File "/home/adam/.pyenv/versions/cb-software-licensing-system/lib/python2.7/site-packages/nefertari/renderers.py", line 61, in __call__
value = self.run_after_calls(value, system)
File "/home/adam/.pyenv/versions/cb-software-licensing-system/lib/python2.7/site-packages/nefertari/renderers.py", line 160, in run_after_calls
value = call(**dict(request=request, result=value))
File "/home/adam/.pyenv/versions/cb-software-licensing-system/lib/python2.7/site-packages/nefertari/wrappers.py", line 319, in __call__
self._set_object_self(result)
File "/home/adam/.pyenv/versions/cb-software-licensing-system/lib/python2.7/site-packages/nefertari/wrappers.py", line 312, in _set_object_self
resource.uid, **{resource.id_name: obj_pk})
And then traceback goes to url dispatch of Pyramid.
Let me explain this in a few words:
As you can see, traceback goes through "renderers" and "wrappers". From this we assume that response was partially generated and went to "wrappers" where it failed on something related to urldispatch (check rest of full traceback).
Thanks, that's helpful, I was just exploring the before/after calls in _transactions. I will re-read what you said and drill down some more into it.
Something interesting i found was that, on a failure, TransactionManager.abort() is being called before commit() so something is raising the abort() function before that https://github.com/zopefoundation/transaction/blob/master/transaction/_manager.py#L76
so something is raising the abort()
May be flush(). We flush() transaction on some object actions.
Thanks @postatum, your info helped a lot in speeding up the process.
Since this is a nefertari problem I will create the ticket https://github.com/brandicted/nefertari/issues/121
Ok, worked it out now.
wrapper.py failing to provide Pyramid with the right **kwarg key See https://github.com/brandicted/nefertari/blob/master/nefertari/wrappers.py#L312
It hits this part of Pyramid and dies https://github.com/Pylons/pyramid/blob/master/pyramid/url.py#L279 because it cant find the route based on the params given to it. Pyramid needs a key:value in the **kwargs dict for the parent that its not being given. Once I change the wrappers.py line to
resource.uid, **{'contacts_id': 1, resource.id_name: obj_pk})
It works, have confirmed with the postgresql database.
Next step is to find a way to assign the key:value programatically.
Have completed a programmatic solution, can be found in my fork here https://github.com/adam-codeberg/nefertari/blob/master/nefertari/wrappers.py#L290
When interacting with nested endpoints they appear to have trouble identifying the parents ID
The result is that the data gets inserted into elasticsearch but not postgre.
Steps to reproduce
Use RAML and Schemas provided here /addressbook/
Debug output is as follows
Have been mashing face against keyboard for most of the day without success.