Skip to content

Commit 006391e

Browse files
feat: allow synchronous mode to be specified for non-test mode
important for void transactions if you immediately want the current state
1 parent 449ebc9 commit 006391e

File tree

3 files changed

+50
-48
lines changed

3 files changed

+50
-48
lines changed

src/EntityDb.Common/Transactions/SnapshottingTransactionSubscriber.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,16 @@
88

99
namespace EntityDb.Common.Transactions
1010
{
11-
internal class SnapshottingTransactionSubscriber<TEntity> : AsyncTransactionSubscriber<TEntity>
11+
internal class SnapshottingTransactionSubscriber<TEntity> : TransactionSubscriber<TEntity>
1212
{
1313
private readonly ISnapshotRepositoryFactory<TEntity> _snapshotRepositoryFactory;
1414
private readonly ISnapshotSessionOptions _snapshotSessionOptions = new SnapshotSessionOptions();
1515

1616
public SnapshottingTransactionSubscriber
1717
(
1818
ISnapshotRepositoryFactory<TEntity> snapshotRepositoryFactory,
19-
bool testMode
20-
) : base(testMode)
19+
bool synchronous
20+
) : base(synchronous)
2121
{
2222
_snapshotRepositoryFactory = snapshotRepositoryFactory;
2323
}
@@ -39,10 +39,10 @@ protected override async Task NotifyAsync(ITransaction<TEntity> transaction)
3939
}
4040
}
4141

42-
public static SnapshottingTransactionSubscriber<TEntity> Create(IServiceProvider serviceProvider, bool testMode)
42+
public static SnapshottingTransactionSubscriber<TEntity> Create(IServiceProvider serviceProvider, bool synchronousMode)
4343
{
4444
return ActivatorUtilities.CreateInstance<SnapshottingTransactionSubscriber<TEntity>>(serviceProvider,
45-
testMode);
45+
synchronousMode);
4646
}
4747
}
4848
}

src/EntityDb.Common/Transactions/AsyncTransactionSubscriber.cs renamed to src/EntityDb.Common/Transactions/TransactionSubscriber.cs

Lines changed: 38 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,38 @@
1-
using EntityDb.Abstractions.Transactions;
2-
using System.Threading.Tasks;
3-
4-
namespace EntityDb.Common.Transactions
5-
{
6-
/// <summary>
7-
/// Represents an asynchronous subscription to transactions.
8-
/// </summary>
9-
/// <typeparam name="TEntity"></typeparam>
10-
public abstract class AsyncTransactionSubscriber<TEntity> : ITransactionSubscriber<TEntity>
11-
{
12-
private readonly bool _testMode;
13-
14-
/// <summary>
15-
/// Constructs a new instance of <see cref="AsyncTransactionSubscriber{TEntity}" />.
16-
/// </summary>
17-
/// <param name="testMode">If <c>true</c> then the task will be synchronously awaited before returning.</param>
18-
protected AsyncTransactionSubscriber(bool testMode)
19-
{
20-
_testMode = testMode;
21-
}
22-
23-
/// <inheritdoc cref="ITransactionSubscriber{TEntity}.Notify(ITransaction{TEntity})" />
24-
public void Notify(ITransaction<TEntity> transaction)
25-
{
26-
var task = Task.Run(() => NotifyAsync(transaction));
27-
28-
if (_testMode)
29-
{
30-
task.Wait();
31-
}
32-
}
33-
34-
/// <inheritdoc cref="ITransactionSubscriber{TEntity}.Notify(ITransaction{TEntity})"/>
35-
/// <returns>A task that handles notification asynchronously.</returns>
36-
protected abstract Task NotifyAsync(ITransaction<TEntity> transaction);
37-
}
38-
}
1+
using EntityDb.Abstractions.Transactions;
2+
using System.Threading.Tasks;
3+
4+
namespace EntityDb.Common.Transactions
5+
{
6+
/// <summary>
7+
/// Represents an asynchronous subscription to transactions.
8+
/// </summary>
9+
/// <typeparam name="TEntity"></typeparam>
10+
public abstract class TransactionSubscriber<TEntity> : ITransactionSubscriber<TEntity>
11+
{
12+
private readonly bool _synchronousMode;
13+
14+
/// <summary>
15+
/// Constructs a new instance of <see cref="TransactionSubscriber{TEntity}" />.
16+
/// </summary>
17+
/// <param name="synchronousMode">If <c>true</c> then the task will be synchronously awaited before returning.</param>
18+
protected TransactionSubscriber(bool synchronousMode)
19+
{
20+
_synchronousMode = synchronousMode;
21+
}
22+
23+
/// <inheritdoc cref="ITransactionSubscriber{TEntity}.Notify(ITransaction{TEntity})" />
24+
public void Notify(ITransaction<TEntity> transaction)
25+
{
26+
var task = Task.Run(async () => await NotifyAsync(transaction).ConfigureAwait(false));
27+
28+
if (_synchronousMode)
29+
{
30+
task.Wait();
31+
}
32+
}
33+
34+
/// <inheritdoc cref="ITransactionSubscriber{TEntity}.Notify(ITransaction{TEntity})"/>
35+
/// <returns>A task that handles notification asynchronously.</returns>
36+
protected abstract Task NotifyAsync(ITransaction<TEntity> transaction);
37+
}
38+
}

src/EntityDb.Redis/Extensions/IServiceCollectionExtensions.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,19 @@ public static class IServiceCollectionExtensions
2222
/// <param name="serviceCollection">The service collection.</param>
2323
/// <param name="keyNamespace">The namespace used to build a Redis key.</param>
2424
/// <param name="getConnectionString">A function that retrieves the Redis connection string.</param>
25+
/// <param name="synchronousMode">If <c>true</c> then snapshots will be synchronously recorded.</param>
2526
/// <remarks>
2627
/// The production-ready implementation will store snapshots as they come in. If you need write an integration test,
2728
/// consider using
28-
/// <see cref="AddTestModeRedisSnapshots{TEntity}(IServiceCollection, string, Func{IConfiguration, string})" />
29+
/// <see cref="AddTestModeRedisSnapshots{TEntity}(IServiceCollection, string, Func{IConfiguration, string}, bool)" />
2930
/// instead.
3031
/// </remarks>
3132
[ExcludeFromCodeCoverage(Justification = "Tests use TestMode.")]
3233
public static void AddRedisSnapshots<TEntity>(this IServiceCollection serviceCollection, string keyNamespace,
33-
Func<IConfiguration, string> getConnectionString)
34+
Func<IConfiguration, string> getConnectionString, bool synchronousMode = false)
3435
{
3536
serviceCollection.AddSingleton<ITransactionSubscriber<TEntity>>(serviceProvider =>
36-
SnapshottingTransactionSubscriber<TEntity>.Create(serviceProvider, false));
37+
SnapshottingTransactionSubscriber<TEntity>.Create(serviceProvider, synchronousMode));
3738

3839
serviceCollection.AddSingleton<ISnapshotRepositoryFactory<TEntity>>(serviceProvider =>
3940
{
@@ -55,15 +56,16 @@ public static void AddRedisSnapshots<TEntity>(this IServiceCollection serviceCol
5556
/// <param name="serviceCollection">The service collection.</param>
5657
/// <param name="keyNamespace">The namespace used to build a Redis key.</param>
5758
/// <param name="getConnectionString">A function that retrieves the Redis connection string.</param>
59+
/// <param name="synchronousMode">If <c>true</c> then snapshots will be synchronously recorded.</param>
5860
/// <remarks>
5961
/// The test-mode implementation will store snapshots as they come in, but the snapshots will be automatically removed
6062
/// when the repository is disposed.
6163
/// </remarks>
6264
public static void AddTestModeRedisSnapshots<TEntity>(this IServiceCollection serviceCollection,
63-
string keyNamespace, Func<IConfiguration, string> getConnectionString)
65+
string keyNamespace, Func<IConfiguration, string> getConnectionString, bool synchronousMode = true)
6466
{
6567
serviceCollection.AddSingleton<ITransactionSubscriber<TEntity>>(serviceProvider =>
66-
SnapshottingTransactionSubscriber<TEntity>.Create(serviceProvider, true));
68+
SnapshottingTransactionSubscriber<TEntity>.Create(serviceProvider, synchronousMode));
6769

6870
serviceCollection.AddSingleton<ISnapshotRepositoryFactory<TEntity>>(serviceProvider =>
6971
{

0 commit comments

Comments
 (0)