aiidateam / aiida-core

The official repository for the AiiDA code
https://aiida-core.readthedocs.io
Other
436 stars 190 forks source link

DbUser is already attached to session, on store() of a Node #5719

Open pcolaianni opened 2 years ago

pcolaianni commented 2 years ago

Describe the bug

I am following the tutorial at https://aiida.readthedocs.io/projects/aiida-core/en/latest/internals/rest_api.html#extending-the-rest-api

When POSTing, it works. The first time. The second time, it raises an exception:

  File "/tmp/rdm-ui-api/app2.py", line 41, in post
    paramsData = Dict(dict=params).store()
  File "/opt/conda/lib/python3.8/site-packages/aiida/orm/nodes/node.py", line 455, in store
    self._store(with_transaction=with_transaction, clean=True)
  File "/opt/conda/lib/python3.8/site-packages/aiida/orm/nodes/node.py", line 472, in _store
    self._backend_entity.store(links, with_transaction=with_transaction, clean=clean)
  File "/opt/conda/lib/python3.8/site-packages/aiida/storage/psql_dos/orm/nodes.py", line 220, in store
    session.add(self.model)
  File "/opt/conda/lib/python3.8/site-packages/sqlalchemy/orm/session.py", line 2626, in add
    self._save_or_update_state(state)
  File "/opt/conda/lib/python3.8/site-packages/sqlalchemy/orm/session.py", line 2645, in _save_or_update_state
    self._save_or_update_impl(st_)
  File "/opt/conda/lib/python3.8/site-packages/sqlalchemy/orm/session.py", line 3226, in _save_or_update_impl
    self._update_impl(state)
  File "/opt/conda/lib/python3.8/site-packages/sqlalchemy/orm/session.py", line 3209, in _update_impl
    to_attach = self._before_attach(state, obj)
  File "/opt/conda/lib/python3.8/site-packages/sqlalchemy/orm/session.py", line 3303, in _before_attach
    raise sa_exc.InvalidRequestError(
sqlalchemy.exc.InvalidRequestError: Object '<DbUser at 0x7fb3c7f67f70>' is already attached to session '1' (this is '2')

Steps to reproduce

Steps to reproduce the behavior:

  1. Run an instance of the docker image version 2.0.4
  2. pip install aiida-core[rest]
  3. create the app.py file as explained in the tutorial, and run it
  4. curl http://localhost:6000/api/v4/new-endpoint/ -X POST
  5. Run again curl http://localhost:6000/api/v4/new-endpoint/ -X POST

Expected behavior

The second call should create a new object and return the id.

Your environment

Other relevant software versions, e.g. Postres & RabbitMQ

Additional context

I found out about this issue while trying to extend the API to support the upload of files. In my case, I am dealing with data of type SinglefileData. At first I thought the problem was uploading the same file several times. But then I tried uploading two different files, and it fails anyway. Also uploading the same file in two different runs of app.py works. AiiDA correctly creates two nodes for the same uploaded file. Therefore the problem seems to be with managing the backend session and the DbUser object.

sphuber commented 2 years ago

Thanks for the report @pcolaianni . This is due to incomplete documentation, but the current REST API should be read-only. It doesn't officially support changing state. The error you found is part of the reason why. There has been ongoing work on implementing a new REST API that does allow POSTing data: https://github.com/aiidateam/aiida-restapi

I am personally not involved in that work, but maybe @chrisjsewell or @flavianojs can shed some light on the status?

ltalirz commented 2 years ago

Hey @pcolaianni , I just updated the documentation of the plugin See https://aiida-restapi.readthedocs.io/en/latest/user_guide/tutorial.html for how to use it.

@sphuber We could close this issue or we could keep it open as a reminder that POST to endpoints that don't support it (I guess all endpoints except the querybuilder one?) should fail.

sphuber commented 2 years ago

We could close this issue or we could keep it open as a reminder that POST to endpoints that don't support it (I guess all endpoints except the querybuilder one?) should fail.

I will quickly open a PR to update the aiida-core docs on extending the REST API saying that only read-only operations are supported.

ltalirz commented 2 years ago

Hey @pcolaianni, apologies for just glancing over your issue - after properly reading through your issue description I do agree it points to an issue in the current REST API implementation.

There are examples of others who extended the REST API to POST requests, such as the codebase for the AiiDA-Ginestra integration. I.e. it is possible that this bug was introduced more recently and went unnoticed because, currently, the only POST endpoint (/querybuilder) in the REST API that ships with aiida-core does not involve the creation of nodes in the AiiDA database.

I just tried creating multiple nodes using the aiida-restapi plugin, and that worked fine. Furthermore, the aiida-restapi already includes an endpoint for creating a singlefiledata via multipart form - you can try it out using the swagger client at /docs (just follow the tutorial I linked above)

image

We also just made aiida-restapi compatible with aiida 2.0 (for aiida-1.x compatible version use tag v0.1.0a0).