Update mutation removing connection between nodes in one field and setting the connection on a different field fails


Report a GraphQL Bug

What edition and version of Dgraph are you using?

Edition:

  • SlashGraphQL
  • Dgraph (community edition/Dgraph Cloud)

If you are using the community edition or enterprise edition of Dgraph, please list the version:

Dgraph Version
$ dgraph version
 
v21.03.0

Have you tried reproducing the issue with the latest release?

yes

Steps to reproduce the issue (paste the query/schema if possible)

Using docker-compose:

version: "3.8"
services:
  zero1:
    image: dgraph/dgraph:v21.03.0 # latest release
    working_dir: /data/zero1
    ports:
      - 5080:5080
      - 6080:6080
    labels:
      cluster: test
      service: zero1
    volumes:
      - ~/dgraph:/dgraph
    restart: on-failure
    command: dgraph zero
      --logtostderr -v=2
      --bindall
      --expose_trace
      --profile_mode block
      --block_rate 10
      --my=zero1:5080
  alpha1:
    image: dgraph/dgraph:v21.03.0 # latest release
    working_dir: /data/alpha1
    volumes:
      - ~/dgraph:/dgraph
    ports:
      - 8080:8080
      - 9080:9080
    labels:
      cluster: test
      service: alpha1
    restart: on-failure
    command: dgraph alpha 
      --zero=zero1:5080
      --expose_trace
      --profile_mode block
      --block_rate 10
      --logtostderr 
      -v=2
      --my=alpha1:7080
      --bindall
      --security whitelist=0.0.0.0/0
      --graphql lambda_url=http://lambda:8686/graphql-worker

  lambda:
    image: dgraph/dgraph-lambda
    labels:
      cluster: test
    ports:
      - 8686:8686
    depends_on:
      - alpha1
    environment:
      DGRAPH_URL: http://alpha1:8080
    volumes:
      - type: bind
        source: ./dist/src/dgraph/lambdas/lambdas.js
        target: /app/script/script.js
        read_only: true

Simplified schema

interface NodeBase {
  id: ID!
  description: String
}
type Person implements NodeBase  {
  attempted: [PersonalActivityType]
  plannedConversations: [Conversation]
}
type PersonalActivity implements NodeBase {
  name: String
}
type Convo1 implements NodeBase {
  type: String!
}
type Convo2 implements NodeBase {
  thing: String!
}
union Conversation = Convo1 | Convo2
union PersonalActivityType = Convo1 | Convo2 | PersonalActivity

Add Person with plannedConversations, return person with their plannedConversations:

mutation ($person: AddPersonInput!) {
  addPerson (input: [$person]) {
    person {
      id
      plannedConversations { ...on Convo1 {id __typename} ...on Convo2 {id __typename} }
      attempted { ...on Convo1 {id __typename} ...on Convo2 {id __typename} }
    }
  }
}

with $person variable:

  "person": {
    "plannedConversations": [
      { "convo1Ref": { "type": "yes" } },
      { "convo2Ref": { "thing": "no" } }
    ]
  }

Remove plannedConversations, and set them as attempted:

mutation ($patch: UpdatePersonInput!) {
  updatePerson (input: $patch) {
    person {
      id
      plannedConversations { ...on Convo1 {id __typename} ...on Convo2 {id __typename} }
      attempted { ...on Convo1 {id __typename} ...on Convo2 {id __typename} }
    }
  }
}

with $patch variable:

  "patch": {
    "filter": { "id": ["0x3de23dd12"] },
    "set": { "attempted": [{ "convo1Ref": { "id": "CONVO1_ID" } }, { "convo2Ref": { "id": "CONVO2_ID" } }] },
    "remove": { "plannedConversations": [{ "convo1Ref": { "id": "CONVO1_ID" } }, { "convo2Ref": { "id": "CONVO2_ID" } }] }
  }

Expected behaviour and actual result.

Expected Behavior:
This should result in the Person’s plannedConversations being an empty array. The Person’s attempted should have both conversations.

Actual Result:
The request just drags on for minutes on end without receiving a response. And future queryPerson operations requesting the same return as that which is in the mutations above stall out in the same way. No error. Just no response.

And this happens anytime thereafter that I try to query that person’s attempted field.

Other Important Notes:

  • Running the update with only set OR only remove works as expected. However, running one after the other results in the same no-response problem on the second update (no matter which was first).
  • Simultaneously setting both conversations as attempted and removing one (either one) from plannedConversations works just fine as well. But if another update removes the final conversation from plannedConversations, the same problem arises.
  • This behavior is the same regardless of how many conversations are added. If there are 5, up to 4 can be removed from planned and put into attempted with no issues. But when the last one is removed from planned, the problem arises.
  • After running into this problem, when I run docker-compose down, the logs say there was a MEMORY LEAK detected:

Update:

It does appear to work with Dgraph Cloud. I don’t understand why it wouldn’t work with the local docker spinup. I’ve restarted everything multiple times, even updated Docker Desktop. It breaks with my actual, complicated schema and with this simplified schema.

The error is FetchError: request to http://localhost:8080/graphql failed, reason: socket hang up.

1 Like

Over a year later, I still run into lots of issues with socket hangups, specifically around GraphQL mutations involving Unions and Interfaces.

I’ve noticed that defining edges on an interface seems to be problematic in this way. For instance, take this definition:

interface ConversationBase {
  id: ID!
  type: CONVERSATION_TYPE!
  data: [DataItem]
}

type ReflectionConversation implements ConversationBase {
  reflectiveItem: String
  reflectionType: REFLECTION_TYPE
}

type DataItem {
  id: ID!
  key: String!
  value: String
  dataType: DATA_TYPE
}

I am regularly seeing socket hangups when attaching DataItem to either the ConversationBase interface or an implementing type using an update mutation. This issue also occurs both if the DataItems are created beforehand and attached later and if the DataItems are created during the update mutation as seen here:

mutation UpdateConversationBase {
  updateConversationBase (input: {
    filter: { id: ["some-id"]},
    set: { data: [{ key: "thing", value: "stuff" }, { key: "marvel", value: "comics" }] } 
  }) {
    numUids
  }
}

Is there any guidance on why this might happen? Or is there a way to stop a GraphQL operation that has already started? CPU usage spikes and doesn’t go down. And if more mutations like this are attempted, it can quickly spiral out of control. The only way I know how to stop it is to restart the docker container.

There doesn’t seem to be anything in the documentation about these issues with Unions and Interfaces. Any support or insight would be appreciated.

1 Like

Hey @jackl I’ll look at this next. Are you still running this against 21.03.0?

Thanks for the response. Yes I’m still running 21.03.0. I’m using dgraph cloud for production and docker for development and testing, so I don’t want to update my setup until cloud is updated to the latest version.

That said I suppose I should try on the latest version and see if it is any better. But given that I haven’t seen any discussion of the issue (not even on my year-old post :frowning: ), I’d guess the problems are still there.

What’s the size of the graph when things go awry?

Size in terms of number of nodes + edges? Maybe a thousand? But I think at some point I saw the issue right away without a large graph size. It may have been the initial post in this thread.

EDIT:
Okay, after a little more testing, the issue arises immediately in 21.03 when attempting to add edges by running an update mutation on an interface. However, the issue isn’t there in the latest release.

I have not yet tested my full service with the latest release. I’ll update again once that is done. Probably tomorrow, though.

@matthewmcneely After more testing, the issue only seems to affect v21.03, and not the latest release. I’m just going to update my setup.

I wonder if this issue has anything to do with the context deadline exceeded errors people have experienced on cloud? Regardless, getting cloud updated to the latest release would be nice. Hopefully that happens soon. Thanks for your attention!

@jackl Can you share which version you were able to see correct functionality? I could not find a PR that seemed to address the issue specifically. Thanks.

I assume it’s v22.0.1. That’s what’s listed as the latest release on your github.

image: dgraph/dgraph:latest

OK, thanks.