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

Allows use of externally owned transactions for writes #282

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
38 changes: 32 additions & 6 deletions source/Nevermore/Advanced/WriteTransaction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -337,31 +337,57 @@ public async ValueTask<string> AllocateIdAsync(string tableName, string idPrefix
var key = await keyAllocator.NextIdAsync(tableName, cancellationToken).ConfigureAwait(false);
return $"{idPrefix}-{key}";
}

public void CommitIfOwned()
{
if (!OwnsSqlTransaction) return;

if (!configuration.AllowSynchronousOperations)
throw new SynchronousOperationsDisabledException();

CommitTransactionAndRunHooks();
}

public void Commit()
{
if (Transaction is null)
jimmyp marked this conversation as resolved.
Show resolved Hide resolved
throw new InvalidOperationException("There is no current transaction, call Open/OpenAsync to start a transaction");

if (!OwnsSqlTransaction)
throw new InvalidOperationException($"{nameof(WriteTransaction)} cannot commit a transaction it does not own");

if (!configuration.AllowSynchronousOperations)
throw new SynchronousOperationsDisabledException();

CommitTransactionAndRunHooks();
}

void CommitTransactionAndRunHooks()
{
if (Transaction is null)
throw new InvalidOperationException("There is no current transaction, call Open/OpenAsync to start a transaction");

configuration.Hooks.BeforeCommit(this);
Transaction.Commit();
configuration.Hooks.AfterCommit(this);
}

public async Task CommitAsync(CancellationToken cancellationToken = default)
public async Task CommitIfOwnedAsync(CancellationToken cancellationToken = default)
{
if (Transaction is null)
gb-8 marked this conversation as resolved.
Show resolved Hide resolved
throw new InvalidOperationException("There is no current transaction, call Open/OpenAsync to start a transaction");
if (!OwnsSqlTransaction) return;

await CommitTransactionAndRunHooksAsync(cancellationToken).ConfigureAwait(false);
}

public async Task CommitAsync(CancellationToken cancellationToken = default)
{
if (!OwnsSqlTransaction)
throw new InvalidOperationException($"{nameof(WriteTransaction)} cannot commit a transaction it does not own");

await CommitTransactionAndRunHooksAsync(cancellationToken).ConfigureAwait(false);
}
async Task CommitTransactionAndRunHooksAsync(CancellationToken cancellationToken)
{
if (Transaction is null)
throw new InvalidOperationException("There is no current transaction, call Open/OpenAsync to start a transaction");

await configuration.Hooks.BeforeCommitAsync(this).ConfigureAwait(false);
await Transaction.CommitAsync(cancellationToken).ConfigureAwait(false);
await configuration.Hooks.AfterCommitAsync(this).ConfigureAwait(false);
Expand Down
2 changes: 2 additions & 0 deletions source/Nevermore/IWriteTransaction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ namespace Nevermore
{
public interface IWriteTransaction : IReadTransaction, IWriteQueryExecutor
{
void CommitIfOwned();
Task CommitIfOwnedAsync(CancellationToken cancellationToken = default);
Comment on lines +8 to +9
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per the feedback on https://github.com/OctopusDeploy/OctopusDeploy/pull/23120, we'd rather not introduce a different way to commit a Nevermore transaction. Rather, the consumer (Octopus Server) should be aware of whether the SQL transaction is externally owned and simply not call Commit() on the Nevermore transaction in that case. Happy to assist with ways to solve that.

void Commit();
Task CommitAsync(CancellationToken cancellationToken = default);
}
Expand Down