< Summary - Heimdall API

Information
Class: ArturRios.Heimdall.Data.Persistence.WriteTransactions
Assembly: ArturRios.Heimdall.Data
File(s): /home/ci/agent/workspace/heimdall-api-docs_main/app/src/Infrastructure/ArturRios.Heimdall.Data/Persistence/WriteTransactions.cs
Line coverage
85%
Covered lines: 12
Uncovered lines: 2
Coverable lines: 14
Total lines: 59
Line coverage: 85.7%
Branch coverage
100%
Covered branches: 2
Total branches: 2
Branch coverage: 100%
Method coverage
100%
Covered methods: 5
Fully covered methods: 4
Total methods: 5
Method coverage: 100%
Full method coverage: 80%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
BeginAsync()100%11100%
.ctor(...)100%11100%
CommitAsync()100%11100%
DisposeAsync()100%2275%

File(s)

/home/ci/agent/workspace/heimdall-api-docs_main/app/src/Infrastructure/ArturRios.Heimdall.Data/Persistence/WriteTransactions.cs

#LineLine coverage
 1using ArturRios.Heimdall.Data.Configuration;
 2using ArturRios.Heimdall.Domain.Persistence;
 3using Microsoft.EntityFrameworkCore.Storage;
 4
 5namespace ArturRios.Heimdall.Data.Persistence;
 6
 7/// <summary>
 8///     <see cref="IWriteTransactions" /> on the request's <see cref="AppDbContext" />: a database
 9///     transaction every write made through that context joins until it is committed or disposed.
 10/// </summary>
 11/// <remarks>
 12///     <para>
 13///         The context runs without a retrying execution strategy, so a transaction the caller opens
 14///         is allowed. <see cref="ApplicationCredentialSlots" /> wraps its own in the strategy because
 15///         it owns the whole unit; here the unit is the handler's and cannot be replayed by EF Core.
 16///     </para>
 17///     <para>
 18///         The rollback and the clearing of the change tracker never throw: they run because something
 19///         already failed, and must not replace that failure with their own.
 20///     </para>
 21/// </remarks>
 26922public sealed class WriteTransactions(AppDbContext context) : IWriteTransactions
 23{
 24    public async Task<IWriteTransaction> BeginAsync() =>
 12225        new WriteTransaction(context, await context.Database.BeginTransactionAsync());
 26
 12227    private sealed class WriteTransaction(AppDbContext context, IDbContextTransaction transaction)
 28        : IWriteTransaction
 29    {
 30        private bool _committed;
 31
 32        public async Task CommitAsync()
 33        {
 9234            await transaction.CommitAsync();
 9235            _committed = true;
 9236        }
 37
 38        public async ValueTask DisposeAsync()
 39        {
 12240            if (!_committed)
 41            {
 42                try
 43                {
 3044                    await transaction.RollbackAsync(CancellationToken.None);
 3045                }
 046                catch
 47                {
 48                    // Already rolled back, or the connection is gone; disposing finishes the cleanup.
 049                }
 50
 51                // Nothing the transaction wrote was kept, so nothing the tracker holds about it is true:
 52                // a failed save's entities are still pending, and the next save would replay them.
 3053                context.ChangeTracker.Clear();
 54            }
 55
 12256            await transaction.DisposeAsync();
 12257        }
 58    }
 59}