"Transaction has been aborted. Please retry" when creating nodes with different predicate values

Hi,

Dgraph version : v20.07.0

I have written an application which imports a big list of domain names and name servers into Dgraph. It works fine until I start another process importing data from another file. As soon as there are two processes running, they both start throwing “Transaction has been aborted. Please retry” errors.

The following predicates have the @upsert directive enabled:

  • name
  • hash

The application has functions which do “Get or Create” when creating/updating a node depending on whether it exists. If the node exists, the values are loaded into a struct, otherwise a new struct is created with the UID set to a blank node i.e.

d := Domain{
		UID:   fmt.Sprintf("_:%s", name),
		Name:  name,
		Created: now,
		Seen: now,
		DgraphType: "Domain",
	}

d := NSSet{
		UID:   fmt.Sprintf("_:%s", hash),
		Created: now,
		Seen: now,
		Hash: hash,
		DgraphType: "NSSet",
	}

The code queries for all nodes, creates blank nodes for nodes which don’t exist and does updates before finally committing at the end of the transaction. It doesn’t use upset blocks with CommitNow enabled on the mutation when it creates a new node.

Schema for these predicates

<hash>: string @index(hash) @upsert .
<name>: string @index(hash, trigram) @upsert .

I changed the second process, so it only inserts the following domain and name server repeatedly.
[ns1.fabulous[.]com ns2.fabulous[.]com] } 0--0--0[.]net

The other process continues to insert/update domains and name servers from the list, which are all guaranteed to be different. However, the process still throws the “Transaction has been aborted. Please retry” error. This shouldn’t be happening as the blank nodes are different.

Does I need to use the upset block when the @upsert directive is enabled on a predicate? So for example, I can’t use blank nodes if @upsert is enabled?

Any idea what is going wrong?

It would be much easier to debug if the transaction error explain why the transaction was aborted!

I’ve added [.] to the domains as the forum is complaining about new users and 2 links.

Thanks

IMO, you can probably do without using the @upsert directive in the schema, as you are implementing your own solution to check if a node exists, and you probably don’t need any other conflict detection mechanism.

I tried removing @upsert but got duplicates.

How do I write the query part of the upsert?

query := fmt.Sprintf("query(func: eq(hash, %s) { uid }", n.Hash)

I’m adding a function to use upserts when creating the nodes.

The above query throws this error

rpc error: code = Unknown desc = while lexing query(func: eq(hash, df79483ecba119d528470ce3e9a2ebb5942b48f8239810925c10a164c69cff14) { uid } at line 1 column 87: Unrecognized character inside a func: U+007B '{'

I’m trying to get the query to return the nodes UID if the hash exists, so the upsert creates a new node if that hash doesn’t exist.

You are missing an closing bracket. It should be as below: Could you please give this a try?
query := fmt.Sprintf(“query(func: eq(hash, %s) ) { uid }”, n.Hash)

1 Like