Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updating node locks outgoing relation deletion for APOC but not for normal queries #670

Closed
saadali5997 opened this issue Oct 17, 2024 · 1 comment

Comments

@saadali5997
Copy link

saadali5997 commented Oct 17, 2024

Guidelines

I already posted the question on forums but didn't get any clear response so writing here. I want to understand the behaviour/limitation behind it and if there's some documentation anywhere which explains this behaviour, that would be really nice.

Expected Behavior (Mandatory)

Updating a node should not lock deletion of its edges.
This works (without APOC) and deletes all draft_entities

MATCH (d: Dataset { id: "D1" })
SET d.updatedAt = datetime()
WITH d
OPTIONAL MATCH (d)-[r:ENTITY]->(draft_entities)
DETACH DELETE draft_entities

So the following query should delete all draft_entities along with their relationships

MATCH (d: Dataset { id: "D1" })
SET d.updatedAt = datetime()
WITH d
CALL apoc.periodic.iterate(
    '   WITH $d as d
        OPTIONAL MATCH (d)-[r:ENTITY]->(draft_entities)
        RETURN draft_entities
    ',
    '  
        DETACH DELETE draft_entities // Or we can also just do DELETE r for testing 
    ',
    { batchSize: 100, parallel: false, params: { d: d } }
) YIELD batches AS draft_batches, total AS draft_total
RETURN draft_total

Actual Behavior (Mandatory)

The following query gets stuck and never finishes because we can not delete the edges when a node is edited:

MATCH (d: Dataset { id: "D1" })
SET d.updatedAt = datetime()
WITH d
CALL apoc.periodic.iterate(
    '   WITH $d as d
        OPTIONAL MATCH (d)-[r:ENTITY]->(draft_entities)
        RETURN draft_entities
    ',
    '  
        DETACH DELETE draft_entities // Or we can also just do DELETE r for testing 
    ',
    { batchSize: 100, parallel: false, params: { d: d } }
) YIELD batches AS draft_batches, total AS draft_total
RETURN draft_total

Even if I do the following behaviour is still the same

CALL apoc.cypher.doIt(
  'MATCH (d:Dataset {id: $id})
   SET d.mutationLock__lockedBy = "3a631518-1726-5bde-a537-e9cb1068e2c1", 
       d.mutationLock__expiresAt = $newDatetime, 
       d.updatedAt = datetime()
   RETURN d',
  { id: $id, newDatetime: $newDatetime }
) YIELD value
MATCH (d: Dataset { id: "D1" })
SET d.updatedAt = datetime()
WITH d
CALL apoc.periodic.iterate(
    '   WITH $d as d
        OPTIONAL MATCH (d)-[r:ENTITY]->(draft_entities)
        RETURN draft_entities
    ',
    '  
        DETACH DELETE draft_entities // Or we can also just do DELETE r for testing 
    ',
    { batchSize: 100, parallel: false, params: { d: d } }
) YIELD batches AS draft_batches, total AS draft_total
RETURN draft_total

How to Reproduce the Problem

By running the queries above it can be reproduced.

Simple Dataset (where it's possibile)

CREATE (d:Dataset {id: "D1", name: "Dataset A"})
CREATE (cd1:CompanyDepartment {id: "CD1", name: "Department 1"})
CREATE (cd2:CompanyDepartment {id: "CD2", name: "Department 2"})
CREATE (cd3:CompanyDepartment {id: "CD3", name: "Department 3"})
CREATE (d)-[:ENTITY]->(cd1)
CREATE (d)-[:ENTITY]->(cd2)
CREATE (d)-[:ENTITY]->(cd3)
RETURN d, cd1, cd2, cd3

Screenshots (where it's possibile)

Specifications (Mandatory)

Neo4j 5.23, using through browser.

Currently used versions

Versions

  • OS: Browser UI
  • Neo4j: 5.23.0
  • Neo4j-Apoc: 5.23.0
@loveleif
Copy link
Contributor

Thanks for your report @saadali5997. The issue is that apoc.periodic.iterate runs in inner transactions. When you do SET d.updatedAt = datetime() in the outer transaction that node is locked and the inner transactions will not be able to write to the node. You can rewrite your query to run in a single transaction. Or perform the SET d.updatedAt = datetime() operation separately (since apoc.periodic.iterate commits multiple transactions there is no atomicity anyway so the effect will be the same).

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

No branches or pull requests

2 participants