Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Orleans.Concurrency;
using Orleans.Transactions.Abstractions;
using Orleans.Transactions.TestKit.Correctnesss;

Expand Down Expand Up @@ -36,5 +37,9 @@ public interface ITransactionCoordinatorGrain : IGrainWithGuidKey

[Transaction(TransactionOption.Create)]
Task MultiGrainAdd(ITransactionCommitterTestGrain committer, ITransactionCommitOperation<IRemoteCommitService> operation, List<ITransactionTestGrain> grains, int numberToAdd);

[Transaction(TransactionOption.Create)]
[ReadOnly]
Task UpdateViolated(ITransactionTestGrain grains, int numberToAdd);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ public Task MultiGrainAdd(ITransactionCommitterTestGrain committer, ITransaction
return Task.WhenAll(tasks);
}

public Task UpdateViolated(ITransactionTestGrain grain, int numberToAdd)
{
return grain.Add(numberToAdd);
}

private async Task Double(ITransactionTestGrain grain)
{
int[] values = await grain.Get();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,27 @@ await TestAfterDustSettles(async () =>
});
}

public virtual async Task AbortTransactionOnReadOnlyViolatedException(string grainStates)
{
const int expected = 5;

ITransactionTestGrain grain = RandomTestGrain(grainStates);
ITransactionCoordinatorGrain coordinator = this.grainFactory.GetGrain<ITransactionCoordinatorGrain>(Guid.NewGuid());

await coordinator.MultiGrainSet(new List<ITransactionTestGrain> { grain }, expected);
Func<Task> task = () => coordinator.UpdateViolated(grain, expected);
await task.Should().ThrowAsync<OrleansReadOnlyViolatedException>();

await TestAfterDustSettles(async () =>
{
int[] actualValues = await grain.Get();
foreach (var actual in actualValues)
{
actual.Should().Be(expected);
}
});
}

public virtual async Task MultiGrainAbortTransactionOnExceptions(string grainStates)
{
const int grainCount = TransactionTestConstants.MaxCoordinatedTransactions - 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ public override Task AbortTransactionOnExceptions(string grainStates)
return base.AbortTransactionOnExceptions(grainStates);
}

[SkippableTheory]
[InlineData(TransactionTestConstants.SingleStateTransactionalGrain)]
[InlineData(TransactionTestConstants.DoubleStateTransactionalGrain)]
[InlineData(TransactionTestConstants.MaxStateTransactionalGrain)]
public override Task AbortTransactionOnReadOnlyViolatedException(string grainStates)
{
return base.AbortTransactionOnReadOnlyViolatedException(grainStates);
}

[SkippableTheory]
[InlineData(TransactionTestConstants.SingleStateTransactionalGrain)]
[InlineData(TransactionTestConstants.DoubleStateTransactionalGrain)]
Expand Down
2 changes: 1 addition & 1 deletion src/Orleans.Transactions/DistributedTM/TransactionAgent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public Task<TransactionInfo> StartTransaction(bool readOnly, TimeSpan timeout)

LogTraceStartTransaction(new(stopwatch), guid, new(ts));
this.statistics.TrackTransactionStarted();
return Task.FromResult<TransactionInfo>(new TransactionInfo(guid, ts, ts));
return Task.FromResult<TransactionInfo>(new TransactionInfo(guid, ts, ts, readOnly));
}

public async Task<(TransactionalStatus, Exception)> Resolve(TransactionInfo transactionInfo)
Expand Down
8 changes: 4 additions & 4 deletions src/Orleans.Transactions/TransactionAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ async Task IOutgoingGrainCallFilter.Invoke(IOutgoingGrainCallContext context)
}

private TransactionInfo SetTransactionInfo()
{
{
// Clear transaction info if transaction operation requires new transaction.
var transactionInfo = TransactionContext.GetTransactionInfo();

Expand Down Expand Up @@ -180,7 +180,7 @@ public override async ValueTask<Response> Invoke()
var transactionTimeout = Debugger.IsAttached ? TimeSpan.FromMinutes(30) : TimeSpan.FromSeconds(10);

// Start a new transaction
var isReadOnly = (this.Options | InvokeMethodOptions.ReadOnly) == InvokeMethodOptions.ReadOnly;
var isReadOnly = (this.Options & InvokeMethodOptions.ReadOnly) == InvokeMethodOptions.ReadOnly;
transactionInfo = await TransactionAgent.StartTransaction(isReadOnly, transactionTimeout);
startedNewTransaction = true;
}
Expand Down Expand Up @@ -312,7 +312,7 @@ public override void Dispose()
}

[SerializerTransparent]
public abstract class TransactionRequest : TransactionRequestBase
public abstract class TransactionRequest : TransactionRequestBase
{
protected TransactionRequest(Serializer<OrleansTransactionAbortedException> exceptionSerializer, IServiceProvider serviceProvider) : base(exceptionSerializer, serviceProvider)
{
Expand Down Expand Up @@ -482,4 +482,4 @@ private static async ValueTask<Response> CompleteInvokeAsync(Task resultTask)
// Generated
protected abstract Task InvokeInner();
}
}
}