Skip to content

✨ NEW: Initial implementation of GraphQL mutations#24

Draft
chrisjsewell wants to merge 5 commits into
masterfrom
graphql-mutations
Draft

✨ NEW: Initial implementation of GraphQL mutations#24
chrisjsewell wants to merge 5 commits into
masterfrom
graphql-mutations

Conversation

@chrisjsewell

@chrisjsewell chrisjsewell commented Jun 15, 2021

Copy link
Copy Markdown
Member

@ltalirz @NinadBhat this is a rough initial implementation of the mutation (see https://graphql.org/learn/queries/#mutations and https://docs.graphene-python.org/en/latest/types/mutations/) to create a group, e.g.:

mutation {
  groupCreate(label: "hallo", description: "heya") {
    created
    group {
      id
      uuid
      label
      type_string
      description
    }
  }
}

returns:

{
  "data": {
    "groupCreate": {
      "created": true,
      "group": {
        "id": 19,
        "uuid": "7e345722-892d-4764-b820-b4f12921dc67",
        "label": "hallo",
        "type_string": "core",
        "description": "heya"
      }
    }
  }
}

@codecov-commenter

codecov-commenter commented Jun 15, 2021

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 82.75862% with 10 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.36%. Comparing base (d115033) to head (08ed301).
⚠️ Report is 82 commits behind head on master.

Files with missing lines Patch % Lines
aiida_restapi/graphql/main.py 60.00% 8 Missing ⚠️
aiida_restapi/graphql/groups.py 95.00% 1 Missing ⚠️
aiida_restapi/graphql/plugins.py 94.44% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master      #24      +/-   ##
==========================================
- Coverage   92.09%   91.36%   -0.73%     
==========================================
  Files          25       25              
  Lines         746      799      +53     
==========================================
+ Hits          687      730      +43     
- Misses         59       69      +10     
Flag Coverage Δ
pytests 91.36% <82.75%> (-0.73%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ltalirz

ltalirz commented Jun 15, 2021

Copy link
Copy Markdown
Member

Thanks @chrisjsewell

Hm... that does indeed look quite a bit more complicated than simply posting a JSON {"label": "hallo", "description": "heya"} to /groups.

  • Do we have to create custom "mutation methods" for creating / updating / ... each entity that a user has to learn or can one get around this?
  • While I understand that it is convenient to have the get_or_create functionality, I would probably first try to keep the API simple, i.e. go for group creation only and implement the get_or_create only later if we really need it

@chrisjsewell

chrisjsewell commented Jun 15, 2021

Copy link
Copy Markdown
Member Author

that does indeed look quite a bit more complicated than simply posting a JSON

yes but the point is you get structured schema validation, and control exactly the return data you receive. for /groups or whatever POST method, you have to go to the documentation and find out what is going to return, this is a lot more explicit.
Plus, as with queries, you can perform multiple mutation in a single request.

You can always just write mutation { groupCreate(label: "hallo", description: "heya") { created } }, if you want to be more concise, but the point is the client controls what they receive, and knows by the structure of the request exactly what the structure of the return JSON will be.

each entity that a user has to learn or can one get around this?

what do they have to learn it, its explicitly in the schema: https://aiida-restapi--24.org.readthedocs.build/en/24/user_guide/graphql.html#the-graphql-schema (see RootMutation) 😉

@chrisjsewell

chrisjsewell commented Jun 15, 2021

Copy link
Copy Markdown
Member Author

Do we have to create custom "mutation methods" for creating / updating /

you can create whatever mutation you want, but again IMO explicit is better than implicit (although note currently the get_or_create means that groupCreate is both a create and update mutation)

I'm not sure why this would be any different to deciding what POST methods to create though?

@chrisjsewell

chrisjsewell commented Jun 15, 2021

Copy link
Copy Markdown
Member Author

In 4b6005f I have added a skeleton implementation of middleware (see https://docs.graphene-python.org/en/latest/execution/middleware/). This allows you to interject before each query resolution / mutation, to run operations such as authentication.
IMO this is a better approach than having to remember to decorate every one of your requests with some authentication function (and expecting plugins to do the same), i.e. it consolidates the "business logic" in a single place and separates it from the query/mutation logic (see https://graphql.org/learn/thinking-in-graphs/#business-logic-layer)

(see also https://www.starlette.io/graphql/#accessing-request-information)

@chrisjsewell

Copy link
Copy Markdown
Member Author

and my final pitch (lol) is that, as with queries, mutations are fully pluggable

@chrisjsewell

Copy link
Copy Markdown
Member Author

FYI I added some links to the initial comment

@ltalirz

ltalirz commented Jun 15, 2021

Copy link
Copy Markdown
Member

Thanks for the links to the docs @chrisjsewell

It seems this is indeed the canonical way in graphql...
Are there conventions for the created field? I see the graphene example using ok.
Should we include a field like this for the create methods of every entity type?

Another question that comes to mind here is how to handle files.
E.g. say you post a request that creates two SinglefileData nodes - is there some policy for passing the files with the request that associated them to the right mutation?

@chrisjsewell

Copy link
Copy Markdown
Member Author

Another question that comes to mind here is how to handle files.

I thought exactly the same thing. Graphene specifically mentions https://pypi.org/project/graphene-file-upload/ but not satisfied on the best approach yet

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.

3 participants