notdodo
(Notdodo)
March 9, 2022, 8:45am
1
opened 06:25PM - 08 Mar 22 UTC
closed 02:09PM - 15 Mar 22 UTC
Using `tx.Run` inside a `WriteTransaction` to perform a trigger creation with `C… ALL apoc.trigger.add` the parametrized input is not substituted and the server returns "org.neo4j.graphdb.TransactionFailureException"
**Neo4j Version:** 4.4.4 Community
**Neo4j Mode**: Single instance (docker)
**Driver version**: Go driver v4.4.1
**Operating System:** Ubuntu 22.04
<details><summary>**Stacktrace**</summary>
<p>
```
neo4j | org.neo4j.graphdb.TransactionFailureException: Unable to complete transaction.
neo4j | at org.neo4j.fabric.executor.FabricLocalExecutor$LocalTransactionContext.transformTerminalOperationError(FabricLocalExecutor.java:230) ~[neo4j-fabric-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.kernel.impl.coreapi.TransactionImpl.safeTerminalOperation(TransactionImpl.java:709) ~[neo4j-kernel-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.kernel.impl.coreapi.TransactionImpl.rollback(TransactionImpl.java:189) ~[neo4j-kernel-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.kernel.impl.query.Neo4jTransactionalContext.rollback(Neo4jTransactionalContext.java:144) ~[neo4j-kernel-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.cypher.internal.ExecutionEngine.closing(ExecutionEngine.scala:185) ~[neo4j-cypher-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.cypher.internal.ExecutionEngine.executeSubquery(ExecutionEngine.scala:175) ~[neo4j-cypher-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.cypher.internal.ExecutionEngine.execute(ExecutionEngine.scala:125) ~[neo4j-cypher-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.cypher.internal.javacompat.ExecutionEngine.executeQuery(ExecutionEngine.java:127) ~[neo4j-cypher-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.cypher.internal.javacompat.ExecutionEngine.executeQuery(ExecutionEngine.java:115) ~[neo4j-cypher-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.kernel.impl.coreapi.TransactionImpl.execute(TransactionImpl.java:285) ~[neo4j-kernel-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.kernel.impl.coreapi.TransactionImpl.execute(TransactionImpl.java:274) ~[neo4j-kernel-4.4.4.jar:4.4.4]
neo4j | at apoc.trigger.TriggerHandler.lambda$executeTriggers$14(TriggerHandler.java:266) ~[apoc.jar:4.4.0.3]
neo4j | at java.util.concurrent.ConcurrentHashMap.forEach(ConcurrentHashMap.java:1603) ~[?:?]
neo4j | at apoc.trigger.TriggerHandler.executeTriggers(TriggerHandler.java:257) ~[apoc.jar:4.4.0.3]
neo4j | at apoc.trigger.TriggerHandler.executeTriggers(TriggerHandler.java:252) ~[apoc.jar:4.4.0.3]
neo4j | at apoc.trigger.TriggerHandler.beforeCommit(TriggerHandler.java:209) ~[apoc.jar:4.4.0.3]
neo4j | at apoc.trigger.TriggerHandler.beforeCommit(TriggerHandler.java:40) ~[apoc.jar:4.4.0.3]
neo4j | at org.neo4j.kernel.internal.event.DatabaseTransactionEventListeners.beforeCommit(DatabaseTransactionEventListeners.java:101) ~[neo4j-kernel-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.kernel.impl.api.KernelTransactionImplementation.commitTransaction(KernelTransactionImplementation.java:822) ~[neo4j-kernel-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.kernel.impl.api.KernelTransactionImplementation.closeTransaction(KernelTransactionImplementation.java:732) ~[neo4j-kernel-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.kernel.impl.api.KernelTransactionImplementation.commit(KernelTransactionImplementation.java:703) ~[neo4j-kernel-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.kernel.impl.coreapi.TransactionImpl.lambda$commit$0(TransactionImpl.java:179) ~[neo4j-kernel-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.kernel.impl.coreapi.TransactionImpl.safeTerminalOperation(TransactionImpl.java:700) ~[neo4j-kernel-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.kernel.impl.coreapi.TransactionImpl.commit(TransactionImpl.java:174) ~[neo4j-kernel-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.kernel.impl.coreapi.TransactionImpl.commit(TransactionImpl.java:169) ~[neo4j-kernel-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.fabric.executor.FabricKernelTransaction.commit(FabricKernelTransaction.java:137) ~[neo4j-fabric-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.fabric.executor.FabricLocalExecutor$KernelTxWrapper.doCommit(FabricLocalExecutor.java:262) ~[neo4j-fabric-4.4.4.jar:4.4.4]
neo4j | at reactor.core.publisher.MonoRunnable.call(MonoRunnable.java:73) ~[reactor-core-3.4.11.jar:3.4.11]
neo4j | at reactor.core.publisher.MonoRunnable.call(MonoRunnable.java:32) ~[reactor-core-3.4.11.jar:3.4.11]
neo4j | at reactor.core.publisher.FluxFlatMap.trySubscribeScalarMap(FluxFlatMap.java:127) ~[reactor-core-3.4.11.jar:3.4.11]
neo4j | at reactor.core.publisher.MonoFlatMap.subscribeOrReturn(MonoFlatMap.java:53) ~[reactor-core-3.4.11.jar:3.4.11]
neo4j | at reactor.core.publisher.Mono.subscribe(Mono.java:4384) ~[reactor-core-3.4.11.jar:3.4.11]
neo4j | at reactor.core.publisher.FluxFlatMap$FlatMapMain.onNext(FluxFlatMap.java:426) ~[reactor-core-3.4.11.jar:3.4.11]
neo4j | at reactor.core.publisher.FluxConcatArray$ConcatArraySubscriber.onNext(FluxConcatArray.java:201) ~[reactor-core-3.4.11.jar:3.4.11]
neo4j | at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2398) ~[reactor-core-3.4.11.jar:3.4.11]
neo4j | at reactor.core.publisher.FluxConcatArray$ConcatArraySubscriber.onSubscribe(FluxConcatArray.java:193) ~[reactor-core-3.4.11.jar:3.4.11]
neo4j | at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:55) ~[reactor-core-3.4.11.jar:3.4.11]
neo4j | at reactor.core.publisher.Mono.subscribe(Mono.java:4399) ~[reactor-core-3.4.11.jar:3.4.11]
neo4j | at reactor.core.publisher.FluxConcatArray$ConcatArraySubscriber.onComplete(FluxConcatArray.java:258) ~[reactor-core-3.4.11.jar:3.4.11]
neo4j | at reactor.core.publisher.FluxConcatArray.subscribe(FluxConcatArray.java:78) ~[reactor-core-3.4.11.jar:3.4.11]
neo4j | at reactor.core.publisher.Mono.subscribe(Mono.java:4399) ~[reactor-core-3.4.11.jar:3.4.11]
neo4j | at reactor.core.publisher.Mono.block(Mono.java:1705) ~[reactor-core-3.4.11.jar:3.4.11]
neo4j | at org.neo4j.fabric.transaction.FabricTransactionImpl.doOnChildren(FabricTransactionImpl.java:286) ~[neo4j-fabric-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.fabric.transaction.FabricTransactionImpl.commit(FabricTransactionImpl.java:197) ~[neo4j-fabric-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.fabric.bolt.BoltFabricDatabaseService$BoltTransactionImpl.commit(BoltFabricDatabaseService.java:145) ~[neo4j-fabric-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.bolt.runtime.statemachine.impl.TransactionStateMachine$State.closeTransaction(TransactionStateMachine.java:406) ~[neo4j-bolt-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.bolt.runtime.statemachine.impl.TransactionStateMachine$State$2.commitTransaction(TransactionStateMachine.java:358) ~[neo4j-bolt-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.bolt.runtime.statemachine.impl.TransactionStateMachine.commitTransaction(TransactionStateMachine.java:108) ~[neo4j-bolt-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.bolt.transaction.StatementProcessorTxManager.commit(StatementProcessorTxManager.java:66) ~[neo4j-bolt-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.bolt.v4.runtime.InTransactionState.processCommitMessage(InTransactionState.java:107) ~[neo4j-bolt-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.bolt.v44.runtime.InTransactionState.processCommitMessage(InTransactionState.java:35) ~[neo4j-bolt-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.bolt.v4.runtime.InTransactionState.processUnsafe(InTransactionState.java:56) ~[neo4j-bolt-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.bolt.v3.runtime.FailSafeBoltStateMachineState.process(FailSafeBoltStateMachineState.java:48) ~[neo4j-bolt-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.bolt.runtime.statemachine.impl.AbstractBoltStateMachine.nextState(AbstractBoltStateMachine.java:154) ~[neo4j-bolt-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.bolt.runtime.statemachine.impl.AbstractBoltStateMachine.process(AbstractBoltStateMachine.java:102) ~[neo4j-bolt-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.bolt.messaging.BoltRequestMessageReader.lambda$doRead$1(BoltRequestMessageReader.java:93) ~[neo4j-bolt-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.bolt.runtime.DefaultBoltConnection.lambda$enqueue$0(DefaultBoltConnection.java:156) ~[neo4j-bolt-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.bolt.runtime.DefaultBoltConnection.processNextBatchInternal(DefaultBoltConnection.java:252) ~[neo4j-bolt-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.bolt.runtime.DefaultBoltConnection.processNextBatch(DefaultBoltConnection.java:187) ~[neo4j-bolt-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.bolt.runtime.DefaultBoltConnection.processNextBatch(DefaultBoltConnection.java:177) ~[neo4j-bolt-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.bolt.runtime.scheduling.ExecutorBoltScheduler.executeBatch(ExecutorBoltScheduler.java:257) ~[neo4j-bolt-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.bolt.runtime.scheduling.ExecutorBoltScheduler.lambda$scheduleBatchOrHandleError$3(ExecutorBoltScheduler.java:240) ~[neo4j-bolt-4.4.4.jar:4.4.4]
neo4j | at java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1700) [?:?]
neo4j | at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) [?:?]
neo4j | at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) [?:?]
neo4j | at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) [netty-common-4.1.73.Final.jar:4.1.73.Final]
neo4j | at java.lang.Thread.run(Thread.java:829) [?:?]
neo4j | Caused by: java.lang.IllegalStateException: This transaction is already being closed.
neo4j | at org.neo4j.kernel.impl.api.KernelTransactionImplementation.assertTransactionNotClosing(KernelTransactionImplementation.java:670) ~[neo4j-kernel-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.kernel.impl.api.KernelTransactionImplementation.closeTransaction(KernelTransactionImplementation.java:724) ~[neo4j-kernel-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.kernel.impl.api.KernelTransactionImplementation.rollback(KernelTransactionImplementation.java:717) ~[neo4j-kernel-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.kernel.impl.coreapi.TransactionImpl.lambda$rollback$1(TransactionImpl.java:194) ~[neo4j-kernel-4.4.4.jar:4.4.4]
neo4j | at org.neo4j.kernel.impl.coreapi.TransactionImpl.safeTerminalOperation(TransactionImpl.java:700) ~[neo4j-kernel-4.4.4.jar:4.4.4]
neo4j | ... 65 more
```
</p>
</details>
Example code:
<details><summary>**Docker Compose**</summary>
<p>
```
version: "3"
services:
neo4j:
image: neo4j:latest
hostname: neo4j
container_name: neo4j
ports:
- "7474:7474"
- "7687:7687"
environment:
NEO4JLABS_PLUGINS: '["apoc"]'
NEO4J_AUTH: "neo4j/issue328"
NEO4J_dbms_logs_debug_level: DEBUG
NEO4J_dbms_memory_pagecache_size: 1G
NEO4J_dbms.memory.heap.initial_size: 1G
NEO4J_dbms_memory_heap_max__size: 1G
apoc.trigger.enabled: "true"
```
</p>
</details>
```go
package main
import (
"log"
"github.com/neo4j/neo4j-go-driver/v4/neo4j"
)
func main() {
driver, err := neo4j.NewDriver("neo4j://localhost:7687", neo4j.BasicAuth("neo4j", "issue328", ""))
if err != nil {
log.Fatalln(err)
}
defer driver.Close()
session := driver.NewSession(neo4j.SessionConfig{AccessMode: neo4j.AccessModeWrite})
defer session.Close()
_, err = session.WriteTransaction(func(tx neo4j.Transaction) (interface{}, error) {
// idP is an int64
var result, err = tx.Run(`CALL apoc.trigger.add("create-rel",
"UNWIND $createdNodes as node WITH node
WHERE (node:A)
MATCH (p:P) WHERE id(p) = toInteger($idP)
MERGE (p)-[r:REL]->(node)",
{phase: 'before'})`, map[string]interface{}{"idP": int64(3)})
if err != nil {
log.Fatalln(err)
}
return result.Consume()
})
if err != nil {
log.Fatalln(err)
}
}
```
On Neo4j `CALL apoc.trigger.list()` returns:
![Screenshot_20220308_204217](https://user-images.githubusercontent.com/6991986/157312923-e17ba5b8-ca57-4176-9f38-2d8a551b9e23.png)
I've opened this issue because I think that the Run
function does not perform the parameter substitution but I'm not sure if the code that I wrote is wrong or the problem is in the driver...
@notdodo
As Florent rightly said into the GitHub issue thread,
the $idP
present in the second parameter of apoc.trigger.add
is entirely managed by APOC.
Anyway, luckily is possible to pass a configuration to "transfer" your parameter from go-driver
to apoc, see here in "optional params" section.
That is, you could change your query in this way, by adding {params: {idP: $idP}}
:
CALL apoc.trigger.add("create-rel",
"UNWIND $createdNodes as node WITH node
WHERE (node:A)
MATCH (p:P) WHERE id(p) = toInteger($idP)
MERGE (p)-[r:REL]->(node)",
{phase: 'before'}, {params: {idP: $idP}})
I haven't replicated the problem with Go because I don't know it, but via Neo4j Desktop,
however I believe it should work here too.
notdodo
(Notdodo)
March 16, 2022, 2:40pm
3
Hi @giuseppe_villan .
Thank you for your response and solution; it worked well.
Sorry I've missed the additional params
parameter.