Browse Source

Additional guard for reentrants

pull/596/head
Sebastian 5 years ago
parent
commit
7cf3328834
  1. 9
      backend/src/Squidex.Infrastructure/EventSourcing/Grains/EventConsumerGrain.cs
  2. 6
      backend/tests/Squidex.Infrastructure.Tests/EventSourcing/Grains/EventConsumerManagerGrainTests.cs

9
backend/src/Squidex.Infrastructure/EventSourcing/Grains/EventConsumerGrain.cs

@ -22,6 +22,7 @@ namespace Squidex.Infrastructure.EventSourcing.Grains
private readonly IEventDataFormatter eventDataFormatter; private readonly IEventDataFormatter eventDataFormatter;
private readonly IEventStore eventStore; private readonly IEventStore eventStore;
private readonly ISemanticLog log; private readonly ISemanticLog log;
private readonly SemaphoreSlim semaphore = new SemaphoreSlim(1);
private TaskScheduler? scheduler; private TaskScheduler? scheduler;
private BatchSubscriber? currentSubscriber; private BatchSubscriber? currentSubscriber;
private IEventConsumer? eventConsumer; private IEventConsumer? eventConsumer;
@ -196,6 +197,9 @@ namespace Squidex.Infrastructure.EventSourcing.Grains
} }
private async Task DoAndUpdateStateAsync(Func<Task> action, [CallerMemberName] string? caller = null) private async Task DoAndUpdateStateAsync(Func<Task> action, [CallerMemberName] string? caller = null)
{
await semaphore.WaitAsync();
try
{ {
var previousState = State; var previousState = State;
@ -227,6 +231,11 @@ namespace Squidex.Infrastructure.EventSourcing.Grains
await state.WriteAsync(); await state.WriteAsync();
} }
} }
finally
{
semaphore.Release();
}
}
private async Task ClearAsync() private async Task ClearAsync()
{ {

6
backend/tests/Squidex.Infrastructure.Tests/EventSourcing/Grains/EventConsumerManagerGrainTests.cs

@ -166,12 +166,10 @@ namespace Squidex.Infrastructure.EventSourcing.Grains
public async Task Should_fetch_infos_from_all_grains() public async Task Should_fetch_infos_from_all_grains()
{ {
A.CallTo(() => grainA.GetStateAsync()) A.CallTo(() => grainA.GetStateAsync())
.Returns(new Immutable<EventConsumerInfo>( .Returns(new EventConsumerInfo { Name = "A", Error = "A-Error", IsStopped = false, Position = "123" });
new EventConsumerInfo { Name = "A", Error = "A-Error", IsStopped = false, Position = "123" }));
A.CallTo(() => grainB.GetStateAsync()) A.CallTo(() => grainB.GetStateAsync())
.Returns(new Immutable<EventConsumerInfo>( .Returns( new EventConsumerInfo { Name = "B", Error = "B-Error", IsStopped = false, Position = "456" });
new EventConsumerInfo { Name = "B", Error = "B-Error", IsStopped = false, Position = "456" }));
var infos = await sut.GetConsumersAsync(); var infos = await sut.GetConsumersAsync();

Loading…
Cancel
Save