You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
It is very important that the application ensures that only one of these is created per cluster, as it performs automated background clean-up processes that should not be duplicated.
Replacing a document requires awaiting a `TransactionGetResult` returned from `ctx.GetAsync()`, `ctx.InsertAsync()`, or another `ctx.ReplaceAsync()` call first.
@@ -166,9 +146,14 @@ As with replaces, removing a document requires awaiting a `TransactionGetResult`
@@ -342,30 +347,11 @@ After a transaction is rolled back, it cannot be committed, no further operation
342
347
343
348
344
349
// Error Handling
345
-
// tag::error[]
346
-
== Error Handling
347
-
348
-
As discussed previously, the transactions library will attempt to resolve many errors itself, through a combination of retrying individual operations and the application's lambda.
349
-
This includes some transient server errors, and conflicts with other transactions.
350
-
351
-
But there are situations that cannot be resolved, and total failure is indicated to the application via exceptions.
352
-
These errors include:
353
-
354
-
* Any exception thrown by your transaction lambda, either deliberately or through an application logic bug.
355
-
* Attempting to insert a document that already exists.
356
-
* Attempting to remove or replace a document that does not exist.
357
-
* Calling `ctx.GetAsync()` on a document key that does not exist.
358
-
359
-
IMPORTANT: Once one of these errors occurs, the current attempt is irrevocably failed (though the transaction may retry the lambda).
360
-
It is not possible for the application to catch the failure and continue.
361
-
Once a failure has occurred, all other operations tried in this attempt (including commit) will instantly fail.
Transactions, as they are multi-stage and multi-document, also have a concept of partial success/failure.
364
-
This is signalled to the application through the `TransactionResult.UnstagingComplete` property, described later.
365
-
366
-
There are three exceptions that the transactions library can raise to the application: `TransactionFailed`, `TransactionExpired`, and `TransactionCommitAmbiguous`.
367
-
All exceptions derive from `TransactionFailed` for backwards-compatibility purposes.
368
-
// end::error[]
352
+
There are three exceptions that Couchbase transactions can raise to the application:
353
+
`TransactionFailedException`, `TransactionExpiredException` and `TransactionCommitAmbiguousException`.
354
+
All exceptions derive from `TransactionFailedException` for backwards-compatibility purposes.
This will allow the protocol more time to get past any transient failures (for example, those caused by a cluster rebalance).
380
-
The tradeoff to consider with longer expiration times, is that documents that have been staged by a transaction are effectively locked from modification from other transactions, until the expiration time has exceeded.
381
-
382
-
Note that expiration is not guaranteed to be followed precisely.
383
-
For example, if the application were to do a long blocking operation inside the lambda (which should be avoided), then expiration can only trigger after this finishes.
384
-
Similarly, if the transaction attempts a key-value operation close to the expiration time, and that key-value operation times out, then the expiration time may be exceeded.
385
-
386
-
=== TransactionCommitAmbiguous
387
-
388
-
As discussed <<mechanics,previously>>, each transaction has a 'single point of truth' that is updated atomically to reflect whether it is committed.
389
-
390
-
However, it is not always possible for the protocol to become 100% certain that the operation was successful, before the transaction expires.
391
-
That is, the operation may have successfully completed on the cluster, or may succeed soon, but the protocol is unable to determine this (whether due to transient network failure or other reason).
392
-
This is important as the transaction may or may not have reached the commit point, e.g. succeeded or failed.
393
-
394
-
The library raises `TransactionCommitAmbiguous` to indicate this state.
If the transaction had in fact successfully reached the commit point, then the transaction will be fully completed ("unstaged") by the asynchronous cleanup process at some point in the future.
398
-
With default settings this will usually be within a minute, but whatever underlying fault has caused the TransactionCommitAmbiguous may lead to it taking longer.
366
+
Similar to `TransactionResult`, `SingleQueryTransactionResult` also has an `UnstagingComplete` property.
399
367
400
-
If the transaction had not in fact reached the commit point, then the asynchronous cleanup process will instead attempt to roll it back at some point in the future.
401
-
If unable to, any staged metadata from the transaction will not be visible, and will not cause problems (e.g. there are safety mechanisms to ensure it will not block writes to these documents for long).
402
-
403
-
==== Handling
404
-
This error can be challenging for an application to handle.
405
-
As with `TransactionFailed` it is recommended that it at least writes any logs from the transaction, for future debugging.
406
-
It may wish to retry the transaction at a later point, or globally extend transactional expiration times to give the protocol additional time to resolve the ambiguity.
407
-
408
-
=== TransactionResult.UnstagingComplete
409
-
410
-
As above, there is a 'single point of truth' for a transaction.
411
-
After this atomic commit point is reached, the documents themselves will still be individually committed (we also call this "unstaging").
412
-
However, transactionally-aware actors will now be returning the post-transaction versions of the documents, and the transaction is effectively fully committed to those actors.
413
-
414
-
So if the application is solely working with transaction-aware actors, then the unstaging process is optional.
415
-
And failures during the unstaging process are not particularly important, in this case.
416
-
(Note the asynchronous cleanup process will still complete the unstaging process at a later point.)
417
-
418
-
Hence, many errors during unstaging will cause the transaction to immediately return success.
419
-
That is, successful return simply means that the commit point was reached.
420
-
421
-
The property `TransactionResult.UnstagingComplete` indicates whether the unstaging process completed successfully or not.
422
-
This should be used any time that the application needs all results of the transaction to be immediately available to non-transactional actors (which currently includes N1QL and non-transactional Key-Value reads).
423
-
424
-
Error handling differs depending on whether a transaction is before or after the point of commit (or rollback).
425
-
// end::txnfailed1[]
426
-
427
-
428
-
== Full Error Handling Example
368
+
=== Full Error Handling Example
429
369
430
370
Pulling all of the above together, this is the suggested best practice for error handling:
|`CleanupWindow`|60 seconds|This determines how long a cleanup 'run' is; that is, how frequently this client will check its subset of ATR documents. It is perfectly valid for the application to change this setting, which is at a conservative default. Decreasing this will cause expiration transactions to be found more swiftly (generally, within this cleanup window), with the tradeoff of increasing the number of reads per second used for the scanning process.
390
+
|`CleanupLostAttempts`|true|This is the thread that takes part in the distributed cleanup process described above, that cleans up expired transactions created by any client. It is strongly recommended that it is left enabled.
391
+
|`CleanupClientAttempts`|true|This thread is for cleaning up transactions created just by this client. The client will preferentially aim to send any transactions it creates to this thread, leaving transactions for the distributed cleanup process only when it is forced to (for example, on an application crash). It is strongly recommended that it is left enabled.
* There’s plenty of explanation about how Transactions work in Couchbase in our xref:{version-server}@server:learn:data/transactions.adoc[Transactions documentation].
455
+
* There's plenty of explanation about how Transactions work in Couchbase in our xref:{version-server}@server:learn:data/transactions.adoc[Transactions documentation].
503
456
* You can find further code examples on our https://github.com/couchbaselabs/couchbase-transactions-dotnet-examples[transactions examples repository].
0 commit comments