diff --git a/src/Chronicle.Integrations.MongoDB/src/Chronicle.Integrations.MongoDB.csproj b/src/Chronicle.Integrations.MongoDB/src/Chronicle.Integrations.MongoDB.csproj
index 8954157..42ad493 100644
--- a/src/Chronicle.Integrations.MongoDB/src/Chronicle.Integrations.MongoDB.csproj
+++ b/src/Chronicle.Integrations.MongoDB/src/Chronicle.Integrations.MongoDB.csproj
@@ -18,9 +18,9 @@
-
-
-
+
+
+
diff --git a/src/Chronicle.Integrations.Redis/src/Chronicle.Integrations.Redis.csproj b/src/Chronicle.Integrations.Redis/src/Chronicle.Integrations.Redis.csproj
index edb2465..4f0b965 100644
--- a/src/Chronicle.Integrations.Redis/src/Chronicle.Integrations.Redis.csproj
+++ b/src/Chronicle.Integrations.Redis/src/Chronicle.Integrations.Redis.csproj
@@ -17,10 +17,10 @@
2.0
-
+
-
-
+
+
diff --git a/src/Chronicle.Integrations.Redis/src/Persistence/RedisSagaLog.cs b/src/Chronicle.Integrations.Redis/src/Persistence/RedisSagaLog.cs
index e0bc763..fc823f4 100644
--- a/src/Chronicle.Integrations.Redis/src/Persistence/RedisSagaLog.cs
+++ b/src/Chronicle.Integrations.Redis/src/Persistence/RedisSagaLog.cs
@@ -31,7 +31,7 @@ public async Task> ReadAsync(SagaId id, Type sagaType)
var sagaLogDatas = new List();
var deserializedSagaLogDatas = new List();
var cachedSagaLogDatas = await cache.GetStringAsync(LogId(id, sagaType));
-
+
if (!string.IsNullOrWhiteSpace(cachedSagaLogDatas))
{
sagaLogDatas = JsonConvert.DeserializeObject>(cachedSagaLogDatas);
@@ -39,7 +39,7 @@ public async Task> ReadAsync(SagaId id, Type sagaType)
{
{
var message = (sld.Message as JObject)?.ToObject(sld.MessageType);
- deserializedSagaLogDatas.Add(new RedisSagaLogData(sld.Id, sld.Type, sld.CreatedAt, message, sld.MessageType));
+ deserializedSagaLogDatas.Add(new RedisSagaLogData { SagaId = sld.Id, Type = sld.Type, CreatedAt = sld.CreatedAt, Message = message, MessageType = sld.MessageType });
}
});
}
@@ -54,7 +54,7 @@ public async Task WriteAsync(ISagaLogData logData)
}
var sagaLogDatas = (await ReadAsync(logData.Id, logData.Type)).ToList();
- var sagaLogData = new RedisSagaLogData(logData.Id, logData.Type, logData.CreatedAt, logData.Message, logData.Message.GetType());
+ var sagaLogData = new RedisSagaLogData { SagaId = logData.Id, Type = logData.Type, CreatedAt = logData.CreatedAt, Message = logData.Message, MessageType = logData.Message.GetType() };
sagaLogDatas.Add(sagaLogData);
diff --git a/src/Chronicle.Integrations.Redis/src/Persistence/RedisSagaLogData.cs b/src/Chronicle.Integrations.Redis/src/Persistence/RedisSagaLogData.cs
index ac4901e..d88b86c 100644
--- a/src/Chronicle.Integrations.Redis/src/Persistence/RedisSagaLogData.cs
+++ b/src/Chronicle.Integrations.Redis/src/Persistence/RedisSagaLogData.cs
@@ -5,23 +5,13 @@ namespace Chronicle.Integrations.Redis.Persistence
{
internal sealed class RedisSagaLogData : ISagaLogData
{
- public SagaId Id { get; }
- public Type Type { get; }
- public long CreatedAt { get; }
- public object Message { get; }
- public Type MessageType { get; }
+ public string SagaId { get; set; }
+ [JsonIgnore]
+ public SagaId Id => SagaId;
+ public Type Type { get; set; }
+ public long CreatedAt { get; set; }
+ public object Message { get; set; }
+ public Type MessageType { get; set; }
- [JsonConstructor]
- public RedisSagaLogData(SagaId id, Type type, long createdAt, object message, Type messageType)
- {
- Id = id;
- Type = type;
- CreatedAt = createdAt;
- Message = message;
- MessageType = messageType;
- }
-
- public static ISagaLogData Create(SagaId sagaId, Type sagaType, object message)
- => new RedisSagaLogData(sagaId, sagaType, DateTimeOffset.Now.ToUnixTimeMilliseconds(), message, message.GetType());
}
}
\ No newline at end of file
diff --git a/src/Chronicle.Integrations.Redis/src/Persistence/RedisSagaState.cs b/src/Chronicle.Integrations.Redis/src/Persistence/RedisSagaState.cs
index 94af561..5e12f93 100644
--- a/src/Chronicle.Integrations.Redis/src/Persistence/RedisSagaState.cs
+++ b/src/Chronicle.Integrations.Redis/src/Persistence/RedisSagaState.cs
@@ -5,18 +5,13 @@ namespace Chronicle.Integrations.Redis.Persistence
{
internal sealed class RedisSagaState : ISagaState
{
- public SagaId Id { get; }
- public Type Type { get; }
- public SagaStates State { get; private set; }
- public object Data { get; private set; }
- public Type DataType { get; }
-
- [JsonConstructor]
- public RedisSagaState(SagaId id, Type type, SagaStates state, object data = null, Type dataType = null)
- => (Id, Type, State, Data, DataType) = (id, type, state, data, dataType);
-
- public static ISagaState Create(SagaId sagaId, Type sagaType, SagaStates state, object data = null, Type dataType = null)
- => new RedisSagaState(sagaId, sagaType, state, data, dataType);
+ public string SagaId { get; set; }
+ [JsonIgnore]
+ public SagaId Id => SagaId;
+ public Type Type { get; set; }
+ public SagaStates State { get; set; }
+ public object Data { get; set; }
+ public Type DataType { get; set; }
public void Update(SagaStates state, object data = null)
{
diff --git a/src/Chronicle.Integrations.Redis/src/Persistence/RedisSagaStateRepository.cs b/src/Chronicle.Integrations.Redis/src/Persistence/RedisSagaStateRepository.cs
index 9df3d68..5282f28 100644
--- a/src/Chronicle.Integrations.Redis/src/Persistence/RedisSagaStateRepository.cs
+++ b/src/Chronicle.Integrations.Redis/src/Persistence/RedisSagaStateRepository.cs
@@ -12,7 +12,7 @@ internal sealed class RedisSagaStateRepository : ISagaStateRepository
public RedisSagaStateRepository(IDistributedCache cache)
=> _cache = cache;
-
+
public async Task ReadAsync(SagaId sagaId, Type sagaType)
{
if (string.IsNullOrWhiteSpace(sagaId))
@@ -26,7 +26,7 @@ public async Task ReadAsync(SagaId sagaId, Type sagaType)
RedisSagaState state = null;
var cachedSagaState = await _cache.GetStringAsync(StateId(sagaId, sagaType));
-
+
if (!string.IsNullOrWhiteSpace(cachedSagaState))
{
state = JsonConvert.DeserializeObject(cachedSagaState);
@@ -42,8 +42,7 @@ public async Task WriteAsync(ISagaState state)
throw new ChronicleException($"{nameof(state)} was null.");
}
- var sagaState = new RedisSagaState(state.Id, state.Type, state.State, state.Data, state.Data.GetType());
-
+ var sagaState = new RedisSagaState { SagaId = state.Id, Type = state.Type, State = state.State, Data = state.Data, DataType = state.Data.GetType() };
var serializedSagaState = JsonConvert.SerializeObject(sagaState);
await _cache.SetStringAsync(StateId(state.Id, state.Type), serializedSagaState);
diff --git a/src/Chronicle.Tests/Chronicle.Tests.csproj b/src/Chronicle.Tests/Chronicle.Tests.csproj
index 039cdd3..ed48e16 100644
--- a/src/Chronicle.Tests/Chronicle.Tests.csproj
+++ b/src/Chronicle.Tests/Chronicle.Tests.csproj
@@ -6,11 +6,14 @@
-
-
-
-
-
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
diff --git a/src/Chronicle.sln b/src/Chronicle.sln
index a10f270..23fb6de 100644
--- a/src/Chronicle.sln
+++ b/src/Chronicle.sln
@@ -11,6 +11,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Chronicle.Tests", "Chronicl
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Chronicle.Integrations.MongoDB", "Chronicle.Integrations.MongoDB\src\Chronicle.Integrations.MongoDB.csproj", "{DFB344D1-3121-43F9-9E66-20BC6B0DD9CC}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Chronicle.Integrations.Redis", "Chronicle.Integrations.Redis", "{3B661443-315C-4A0F-A67E-62A792AF35D3}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Chronicle.Integrations.Redis", "Chronicle.Integrations.Redis\src\Chronicle.Integrations.Redis.csproj", "{755F7A4D-7FC3-444E-86D3-528787961B2F}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -69,6 +73,18 @@ Global
{DFB344D1-3121-43F9-9E66-20BC6B0DD9CC}.Release|x64.Build.0 = Release|Any CPU
{DFB344D1-3121-43F9-9E66-20BC6B0DD9CC}.Release|x86.ActiveCfg = Release|Any CPU
{DFB344D1-3121-43F9-9E66-20BC6B0DD9CC}.Release|x86.Build.0 = Release|Any CPU
+ {755F7A4D-7FC3-444E-86D3-528787961B2F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {755F7A4D-7FC3-444E-86D3-528787961B2F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {755F7A4D-7FC3-444E-86D3-528787961B2F}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {755F7A4D-7FC3-444E-86D3-528787961B2F}.Debug|x64.Build.0 = Debug|Any CPU
+ {755F7A4D-7FC3-444E-86D3-528787961B2F}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {755F7A4D-7FC3-444E-86D3-528787961B2F}.Debug|x86.Build.0 = Debug|Any CPU
+ {755F7A4D-7FC3-444E-86D3-528787961B2F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {755F7A4D-7FC3-444E-86D3-528787961B2F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {755F7A4D-7FC3-444E-86D3-528787961B2F}.Release|x64.ActiveCfg = Release|Any CPU
+ {755F7A4D-7FC3-444E-86D3-528787961B2F}.Release|x64.Build.0 = Release|Any CPU
+ {755F7A4D-7FC3-444E-86D3-528787961B2F}.Release|x86.ActiveCfg = Release|Any CPU
+ {755F7A4D-7FC3-444E-86D3-528787961B2F}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -76,4 +92,7 @@ Global
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {F6DDA96B-847E-4F6D-86EC-126800155219}
EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {755F7A4D-7FC3-444E-86D3-528787961B2F} = {3B661443-315C-4A0F-A67E-62A792AF35D3}
+ EndGlobalSection
EndGlobal
diff --git a/src/Chronicle/Builders/ChronicleBuilder.cs b/src/Chronicle/Builders/ChronicleBuilder.cs
index 5a4e614..3041cc5 100644
--- a/src/Chronicle/Builders/ChronicleBuilder.cs
+++ b/src/Chronicle/Builders/ChronicleBuilder.cs
@@ -28,5 +28,15 @@ public IChronicleBuilder UseSagaStateRepository() where TRepository
Services.AddTransient(typeof(ISagaStateRepository), typeof(TRepository));
return this;
}
+
+ public IChronicleBuilder UseChronicleConfiguration(IChronicleConfiguration configuration)
+ {
+ if (configuration is null)
+ {
+ configuration = new ChronicleConfiguration();
+ }
+ Services.AddSingleton(configuration);
+ return this;
+ }
}
}
diff --git a/src/Chronicle/Chronicle.csproj b/src/Chronicle/Chronicle.csproj
index aa237dc..1142558 100644
--- a/src/Chronicle/Chronicle.csproj
+++ b/src/Chronicle/Chronicle.csproj
@@ -19,8 +19,8 @@
-
-
+
+
diff --git a/src/Chronicle/ChronicleConfiguration.cs b/src/Chronicle/ChronicleConfiguration.cs
new file mode 100644
index 0000000..7a03673
--- /dev/null
+++ b/src/Chronicle/ChronicleConfiguration.cs
@@ -0,0 +1,8 @@
+namespace Chronicle
+{
+
+ public class ChronicleConfiguration : IChronicleConfiguration
+ {
+ public bool AllowConcurrentWrites { get; set; } = true;
+ }
+}
\ No newline at end of file
diff --git a/src/Chronicle/Extensions.cs b/src/Chronicle/Extensions.cs
index e6b6ba8..f5afe5e 100644
--- a/src/Chronicle/Extensions.cs
+++ b/src/Chronicle/Extensions.cs
@@ -17,6 +17,7 @@ public static IServiceCollection AddChronicle(this IServiceCollection services,
services.AddTransient();
services.AddTransient();
services.AddTransient();
+ services.AddSingleton();
var chronicleBuilder = new ChronicleBuilder(services);
diff --git a/src/Chronicle/IChronicleBuilder.cs b/src/Chronicle/IChronicleBuilder.cs
index c24b649..aa130fe 100644
--- a/src/Chronicle/IChronicleBuilder.cs
+++ b/src/Chronicle/IChronicleBuilder.cs
@@ -8,5 +8,6 @@ public interface IChronicleBuilder
IChronicleBuilder UseInMemoryPersistence();
IChronicleBuilder UseSagaLog() where TSagaLog : ISagaLog;
IChronicleBuilder UseSagaStateRepository() where TRepository : ISagaStateRepository;
+ IChronicleBuilder UseChronicleConfiguration(IChronicleConfiguration configuration);
}
}
diff --git a/src/Chronicle/IChronicleConfiguration.cs b/src/Chronicle/IChronicleConfiguration.cs
new file mode 100644
index 0000000..aadfce9
--- /dev/null
+++ b/src/Chronicle/IChronicleConfiguration.cs
@@ -0,0 +1,7 @@
+namespace Chronicle
+{
+ public interface IChronicleConfiguration
+ {
+ bool AllowConcurrentWrites { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Chronicle/Managers/SagaCoordinator.cs b/src/Chronicle/Managers/SagaCoordinator.cs
index 9e877b8..a9bef2a 100644
--- a/src/Chronicle/Managers/SagaCoordinator.cs
+++ b/src/Chronicle/Managers/SagaCoordinator.cs
@@ -53,7 +53,7 @@ private async Task ProcessAsync(TMessage message, ISagaAction(TMessage message, ISaga saga, ISaga
state.Update(saga.State, updatedSagaData);
var logData = SagaLogData.Create(saga.Id, sagaType, message);
- var persistenceTasks = new []
+ if (_configuration.AllowConcurrentWrites)
{
- _repository.WriteAsync(state),
- _log.WriteAsync(logData)
- };
+ var persistenceTasks = new[]
+ {
+ _repository.WriteAsync(state),
+ _log.WriteAsync(logData)
+ };
- await Task.WhenAll(persistenceTasks).ConfigureAwait(false);
+ await Task.WhenAll(persistenceTasks).ConfigureAwait(false);
+ }
+ else
+ {
+ await _repository.WriteAsync(state);
+ await _log.WriteAsync(logData);
+ }
}
}
}