Open Shishkovskiy opened 1 year ago
Which Transaction exactly do you mean?
The Driver transactions currently represent the state of the transaction on the server, so you can cancel a transaction by not committing it, or throwing an exception if you are using ExecuteRead/ExecuteWrite (previously known as ReadTransaction/WriteTransaction).
That said currently there is not a way to interrupt a query in the driver.
I'm talking about driver transactions, let's imagine I need to insert some data into the database, and I'd like to use transactions for it. Besides that, I'd like to have a chance to cancel that transaction in the middle of the process. For instance, I provide some inserting progress to users, and if it takes more time than they expect, they can cancel the transaction. And my question is, is there any way to have a unique identifier for each transaction and then cancel it using a unique identifier?
Hi @Shishkovskiy sorry about the delay responding, I took some time to have a go at how this might work for an application and got side tracked.
You ideally would wrap your transactions to enable cancellation tokens then register your transactions with with some sort of transaction manager. If you use transaction functions (ExecuteReadAsync, ExecuteWriteAsync) throwing an exception in lambda will cause the transaction to be cancelled.
We won't be adding any functionality for this in the driver currently, though we are trying to increase the surface which is cancellation token friendly.
It would be nice to have the cancellation token that you mention:
CancellationToken token;
...
using Neo4j.Driver.ISession session = Driver.Session();
var rrr = session.ExecuteWrite<(List<IRecord>, IResultSummary)>(tx =>
{
IResult result = tx.Run(cypherSource, parameters, **token**);
var records = result.ToList();
IResultSummary summary = result.Consume();
return (records, summary);
});
where the token is cancelled from some button on the UI. The problem then becomes knowing when to enable and disable that button (as when a transaction is running or not).
Right now, it is a real mess dealing with transactions. I ended up using the cypher "show transactions" and "terminate transaction
Let me add one more context to the ticket: I think the cancellation token is the right approach, since it is idiomatic to C#. However, I wonder if it would be a simple orthogonal fix to simply have a property on the transaction instance that shows the same ID as you get from the SHOW TRANSACTION command? At least it would then be possible to use that ID in a TERMINATE TRANSACTION command. Did I fail to find this?
Hi @pvillads, one way you can achieve that is by attaching metadata to the transaction...
await session.ExecuteReadAsync(async transaction =>
{
... Code here
}, (config) => config.WithMetadata(new Dictionary<string, object>() {{ "myId", "TheId" }}));
and then execute something like this...
SHOW TRANSACTIONS YIELD transactionId AS txId, metaData AS md WHERE md.myId = "TheId"
TERMINATE TRANSACTIONS txId
YIELD message
RETURN txId, message
Only make sure you attach info that can be uniquely identified.
Hope that help!
Cheers!
Is there any chance to have the transaction Id or something like that to cancel it in the middle of the process?