diff --git a/src/Squidex.Infrastructure/Orleans/StateFilter.cs b/src/Squidex.Infrastructure/Orleans/StateFilter.cs new file mode 100644 index 000000000..f946bc7a8 --- /dev/null +++ b/src/Squidex.Infrastructure/Orleans/StateFilter.cs @@ -0,0 +1,29 @@ +// ========================================================================== +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex UG (haftungsbeschraenkt) +// All rights reserved. Licensed under the MIT license. +// ========================================================================== + +using System.Threading.Tasks; +using Orleans; +using Orleans.Storage; +using StateInconsistentStateException = Squidex.Infrastructure.States.InconsistentStateException; + +namespace Squidex.Infrastructure.Orleans +{ + public sealed class StateFilter : IIncomingGrainCallFilter + { + public async Task Invoke(IIncomingGrainCallContext context) + { + try + { + await context.Invoke(); + } + catch (StateInconsistentStateException ex) + { + throw new InconsistentStateException(ex.Message, ex); + } + } + } +} diff --git a/src/Squidex.Infrastructure/States/InconsistentStateException.cs b/src/Squidex.Infrastructure/States/InconsistentStateException.cs index d9091b9dd..ccdd14a08 100644 --- a/src/Squidex.Infrastructure/States/InconsistentStateException.cs +++ b/src/Squidex.Infrastructure/States/InconsistentStateException.cs @@ -26,8 +26,8 @@ namespace Squidex.Infrastructure.States get { return expectedVersion; } } - public InconsistentStateException(long currentVersion, long expectedVersion, Exception ex) - : base(FormatMessage(currentVersion, expectedVersion), ex) + public InconsistentStateException(long currentVersion, long expectedVersion, Exception inner = null) + : base(FormatMessage(currentVersion, expectedVersion), inner) { this.currentVersion = currentVersion; diff --git a/src/Squidex.Infrastructure/States/Persistence{TSnapshot,TKey}.cs b/src/Squidex.Infrastructure/States/Persistence{TSnapshot,TKey}.cs index 0d3264c08..17608e24c 100644 --- a/src/Squidex.Infrastructure/States/Persistence{TSnapshot,TKey}.cs +++ b/src/Squidex.Infrastructure/States/Persistence{TSnapshot,TKey}.cs @@ -77,7 +77,7 @@ namespace Squidex.Infrastructure.States } else { - throw new DomainObjectVersionException(ownerKey.ToString(), ownerType, version, expectedVersion); + throw new InconsistentStateException(version, expectedVersion); } } } @@ -134,14 +134,7 @@ namespace Squidex.Infrastructure.States if (newVersion != versionSnapshot) { - try - { - await snapshotStore.WriteAsync(ownerKey, state, versionSnapshot, newVersion); - } - catch (InconsistentStateException ex) - { - throw new DomainObjectVersionException(ownerKey.ToString(), ownerType, ex.CurrentVersion, ex.ExpectedVersion); - } + await snapshotStore.WriteAsync(ownerKey, state, versionSnapshot, newVersion); versionSnapshot = newVersion; } @@ -175,7 +168,7 @@ namespace Squidex.Infrastructure.States } catch (WrongEventVersionException ex) { - throw new DomainObjectVersionException(ownerKey.ToString(), ownerType, ex.CurrentVersion, ex.ExpectedVersion); + throw new InconsistentStateException(ex.CurrentVersion, ex.ExpectedVersion, ex); } versionEvents += eventArray.Length; diff --git a/src/Squidex/Config/Orleans/OrleansServices.cs b/src/Squidex/Config/Orleans/OrleansServices.cs index 87a852495..a00d44982 100644 --- a/src/Squidex/Config/Orleans/OrleansServices.cs +++ b/src/Squidex/Config/Orleans/OrleansServices.cs @@ -65,6 +65,7 @@ namespace Squidex.Config.Orleans builder.AddIncomingGrainCallFilter(); builder.AddIncomingGrainCallFilter(); builder.AddIncomingGrainCallFilter(); + builder.AddIncomingGrainCallFilter(); var orleansPortSilo = config.GetOptionalValue("orleans:siloPort", 11111); var orleansPortGateway = config.GetOptionalValue("orleans:gatewayPort", 40000); diff --git a/src/Squidex/app/framework/state.ts b/src/Squidex/app/framework/state.ts index be72bfc4a..f74d5197f 100644 --- a/src/Squidex/app/framework/state.ts +++ b/src/Squidex/app/framework/state.ts @@ -167,19 +167,19 @@ export class State { return this.state.value; } - public project(project1: (value: T) => M, compare?: (x: M, y: M) => boolean) { + public project(project: (value: T) => M, compare?: (x: M, y: M) => boolean) { return this.changes.pipe( - map(x => project1(x)), distinctUntilChanged(compare), shareReplay()); + map(x => project(x)), distinctUntilChanged(compare), shareReplay(1)); } public projectFrom(source: Observable, project: (value: M) => N, compare?: (x: N, y: N) => boolean) { return source.pipe( - map(x => project(x)), distinctUntilChanged(compare), shareReplay()); + map(x => project(x)), distinctUntilChanged(compare), shareReplay(1)); } public projectFrom2(lhs: Observable, rhs: Observable, project: (l: M, r: N) => O, compare?: (x: O, y: O) => boolean) { return combineLatest(lhs, rhs, (x, y) => project(x, y)).pipe( - distinctUntilChanged(compare), shareReplay()); + distinctUntilChanged(compare), shareReplay(1)); } constructor(state: Readonly) { diff --git a/tests/Squidex.Infrastructure.Tests/States/PersistenceEventSourcingTests.cs b/tests/Squidex.Infrastructure.Tests/States/PersistenceEventSourcingTests.cs index d82f25ad8..2cddffb8e 100644 --- a/tests/Squidex.Infrastructure.Tests/States/PersistenceEventSourcingTests.cs +++ b/tests/Squidex.Infrastructure.Tests/States/PersistenceEventSourcingTests.cs @@ -145,7 +145,7 @@ namespace Squidex.Infrastructure.States var persistedEvents = new List(); var persistence = sut.WithEventSourcing(None.Type, key, x => persistedEvents.Add(x.Payload)); - await Assert.ThrowsAsync(() => persistence.ReadAsync(1)); + await Assert.ThrowsAsync(() => persistence.ReadAsync(1)); } [Fact] @@ -160,7 +160,7 @@ namespace Squidex.Infrastructure.States var persistedEvents = new List(); var persistence = sut.WithSnapshotsAndEventSourcing(None.Type, key, (int x) => persistedState = x, x => persistedEvents.Add(x.Payload)); - await Assert.ThrowsAsync(() => persistence.ReadAsync(1)); + await Assert.ThrowsAsync(() => persistence.ReadAsync(1)); } [Fact] @@ -209,7 +209,7 @@ namespace Squidex.Infrastructure.States A.CallTo(() => eventStore.AppendAsync(A.Ignored, key, 2, A>.That.Matches(x => x.Count == 1))) .Throws(new WrongEventVersionException(1, 1)); - await Assert.ThrowsAsync(() => persistence.WriteEventAsync(Envelope.Create(new MyEvent()))); + await Assert.ThrowsAsync(() => persistence.WriteEventAsync(Envelope.Create(new MyEvent()))); } [Fact] diff --git a/tests/Squidex.Infrastructure.Tests/States/PersistenceSnapshotTests.cs b/tests/Squidex.Infrastructure.Tests/States/PersistenceSnapshotTests.cs index 0cac6d31f..4dec98730 100644 --- a/tests/Squidex.Infrastructure.Tests/States/PersistenceSnapshotTests.cs +++ b/tests/Squidex.Infrastructure.Tests/States/PersistenceSnapshotTests.cs @@ -98,7 +98,7 @@ namespace Squidex.Infrastructure.States var persistedState = 0; var persistence = sut.WithSnapshots(None.Type, key, (int x) => persistedState = x); - await Assert.ThrowsAsync(() => persistence.ReadAsync(1)); + await Assert.ThrowsAsync(() => persistence.ReadAsync(1)); } [Fact] @@ -122,7 +122,7 @@ namespace Squidex.Infrastructure.States } [Fact] - public async Task Should_wrap_exception_when_writing_to_store_with_previous_version() + public async Task Should_not_wrap_exception_when_writing_to_store_with_previous_version() { A.CallTo(() => snapshotStore.ReadAsync(key)) .Returns((20, 10)); @@ -135,7 +135,7 @@ namespace Squidex.Infrastructure.States await persistence.ReadAsync(); - await Assert.ThrowsAsync(() => persistence.WriteSnapshotAsync(100)); + await Assert.ThrowsAsync(() => persistence.WriteSnapshotAsync(100)); } [Fact]