Browse Source

Base class for grains.

pull/342/head
Sebastian 7 years ago
parent
commit
dddd3efe6d
  1. 32
      src/Squidex.Domain.Apps.Entities/Apps/AppUISettingsGrain.cs
  2. 49
      src/Squidex.Domain.Apps.Entities/Apps/Indexes/AppsByNameIndexGrain.cs
  3. 38
      src/Squidex.Domain.Apps.Entities/Apps/Indexes/AppsByUserIndexGrain.cs
  4. 65
      src/Squidex.Domain.Apps.Entities/Backup/BackupGrain.cs
  5. 39
      src/Squidex.Domain.Apps.Entities/Backup/RestoreGrain.cs
  6. 43
      src/Squidex.Domain.Apps.Entities/Rules/Indexes/RulesByAppIndexGrain.cs
  7. 45
      src/Squidex.Domain.Apps.Entities/Schemas/Indexes/SchemasByAppIndexGrain.cs
  8. 51
      src/Squidex.Domain.Apps.Entities/Tags/TagGrain.cs
  9. 2
      src/Squidex.Infrastructure/Commands/DomainObjectGrainBase.cs
  10. 2
      src/Squidex.Infrastructure/EventSourcing/Grains/EventConsumerGrain.cs
  11. 13
      src/Squidex.Infrastructure/Orleans/GrainOfGuid.cs
  12. 71
      src/Squidex.Infrastructure/Orleans/GrainOfGuid{T}.cs
  13. 13
      src/Squidex.Infrastructure/Orleans/GrainOfString.cs
  14. 70
      src/Squidex.Infrastructure/Orleans/GrainOfString{T}.cs
  15. 2
      tests/Squidex.Domain.Apps.Entities.Tests/Apps/AppGrainTests.cs
  16. 6
      tests/Squidex.Domain.Apps.Entities.Tests/Apps/AppUISettingsGrainTests.cs
  17. 12
      tests/Squidex.Domain.Apps.Entities.Tests/Apps/Indexes/AppsByNameIndexGrainTests.cs
  18. 12
      tests/Squidex.Domain.Apps.Entities.Tests/Apps/Indexes/AppsByUserIndexGrainTests.cs
  19. 2
      tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetCommandMiddlewareTests.cs
  20. 2
      tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetGrainTests.cs
  21. 2
      tests/Squidex.Domain.Apps.Entities.Tests/Comments/CommentsGrainTests.cs
  22. 2
      tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentGrainTests.cs
  23. 12
      tests/Squidex.Domain.Apps.Entities.Tests/Rules/Indexes/RulesByAppIndexGrainTests.cs
  24. 2
      tests/Squidex.Domain.Apps.Entities.Tests/Rules/RuleGrainTests.cs
  25. 12
      tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Indexes/SchemasByAppIndexGrainTests.cs
  26. 2
      tests/Squidex.Domain.Apps.Entities.Tests/Schemas/SchemaGrainTests.cs
  27. 6
      tests/Squidex.Domain.Apps.Entities.Tests/Tags/TagGrainTests.cs
  28. 4
      tests/Squidex.Infrastructure.Tests/Commands/DomainObjectGrainTests.cs
  29. 4
      tests/Squidex.Infrastructure.Tests/Commands/LogSnapshotDomainObjectGrainTests.cs
  30. 30
      tests/Squidex.Infrastructure.Tests/EventSourcing/Grains/EventConsumerGrainTests.cs

32
src/Squidex.Domain.Apps.Entities/Apps/AppUISettingsGrain.cs

@ -8,6 +8,7 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Squidex.Domain.Apps.Entities.Apps.Indexes;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Json.Objects;
using Squidex.Infrastructure.Orleans;
@ -15,42 +16,29 @@ using Squidex.Infrastructure.States;
namespace Squidex.Domain.Apps.Entities.Apps
{
public sealed class AppUISettingsGrain : GrainOfGuid, IAppUISettingsGrain
public sealed class AppUISettingsGrain : GrainOfGuid<AppUISettingsGrain.GrainState>, IAppUISettingsGrain
{
private readonly IStore<Guid> store;
private IPersistence<State> persistence;
private State state = new State();
[CollectionName("UISettings")]
public sealed class State
public sealed class GrainState
{
public JsonObject Settings { get; set; } = JsonValue.Object();
}
public AppUISettingsGrain(IStore<Guid> store)
: base(store)
{
Guard.NotNull(store, nameof(store));
this.store = store;
}
public override Task OnActivateAsync(Guid key)
{
persistence = store.WithSnapshots<State, Guid>(GetType(), key, x => state = x);
return persistence.ReadAsync();
}
public Task<J<JsonObject>> GetAsync()
{
return Task.FromResult(state.Settings.AsJ());
return Task.FromResult(State.Settings.AsJ());
}
public Task SetAsync(J<JsonObject> settings)
{
state.Settings = settings;
State.Settings = settings;
return persistence.WriteSnapshotAsync(state);
return WriteStateAsync();
}
public Task SetAsync(string path, J<IJsonValue> value)
@ -64,7 +52,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
container[key] = value.Value;
return persistence.WriteSnapshotAsync(state);
return WriteStateAsync();
}
public Task RemoveAsync(string path)
@ -76,7 +64,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
container.Remove(key);
}
return persistence.WriteSnapshotAsync(state);
return WriteStateAsync();
}
private JsonObject GetContainer(string path, out string key)
@ -87,7 +75,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
key = segments[segments.Length - 1];
var current = state.Settings;
var current = State.Settings;
if (segments.Length > 1)
{

49
src/Squidex.Domain.Apps.Entities/Apps/Indexes/AppsByNameIndexGrain.cs

@ -9,56 +9,39 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Orleans;
using Squidex.Infrastructure.States;
using Squidex.Infrastructure.Tasks;
namespace Squidex.Domain.Apps.Entities.Apps.Indexes
{
public sealed class AppsByNameIndexGrain : GrainOfString, IAppsByNameIndex
public sealed class AppsByNameIndexGrain : GrainOfString<AppsByNameIndexGrain.GrainState>, IAppsByNameIndex
{
private readonly IStore<string> store;
private readonly HashSet<Guid> reservedIds = new HashSet<Guid>();
private readonly HashSet<string> reservedNames = new HashSet<string>();
private IPersistence<State> persistence;
private State state = new State();
[CollectionName("Index_AppsByName")]
public sealed class State
public sealed class GrainState
{
public Dictionary<string, Guid> Apps { get; set; } = new Dictionary<string, Guid>();
}
public AppsByNameIndexGrain(IStore<string> store)
: base(store)
{
Guard.NotNull(store, nameof(store));
this.store = store;
}
public override Task OnActivateAsync(string key)
{
persistence = store.WithSnapshots<AppsByNameIndexGrain, State, string>(key, s =>
{
state = s;
});
return persistence.ReadAsync();
}
public Task RebuildAsync(Dictionary<string, Guid> apps)
{
state = new State { Apps = apps };
State = new GrainState { Apps = apps };
return persistence.WriteSnapshotAsync(state);
return WriteStateAsync();
}
public Task<bool> ReserveAppAsync(Guid appId, string name)
{
var canReserve =
!state.Apps.ContainsKey(name) &&
!state.Apps.Any(x => x.Value == appId) &&
!State.Apps.ContainsKey(name) &&
!State.Apps.Any(x => x.Value == appId) &&
!reservedIds.Contains(appId) &&
!reservedNames.Contains(name);
@ -81,27 +64,27 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes
public Task AddAppAsync(Guid appId, string name)
{
state.Apps[name] = appId;
State.Apps[name] = appId;
reservedIds.Remove(appId);
reservedNames.Remove(name);
return persistence.WriteSnapshotAsync(state);
return WriteStateAsync();
}
public Task RemoveAppAsync(Guid appId)
{
var name = state.Apps.FirstOrDefault(x => x.Value == appId).Key;
var name = State.Apps.FirstOrDefault(x => x.Value == appId).Key;
if (!string.IsNullOrWhiteSpace(name))
{
state.Apps.Remove(name);
State.Apps.Remove(name);
reservedIds.Remove(appId);
reservedNames.Remove(name);
}
return persistence.WriteSnapshotAsync(state);
return WriteStateAsync();
}
public Task<List<Guid>> GetAppIdsAsync(params string[] names)
@ -110,7 +93,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes
foreach (var appName in names)
{
if (state.Apps.TryGetValue(appName, out var appId))
if (State.Apps.TryGetValue(appName, out var appId))
{
appIds.Add(appId);
}
@ -121,19 +104,19 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes
public Task<Guid> GetAppIdAsync(string appName)
{
state.Apps.TryGetValue(appName, out var appId);
State.Apps.TryGetValue(appName, out var appId);
return Task.FromResult(appId);
}
public Task<List<Guid>> GetAppIdsAsync()
{
return Task.FromResult(state.Apps.Values.ToList());
return Task.FromResult(State.Apps.Values.ToList());
}
public Task<long> CountAsync()
{
return Task.FromResult((long)state.Apps.Count);
return Task.FromResult((long)State.Apps.Count);
}
}
}

38
src/Squidex.Domain.Apps.Entities/Apps/Indexes/AppsByUserIndexGrain.cs

@ -9,65 +9,47 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Orleans;
using Squidex.Infrastructure.States;
namespace Squidex.Domain.Apps.Entities.Apps.Indexes
{
public sealed class AppsByUserIndexGrain : GrainOfString, IAppsByUserIndex
public sealed class AppsByUserIndexGrain : GrainOfString<AppsByUserIndexGrain.GrainState>, IAppsByUserIndex
{
private readonly IStore<string> store;
private IPersistence<State> persistence;
private State state = new State();
[CollectionName("Index_AppsByUser")]
public sealed class State
public sealed class GrainState
{
public HashSet<Guid> Apps { get; set; } = new HashSet<Guid>();
}
public AppsByUserIndexGrain(IStore<string> store)
: base(store)
{
Guard.NotNull(store, nameof(store));
this.store = store;
}
public override Task OnActivateAsync(string key)
{
persistence = store.WithSnapshots<AppsByUserIndexGrain, State, string>(key, s =>
{
state = s;
});
return persistence.ReadAsync();
}
public Task RebuildAsync(HashSet<Guid> apps)
{
state = new State { Apps = apps };
State = new GrainState { Apps = apps };
return persistence.WriteSnapshotAsync(state);
return WriteStateAsync();
}
public Task AddAppAsync(Guid appId)
{
state.Apps.Add(appId);
State.Apps.Add(appId);
return persistence.WriteSnapshotAsync(state);
return WriteStateAsync();
}
public Task RemoveAppAsync(Guid appId)
{
state.Apps.Remove(appId);
State.Apps.Remove(appId);
return persistence.WriteSnapshotAsync(state);
return WriteStateAsync();
}
public Task<List<Guid>> GetAppIdsAsync()
{
return Task.FromResult(state.Apps.ToList());
return Task.FromResult(State.Apps.ToList());
}
}
}

65
src/Squidex.Domain.Apps.Entities/Backup/BackupGrain.cs

@ -12,6 +12,7 @@ using System.Threading;
using System.Threading.Tasks;
using NodaTime;
using Orleans.Concurrency;
using Squidex.Domain.Apps.Entities.Apps.Indexes;
using Squidex.Domain.Apps.Entities.Backup.Helpers;
using Squidex.Domain.Apps.Entities.Backup.State;
using Squidex.Domain.Apps.Events;
@ -27,7 +28,7 @@ using Squidex.Infrastructure.Tasks;
namespace Squidex.Domain.Apps.Entities.Backup
{
[Reentrant]
public sealed class BackupGrain : GrainOfGuid, IBackupGrain
public sealed class BackupGrain : GrainOfGuid<BackupState>, IBackupGrain
{
private const int MaxBackups = 10;
private static readonly Duration UpdateDuration = Duration.FromSeconds(1);
@ -39,12 +40,8 @@ namespace Squidex.Domain.Apps.Entities.Backup
private readonly IEventDataFormatter eventDataFormatter;
private readonly IEventStore eventStore;
private readonly ISemanticLog log;
private readonly IStore<Guid> store;
private CancellationTokenSource currentTask;
private BackupStateJob currentJob;
private BackupState state = new BackupState();
private Guid appId;
private IPersistence<BackupState> persistence;
public BackupGrain(
IAssetStore assetStore,
@ -56,6 +53,7 @@ namespace Squidex.Domain.Apps.Entities.Backup
IJsonSerializer serializer,
ISemanticLog log,
IStore<Guid> store)
: base(store)
{
Guard.NotNull(assetStore, nameof(assetStore));
Guard.NotNull(backupArchiveLocation, nameof(backupArchiveLocation));
@ -64,7 +62,6 @@ namespace Squidex.Domain.Apps.Entities.Backup
Guard.NotNull(eventDataFormatter, nameof(eventDataFormatter));
Guard.NotNull(handlers, nameof(handlers));
Guard.NotNull(serializer, nameof(serializer));
Guard.NotNull(store, nameof(store));
Guard.NotNull(log, nameof(log));
this.assetStore = assetStore;
@ -74,29 +71,19 @@ namespace Squidex.Domain.Apps.Entities.Backup
this.eventDataFormatter = eventDataFormatter;
this.handlers = handlers;
this.serializer = serializer;
this.store = store;
this.log = log;
}
public override async Task OnActivateAsync(Guid key)
{
appId = key;
persistence = store.WithSnapshots<BackupState, Guid>(GetType(), key, s => state = s);
await ReadAsync();
RecoverAfterRestart();
}
private void RecoverAfterRestart()
protected override Task OnActivateAsync(Guid key)
{
RecoverAfterRestartAsync().Forget();
return TaskHelper.Done;
}
private async Task RecoverAfterRestartAsync()
{
foreach (var job in state.Jobs)
foreach (var job in State.Jobs)
{
if (!job.Stopped.HasValue)
{
@ -107,7 +94,7 @@ namespace Squidex.Domain.Apps.Entities.Backup
job.Status = JobStatus.Failed;
await WriteAsync();
await WriteStateAsync();
}
}
}
@ -119,7 +106,7 @@ namespace Squidex.Domain.Apps.Entities.Backup
throw new DomainException("Another backup process is already running.");
}
if (state.Jobs.Count >= MaxBackups)
if (State.Jobs.Count >= MaxBackups)
{
throw new DomainException($"You cannot have more than {MaxBackups} backups.");
}
@ -136,9 +123,9 @@ namespace Squidex.Domain.Apps.Entities.Backup
var lastTimestamp = job.Started;
state.Jobs.Insert(0, job);
State.Jobs.Insert(0, job);
await WriteAsync();
await WriteStateAsync();
try
{
@ -154,23 +141,23 @@ namespace Squidex.Domain.Apps.Entities.Backup
foreach (var handler in handlers)
{
await handler.BackupEventAsync(@event, appId, writer);
await handler.BackupEventAsync(@event, Key, writer);
}
job.HandledEvents = writer.WrittenEvents;
job.HandledAssets = writer.WrittenAttachments;
lastTimestamp = await WritePeriodically(lastTimestamp);
}, SquidexHeaders.AppId, appId.ToString(), null, currentTask.Token);
}, SquidexHeaders.AppId, Key.ToString(), null, currentTask.Token);
foreach (var handler in handlers)
{
await handler.BackupAsync(appId, writer);
await handler.BackupAsync(Key, writer);
}
foreach (var handler in handlers)
{
await handler.CompleteBackupAsync(appId, writer);
await handler.CompleteBackupAsync(Key, writer);
}
}
@ -198,7 +185,7 @@ namespace Squidex.Domain.Apps.Entities.Backup
job.Stopped = clock.GetCurrentInstant();
await WriteAsync();
await WriteStateAsync();
currentTask = null;
currentJob = null;
@ -213,7 +200,7 @@ namespace Squidex.Domain.Apps.Entities.Backup
{
lastTimestamp = now;
await WriteAsync();
await WriteStateAsync();
}
return lastTimestamp;
@ -221,7 +208,7 @@ namespace Squidex.Domain.Apps.Entities.Backup
public async Task DeleteAsync(Guid id)
{
var job = state.Jobs.FirstOrDefault(x => x.Id == id);
var job = State.Jobs.FirstOrDefault(x => x.Id == id);
if (job == null)
{
@ -237,25 +224,15 @@ namespace Squidex.Domain.Apps.Entities.Backup
await Safe.DeleteAsync(backupArchiveLocation, job.Id, log);
await Safe.DeleteAsync(assetStore, job.Id, log);
state.Jobs.Remove(job);
State.Jobs.Remove(job);
await WriteAsync();
await WriteStateAsync();
}
}
public Task<J<List<IBackupJob>>> GetStateAsync()
{
return J.AsTask(state.Jobs.OfType<IBackupJob>().ToList());
}
private async Task ReadAsync()
{
await persistence.ReadAsync();
}
private async Task WriteAsync()
{
await persistence.WriteSnapshotAsync(state);
return J.AsTask(State.Jobs.OfType<IBackupJob>().ToList());
}
}
}

39
src/Squidex.Domain.Apps.Entities/Backup/RestoreGrain.cs

@ -11,6 +11,7 @@ using System.Threading.Tasks;
using NodaTime;
using Squidex.Domain.Apps.Core.Apps;
using Squidex.Domain.Apps.Entities.Apps.Commands;
using Squidex.Domain.Apps.Entities.Apps.Indexes;
using Squidex.Domain.Apps.Entities.Backup.Helpers;
using Squidex.Domain.Apps.Entities.Backup.State;
using Squidex.Domain.Apps.Events;
@ -26,7 +27,7 @@ using Squidex.Infrastructure.Tasks;
namespace Squidex.Domain.Apps.Entities.Backup
{
public sealed class RestoreGrain : GrainOfString, IRestoreGrain
public sealed class RestoreGrain : GrainOfString<RestoreState>, IRestoreGrain
{
private readonly IBackupArchiveLocation backupArchiveLocation;
private readonly IClock clock;
@ -37,14 +38,11 @@ namespace Squidex.Domain.Apps.Entities.Backup
private readonly IEventDataFormatter eventDataFormatter;
private readonly ISemanticLog log;
private readonly IStreamNameResolver streamNameResolver;
private readonly IStore<string> store;
private RefToken actor;
private RestoreState state = new RestoreState();
private IPersistence<RestoreState> persistence;
private RestoreStateJob CurrentJob
{
get { return state.Job; }
get { return State.Job; }
}
public RestoreGrain(IBackupArchiveLocation backupArchiveLocation,
@ -57,6 +55,7 @@ namespace Squidex.Domain.Apps.Entities.Backup
ISemanticLog log,
IStreamNameResolver streamNameResolver,
IStore<string> store)
: base(store)
{
Guard.NotNull(backupArchiveLocation, nameof(backupArchiveLocation));
Guard.NotNull(clock, nameof(clock));
@ -76,25 +75,17 @@ namespace Squidex.Domain.Apps.Entities.Backup
this.eventDataFormatter = eventDataFormatter;
this.handlers = handlers;
this.serializer = serializer;
this.store = store;
this.streamNameResolver = streamNameResolver;
this.log = log;
}
public override async Task OnActivateAsync(string key)
protected override Task OnActivateAsync(string key)
{
actor = new RefToken(RefTokenType.Subject, key);
persistence = store.WithSnapshots<RestoreState, string>(GetType(), key, s => state = s);
await ReadAsync();
RecoverAfterRestart();
}
private void RecoverAfterRestart()
{
RecoverAfterRestartAsync().Forget();
return TaskHelper.Done;
}
private async Task RecoverAfterRestartAsync()
@ -106,7 +97,7 @@ namespace Squidex.Domain.Apps.Entities.Backup
CurrentJob.Status = JobStatus.Failed;
await CleanupAsync();
await WriteAsync();
await WriteStateAsync();
}
}
@ -124,7 +115,7 @@ namespace Squidex.Domain.Apps.Entities.Backup
throw new DomainException("A restore operation is already running.");
}
state.Job = new RestoreStateJob
State.Job = new RestoreStateJob
{
Id = Guid.NewGuid(),
NewAppName = newAppName,
@ -239,7 +230,7 @@ namespace Squidex.Domain.Apps.Entities.Backup
{
CurrentJob.Stopped = clock.GetCurrentInstant();
await WriteAsync();
await WriteStateAsync();
}
}
}
@ -340,16 +331,6 @@ namespace Squidex.Domain.Apps.Entities.Backup
}
}
private async Task ReadAsync()
{
await persistence.ReadAsync();
}
private async Task WriteAsync()
{
await persistence.WriteSnapshotAsync(state);
}
public Task<J<IRestoreJob>> GetJobAsync()
{
return Task.FromResult<J<IRestoreJob>>(CurrentJob);

43
src/Squidex.Domain.Apps.Entities/Rules/Indexes/RulesByAppIndexGrain.cs

@ -9,72 +9,53 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Orleans;
using Squidex.Domain.Apps.Entities.Apps.Indexes;
using Squidex.Infrastructure.States;
namespace Squidex.Domain.Apps.Entities.Rules.Indexes
{
public sealed class RulesByAppIndexGrain : GrainOfGuid, IRulesByAppIndex
public sealed class RulesByAppIndexGrain : GrainOfGuid<RulesByAppIndexGrain.GrainState>, IRulesByAppIndex
{
private readonly IStore<Guid> store;
private IPersistence<State> persistence;
private State state = new State();
[CollectionName("Index_RulesByApp")]
public sealed class State
public sealed class GrainState
{
public HashSet<Guid> Rules { get; set; } = new HashSet<Guid>();
}
public RulesByAppIndexGrain(IStore<Guid> store)
: base(store)
{
Guard.NotNull(store, nameof(store));
this.store = store;
}
public override Task OnActivateAsync(Guid key)
{
persistence = store.WithSnapshots<RulesByAppIndexGrain, State, Guid>(key, s =>
{
state = s;
});
return persistence.ReadAsync();
}
public Task ClearAsync()
{
state = new State();
return persistence.DeleteAsync();
return ClearStateAsync();
}
public Task RebuildAsync(HashSet<Guid> rules)
{
state = new State { Rules = rules };
State = new GrainState { Rules = rules };
return persistence.WriteSnapshotAsync(state);
return WriteStateAsync();
}
public Task AddRuleAsync(Guid ruleId)
{
state.Rules.Add(ruleId);
State.Rules.Add(ruleId);
return persistence.WriteSnapshotAsync(state);
return WriteStateAsync();
}
public Task RemoveRuleAsync(Guid ruleId)
{
state.Rules.Remove(ruleId);
State.Rules.Remove(ruleId);
return persistence.WriteSnapshotAsync(state);
return WriteStateAsync();
}
public Task<List<Guid>> GetRuleIdsAsync()
{
return Task.FromResult(state.Rules.ToList());
return Task.FromResult(State.Rules.ToList());
}
}
}

45
src/Squidex.Domain.Apps.Entities/Schemas/Indexes/SchemasByAppIndexGrain.cs

@ -9,79 +9,60 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Orleans;
using Squidex.Domain.Apps.Entities.Apps.Indexes;
using Squidex.Infrastructure.States;
namespace Squidex.Domain.Apps.Entities.Schemas.Indexes
{
public sealed class SchemasByAppIndexGrain : GrainOfGuid, ISchemasByAppIndex
public sealed class SchemasByAppIndexGrain : GrainOfGuid<SchemasByAppIndexGrain.GrainState>, ISchemasByAppIndex
{
private readonly IStore<Guid> store;
private IPersistence<State> persistence;
private State state = new State();
[CollectionName("Index_SchemasByApp")]
public sealed class State
public sealed class GrainState
{
public Dictionary<string, Guid> Schemas { get; set; } = new Dictionary<string, Guid>();
}
public SchemasByAppIndexGrain(IStore<Guid> store)
: base(store)
{
Guard.NotNull(store, nameof(store));
this.store = store;
}
public override Task OnActivateAsync(Guid key)
{
persistence = store.WithSnapshots<SchemasByAppIndexGrain, State, Guid>(key, s =>
{
state = s;
});
return persistence.ReadAsync();
}
public Task ClearAsync()
{
state = new State();
return persistence.DeleteAsync();
return ClearStateAsync();
}
public Task RebuildAsync(Dictionary<string, Guid> schemas)
{
state = new State { Schemas = schemas };
State = new GrainState { Schemas = schemas };
return persistence.WriteSnapshotAsync(state);
return WriteStateAsync();
}
public Task AddSchemaAsync(Guid schemaId, string name)
{
state.Schemas[name] = schemaId;
State.Schemas[name] = schemaId;
return persistence.WriteSnapshotAsync(state);
return WriteStateAsync();
}
public Task RemoveSchemaAsync(Guid schemaId)
{
state.Schemas.Remove(state.Schemas.FirstOrDefault(x => x.Value == schemaId).Key ?? string.Empty);
State.Schemas.Remove(State.Schemas.FirstOrDefault(x => x.Value == schemaId).Key ?? string.Empty);
return persistence.WriteSnapshotAsync(state);
return WriteStateAsync();
}
public Task<Guid> GetSchemaIdAsync(string name)
{
state.Schemas.TryGetValue(name, out var schemaId);
State.Schemas.TryGetValue(name, out var schemaId);
return Task.FromResult(schemaId);
}
public Task<List<Guid>> GetSchemaIdsAsync()
{
return Task.FromResult(state.Schemas.Values.ToList());
return Task.FromResult(State.Schemas.Values.ToList());
}
}
}

51
src/Squidex.Domain.Apps.Entities/Tags/TagGrain.cs

@ -10,53 +10,34 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Squidex.Domain.Apps.Core.Tags;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Orleans;
using Squidex.Domain.Apps.Entities.Apps.Indexes;
using Squidex.Infrastructure.States;
namespace Squidex.Domain.Apps.Entities.Tags
{
public sealed class TagGrain : GrainOfString, ITagGrain
public sealed class TagGrain : GrainOfString<TagGrain.GrainState>, ITagGrain
{
private readonly IStore<string> store;
private IPersistence<State> persistence;
private State state = new State();
[CollectionName("Index_Tags")]
public sealed class State
public sealed class GrainState
{
public TagSet Tags { get; set; } = new TagSet();
}
public TagGrain(IStore<string> store)
: base(store)
{
Guard.NotNull(store, nameof(store));
this.store = store;
}
public override Task OnActivateAsync(string key)
{
persistence = store.WithSnapshots<TagGrain, State, string>(key, s =>
{
state = s;
});
return persistence.ReadAsync();
}
public Task ClearAsync()
{
state = new State();
return persistence.DeleteAsync();
return ClearStateAsync();
}
public Task RebuildAsync(TagSet tags)
{
state.Tags = tags;
State.Tags = tags;
return persistence.WriteSnapshotAsync(state);
return WriteStateAsync();
}
public async Task<Dictionary<string, string>> NormalizeTagsAsync(HashSet<string> names, HashSet<string> ids)
@ -72,7 +53,7 @@ namespace Squidex.Domain.Apps.Entities.Tags
var tagName = tag.ToLowerInvariant();
var tagId = string.Empty;
var found = state.Tags.FirstOrDefault(x => string.Equals(x.Value.Name, tagName, StringComparison.OrdinalIgnoreCase));
var found = State.Tags.FirstOrDefault(x => string.Equals(x.Value.Name, tagName, StringComparison.OrdinalIgnoreCase));
if (found.Value != null)
{
@ -87,7 +68,7 @@ namespace Squidex.Domain.Apps.Entities.Tags
{
tagId = Guid.NewGuid().ToString();
state.Tags.Add(tagId, new Tag { Name = tagName });
State.Tags.Add(tagId, new Tag { Name = tagName });
}
result.Add(tagName, tagId);
@ -101,20 +82,20 @@ namespace Squidex.Domain.Apps.Entities.Tags
{
if (!result.ContainsValue(id))
{
if (state.Tags.TryGetValue(id, out var tagInfo))
if (State.Tags.TryGetValue(id, out var tagInfo))
{
tagInfo.Count--;
if (tagInfo.Count <= 0)
{
state.Tags.Remove(id);
State.Tags.Remove(id);
}
}
}
}
}
await persistence.WriteSnapshotAsync(state);
await WriteStateAsync();
return result;
}
@ -125,7 +106,7 @@ namespace Squidex.Domain.Apps.Entities.Tags
foreach (var name in names)
{
var id = state.Tags.FirstOrDefault(x => string.Equals(x.Value.Name, name, StringComparison.OrdinalIgnoreCase)).Key;
var id = State.Tags.FirstOrDefault(x => string.Equals(x.Value.Name, name, StringComparison.OrdinalIgnoreCase)).Key;
if (!string.IsNullOrWhiteSpace(id))
{
@ -142,7 +123,7 @@ namespace Squidex.Domain.Apps.Entities.Tags
foreach (var id in ids)
{
if (state.Tags.TryGetValue(id, out var tagInfo))
if (State.Tags.TryGetValue(id, out var tagInfo))
{
result[id] = tagInfo.Name;
}
@ -153,12 +134,12 @@ namespace Squidex.Domain.Apps.Entities.Tags
public Task<Dictionary<string, int>> GetTagsAsync()
{
return Task.FromResult(state.Tags.Values.ToDictionary(x => x.Name, x => x.Count));
return Task.FromResult(State.Tags.Values.ToDictionary(x => x.Name, x => x.Count));
}
public Task<TagSet> GetExportableTagsAsync()
{
return Task.FromResult(state.Tags);
return Task.FromResult(State.Tags);
}
}
}

2
src/Squidex.Infrastructure/Commands/DomainObjectGrainBase.cs

@ -47,7 +47,7 @@ namespace Squidex.Infrastructure.Commands
this.log = log;
}
public sealed override async Task OnActivateAsync(Guid key)
protected sealed override async Task OnActivateAsync(Guid key)
{
using (log.MeasureInformation(w => w
.WriteProperty("action", "ActivateDomainObject")

2
src/Squidex.Infrastructure/EventSourcing/Grains/EventConsumerGrain.cs

@ -50,7 +50,7 @@ namespace Squidex.Infrastructure.EventSourcing.Grains
this.eventConsumerFactory = eventConsumerFactory;
}
public override Task OnActivateAsync(string key)
protected override Task OnActivateAsync(string key)
{
scheduler = TaskScheduler.Current;

13
src/Squidex.Infrastructure/Orleans/GrainOfGuid.cs

@ -14,12 +14,21 @@ namespace Squidex.Infrastructure.Orleans
{
public abstract class GrainOfGuid : Grain
{
public Guid Key { get; private set; }
public sealed override Task OnActivateAsync()
{
return OnActivateAsync(this.GetPrimaryKey());
return ActivateAsync(this.GetPrimaryKey());
}
public Task ActivateAsync(Guid key)
{
Key = key;
return OnActivateAsync(key);
}
public virtual Task OnActivateAsync(Guid key)
protected virtual Task OnActivateAsync(Guid key)
{
return TaskHelper.Done;
}

71
src/Squidex.Infrastructure/Orleans/GrainOfGuid{T}.cs

@ -0,0 +1,71 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using System.Threading.Tasks;
using Orleans;
using Squidex.Infrastructure;
using Squidex.Infrastructure.States;
using Squidex.Infrastructure.Tasks;
namespace Squidex.Domain.Apps.Entities.Apps.Indexes
{
public abstract class GrainOfGuid<T> : Grain where T : class, new()
{
private readonly IStore<Guid> store;
private IPersistence<T> persistence;
protected T State { get; set; }
public Guid Key { get; private set; }
protected GrainOfGuid(IStore<Guid> store)
{
Guard.NotNull(store, nameof(store));
this.store = store;
}
public sealed override Task OnActivateAsync()
{
return ActivateAsync(this.GetPrimaryKey());
}
public async Task ActivateAsync(Guid key)
{
Key = key;
persistence = store.WithSnapshots<T, Guid>(GetType(), key, ApplyState);
await persistence.ReadAsync();
await OnActivateAsync(key);
}
protected virtual Task OnActivateAsync(Guid key)
{
return TaskHelper.Done;
}
private void ApplyState(T state)
{
State = state;
}
public Task ClearStateAsync()
{
State = new T();
return persistence.DeleteAsync();
}
protected Task WriteStateAsync()
{
return persistence.WriteSnapshotAsync(State);
}
}
}

13
src/Squidex.Infrastructure/Orleans/GrainOfString.cs

@ -13,12 +13,21 @@ namespace Squidex.Infrastructure.Orleans
{
public abstract class GrainOfString : Grain
{
public string Key { get; private set; }
public sealed override Task OnActivateAsync()
{
return OnActivateAsync(this.GetPrimaryKeyString());
return ActivateAsync(this.GetPrimaryKeyString());
}
public Task ActivateAsync(string key)
{
Key = key;
return OnActivateAsync(key);
}
public virtual Task OnActivateAsync(string key)
protected virtual Task OnActivateAsync(string key)
{
return TaskHelper.Done;
}

70
src/Squidex.Infrastructure/Orleans/GrainOfString{T}.cs

@ -0,0 +1,70 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Threading.Tasks;
using Orleans;
using Squidex.Infrastructure;
using Squidex.Infrastructure.States;
using Squidex.Infrastructure.Tasks;
namespace Squidex.Domain.Apps.Entities.Apps.Indexes
{
public abstract class GrainOfString<T> : Grain where T : class, new()
{
private readonly IStore<string> store;
private IPersistence<T> persistence;
public string Key { get; set; }
protected T State { get; set; }
protected GrainOfString(IStore<string> store)
{
Guard.NotNull(store, nameof(store));
this.store = store;
}
public sealed override Task OnActivateAsync()
{
return ActivateAsync(this.GetPrimaryKeyString());
}
public async Task ActivateAsync(string key)
{
Key = key;
persistence = store.WithSnapshots<T, string>(GetType(), key, ApplyState);
await persistence.ReadAsync();
await OnActivateAsync(key);
}
protected virtual Task OnActivateAsync(string key)
{
return TaskHelper.Done;
}
private void ApplyState(T state)
{
State = state;
}
public Task ClearStateAsync()
{
State = new T();
return persistence.DeleteAsync();
}
protected Task WriteStateAsync()
{
return persistence.WriteSnapshotAsync(State);
}
}
}

2
tests/Squidex.Domain.Apps.Entities.Tests/Apps/AppGrainTests.cs

@ -60,7 +60,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
};
sut = new AppGrain(initialPatterns, Store, A.Dummy<ISemanticLog>(), appPlansProvider, appPlansBillingManager, userResolver);
sut.OnActivateAsync(Id).Wait();
sut.ActivateAsync(Id).Wait();
}
[Fact]

6
tests/Squidex.Domain.Apps.Entities.Tests/Apps/AppUISettingsGrainTests.cs

@ -18,16 +18,16 @@ namespace Squidex.Domain.Apps.Entities.Apps
public sealed class AppUISettingsGrainTests
{
private readonly IStore<Guid> store = A.Fake<IStore<Guid>>();
private readonly IPersistence<AppUISettingsGrain.State> persistence = A.Fake<IPersistence<AppUISettingsGrain.State>>();
private readonly IPersistence<AppUISettingsGrain.GrainState> persistence = A.Fake<IPersistence<AppUISettingsGrain.GrainState>>();
private readonly AppUISettingsGrain sut;
public AppUISettingsGrainTests()
{
A.CallTo(() => store.WithSnapshots(A<Type>.Ignored, A<Guid>.Ignored, A<Func<AppUISettingsGrain.State, Task>>.Ignored))
A.CallTo(() => store.WithSnapshots(A<Type>.Ignored, A<Guid>.Ignored, A<Func<AppUISettingsGrain.GrainState, Task>>.Ignored))
.Returns(persistence);
sut = new AppUISettingsGrain(store);
sut.OnActivateAsync(Guid.Empty).Wait();
sut.ActivateAsync(Guid.Empty).Wait();
}
[Fact]

12
tests/Squidex.Domain.Apps.Entities.Tests/Apps/Indexes/AppsByNameIndexGrainTests.cs

@ -18,7 +18,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes
public class AppsByNameIndexGrainTests
{
private readonly IStore<string> store = A.Fake<IStore<string>>();
private readonly IPersistence<AppsByNameIndexGrain.State> persistence = A.Fake<IPersistence<AppsByNameIndexGrain.State>>();
private readonly IPersistence<AppsByNameIndexGrain.GrainState> persistence = A.Fake<IPersistence<AppsByNameIndexGrain.GrainState>>();
private readonly Guid appId1 = Guid.NewGuid();
private readonly Guid appId2 = Guid.NewGuid();
private readonly string appName1 = "my-app1";
@ -27,11 +27,11 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes
public AppsByNameIndexGrainTests()
{
A.CallTo(() => store.WithSnapshots(A<Type>.Ignored, A<string>.Ignored, A<Func<AppsByNameIndexGrain.State, Task>>.Ignored))
A.CallTo(() => store.WithSnapshots(A<Type>.Ignored, A<string>.Ignored, A<Func<AppsByNameIndexGrain.GrainState, Task>>.Ignored))
.Returns(persistence);
sut = new AppsByNameIndexGrain(store);
sut.OnActivateAsync(SingleGrain.Id).Wait();
sut.ActivateAsync(SingleGrain.Id).Wait();
}
[Fact]
@ -43,7 +43,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes
Assert.Equal(appId1, result);
A.CallTo(() => persistence.WriteSnapshotAsync(A<AppsByNameIndexGrain.State>.Ignored))
A.CallTo(() => persistence.WriteSnapshotAsync(A<AppsByNameIndexGrain.GrainState>.Ignored))
.MustHaveHappened();
}
@ -126,7 +126,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes
Assert.Equal(Guid.Empty, result);
A.CallTo(() => persistence.WriteSnapshotAsync(A<AppsByNameIndexGrain.State>.Ignored))
A.CallTo(() => persistence.WriteSnapshotAsync(A<AppsByNameIndexGrain.GrainState>.Ignored))
.MustHaveHappenedTwiceExactly();
}
@ -148,7 +148,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes
Assert.Equal(2, await sut.CountAsync());
A.CallTo(() => persistence.WriteSnapshotAsync(A<AppsByNameIndexGrain.State>.Ignored))
A.CallTo(() => persistence.WriteSnapshotAsync(A<AppsByNameIndexGrain.GrainState>.Ignored))
.MustHaveHappened();
}
}

12
tests/Squidex.Domain.Apps.Entities.Tests/Apps/Indexes/AppsByUserIndexGrainTests.cs

@ -18,18 +18,18 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes
public class AppsByUserIndexGrainTests
{
private readonly IStore<string> store = A.Fake<IStore<string>>();
private readonly IPersistence<AppsByUserIndexGrain.State> persistence = A.Fake<IPersistence<AppsByUserIndexGrain.State>>();
private readonly IPersistence<AppsByUserIndexGrain.GrainState> persistence = A.Fake<IPersistence<AppsByUserIndexGrain.GrainState>>();
private readonly Guid appId1 = Guid.NewGuid();
private readonly Guid appId2 = Guid.NewGuid();
private readonly AppsByUserIndexGrain sut;
public AppsByUserIndexGrainTests()
{
A.CallTo(() => store.WithSnapshots(A<Type>.Ignored, A<string>.Ignored, A<Func<AppsByUserIndexGrain.State, Task>>.Ignored))
A.CallTo(() => store.WithSnapshots(A<Type>.Ignored, A<string>.Ignored, A<Func<AppsByUserIndexGrain.GrainState, Task>>.Ignored))
.Returns(persistence);
sut = new AppsByUserIndexGrain(store);
sut.OnActivateAsync("user").Wait();
sut.ActivateAsync("user").Wait();
}
[Fact]
@ -42,7 +42,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes
Assert.Equal(new List<Guid> { appId1, appId2 }, result);
A.CallTo(() => persistence.WriteSnapshotAsync(A<AppsByUserIndexGrain.State>.Ignored))
A.CallTo(() => persistence.WriteSnapshotAsync(A<AppsByUserIndexGrain.GrainState>.Ignored))
.MustHaveHappenedTwiceExactly();
}
@ -57,7 +57,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes
Assert.Equal(new List<Guid> { appId2 }, result);
A.CallTo(() => persistence.WriteSnapshotAsync(A<AppsByUserIndexGrain.State>.Ignored))
A.CallTo(() => persistence.WriteSnapshotAsync(A<AppsByUserIndexGrain.GrainState>.Ignored))
.MustHaveHappenedTwiceOrMore();
}
@ -72,7 +72,7 @@ namespace Squidex.Domain.Apps.Entities.Apps.Indexes
Assert.Equal(new List<Guid> { appId1, appId2 }, result);
A.CallTo(() => persistence.WriteSnapshotAsync(A<AppsByUserIndexGrain.State>.Ignored))
A.CallTo(() => persistence.WriteSnapshotAsync(A<AppsByUserIndexGrain.GrainState>.Ignored))
.MustHaveHappened();
}
}

2
tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetCommandMiddlewareTests.cs

@ -48,7 +48,7 @@ namespace Squidex.Domain.Apps.Entities.Assets
file = new AssetFile("my-image.png", "image/png", 1024, () => stream);
asset = new AssetGrain(Store, tagService, A.Dummy<ISemanticLog>());
asset.OnActivateAsync(Id).Wait();
asset.ActivateAsync(Id).Wait();
A.CallTo(() => tagService.NormalizeTagsAsync(AppId, TagGroups.Assets, A<HashSet<string>>.Ignored, A<HashSet<string>>.Ignored))
.Returns(new Dictionary<string, string>());

2
tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetGrainTests.cs

@ -42,7 +42,7 @@ namespace Squidex.Domain.Apps.Entities.Assets
.Returns(new Dictionary<string, string>());
sut = new AssetGrain(Store, tagService, A.Dummy<ISemanticLog>());
sut.OnActivateAsync(Id).Wait();
sut.ActivateAsync(Id).Wait();
}
[Fact]

2
tests/Squidex.Domain.Apps.Entities.Tests/Comments/CommentsGrainTests.cs

@ -37,7 +37,7 @@ namespace Squidex.Domain.Apps.Entities.Comments
public CommentsGrainTests()
{
sut = new CommentsGrain(Store, A.Dummy<ISemanticLog>());
sut.OnActivateAsync(Id).Wait();
sut.ActivateAsync(Id).Wait();
}
[Fact]

2
tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentGrainTests.cs

@ -98,7 +98,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
patched = patch.MergeInto(data);
sut = new ContentGrain(Store, A.Dummy<ISemanticLog>(), appProvider, A.Dummy<IAssetRepository>(), scriptEngine, A.Dummy<IContentRepository>());
sut.OnActivateAsync(Id).Wait();
sut.ActivateAsync(Id).Wait();
}
[Fact]

12
tests/Squidex.Domain.Apps.Entities.Tests/Rules/Indexes/RulesByAppIndexGrainTests.cs

@ -17,18 +17,18 @@ namespace Squidex.Domain.Apps.Entities.Rules.Indexes
public class RulesByAppIndexGrainTests
{
private readonly IStore<Guid> store = A.Fake<IStore<Guid>>();
private readonly IPersistence<RulesByAppIndexGrain.State> persistence = A.Fake<IPersistence<RulesByAppIndexGrain.State>>();
private readonly IPersistence<RulesByAppIndexGrain.GrainState> persistence = A.Fake<IPersistence<RulesByAppIndexGrain.GrainState>>();
private readonly Guid ruleId1 = Guid.NewGuid();
private readonly Guid ruleId2 = Guid.NewGuid();
private readonly RulesByAppIndexGrain sut;
public RulesByAppIndexGrainTests()
{
A.CallTo(() => store.WithSnapshots(A<Type>.Ignored, A<Guid>.Ignored, A<Func<RulesByAppIndexGrain.State, Task>>.Ignored))
A.CallTo(() => store.WithSnapshots(A<Type>.Ignored, A<Guid>.Ignored, A<Func<RulesByAppIndexGrain.GrainState, Task>>.Ignored))
.Returns(persistence);
sut = new RulesByAppIndexGrain(store);
sut.OnActivateAsync(Guid.NewGuid()).Wait();
sut.ActivateAsync(Guid.NewGuid()).Wait();
}
[Fact]
@ -41,7 +41,7 @@ namespace Squidex.Domain.Apps.Entities.Rules.Indexes
Assert.Equal(new List<Guid> { ruleId1, ruleId2 }, result);
A.CallTo(() => persistence.WriteSnapshotAsync(A<RulesByAppIndexGrain.State>.Ignored))
A.CallTo(() => persistence.WriteSnapshotAsync(A<RulesByAppIndexGrain.GrainState>.Ignored))
.MustHaveHappenedTwiceExactly();
}
@ -71,7 +71,7 @@ namespace Squidex.Domain.Apps.Entities.Rules.Indexes
Assert.Equal(new List<Guid> { ruleId2 }, result);
A.CallTo(() => persistence.WriteSnapshotAsync(A<RulesByAppIndexGrain.State>.Ignored))
A.CallTo(() => persistence.WriteSnapshotAsync(A<RulesByAppIndexGrain.GrainState>.Ignored))
.MustHaveHappenedTwiceOrMore();
}
@ -90,7 +90,7 @@ namespace Squidex.Domain.Apps.Entities.Rules.Indexes
Assert.Equal(new List<Guid> { ruleId1, ruleId2 }, result);
A.CallTo(() => persistence.WriteSnapshotAsync(A<RulesByAppIndexGrain.State>.Ignored))
A.CallTo(() => persistence.WriteSnapshotAsync(A<RulesByAppIndexGrain.GrainState>.Ignored))
.MustHaveHappened();
}
}

2
tests/Squidex.Domain.Apps.Entities.Tests/Rules/RuleGrainTests.cs

@ -41,7 +41,7 @@ namespace Squidex.Domain.Apps.Entities.Rules
public RuleGrainTests()
{
sut = new RuleGrain(Store, A.Dummy<ISemanticLog>(), appProvider);
sut.OnActivateAsync(Id).Wait();
sut.ActivateAsync(Id).Wait();
}
[Fact]

12
tests/Squidex.Domain.Apps.Entities.Tests/Schemas/Indexes/SchemasByAppIndexGrainTests.cs

@ -17,7 +17,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Indexes
public class SchemasByAppIndexGrainTests
{
private readonly IStore<Guid> store = A.Fake<IStore<Guid>>();
private readonly IPersistence<SchemasByAppIndexGrain.State> persistence = A.Fake<IPersistence<SchemasByAppIndexGrain.State>>();
private readonly IPersistence<SchemasByAppIndexGrain.GrainState> persistence = A.Fake<IPersistence<SchemasByAppIndexGrain.GrainState>>();
private readonly Guid schemaId1 = Guid.NewGuid();
private readonly Guid schemaId2 = Guid.NewGuid();
private readonly string schemaName1 = "my-schema1";
@ -26,11 +26,11 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Indexes
public SchemasByAppIndexGrainTests()
{
A.CallTo(() => store.WithSnapshots(A<Type>.Ignored, A<Guid>.Ignored, A<Func<SchemasByAppIndexGrain.State, Task>>.Ignored))
A.CallTo(() => store.WithSnapshots(A<Type>.Ignored, A<Guid>.Ignored, A<Func<SchemasByAppIndexGrain.GrainState, Task>>.Ignored))
.Returns(persistence);
sut = new SchemasByAppIndexGrain(store);
sut.OnActivateAsync(Guid.NewGuid()).Wait();
sut.ActivateAsync(Guid.NewGuid()).Wait();
}
[Fact]
@ -42,7 +42,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Indexes
Assert.Equal(schemaId1, result);
A.CallTo(() => persistence.WriteSnapshotAsync(A<SchemasByAppIndexGrain.State>.Ignored))
A.CallTo(() => persistence.WriteSnapshotAsync(A<SchemasByAppIndexGrain.GrainState>.Ignored))
.MustHaveHappened();
}
@ -70,7 +70,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Indexes
Assert.Equal(Guid.Empty, result);
A.CallTo(() => persistence.WriteSnapshotAsync(A<SchemasByAppIndexGrain.State>.Ignored))
A.CallTo(() => persistence.WriteSnapshotAsync(A<SchemasByAppIndexGrain.GrainState>.Ignored))
.MustHaveHappenedTwiceExactly();
}
@ -90,7 +90,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas.Indexes
Assert.Equal(new List<Guid> { schemaId1, schemaId2 }, await sut.GetSchemaIdsAsync());
A.CallTo(() => persistence.WriteSnapshotAsync(A<SchemasByAppIndexGrain.State>.Ignored))
A.CallTo(() => persistence.WriteSnapshotAsync(A<SchemasByAppIndexGrain.GrainState>.Ignored))
.MustHaveHappened();
}
}

2
tests/Squidex.Domain.Apps.Entities.Tests/Schemas/SchemaGrainTests.cs

@ -45,7 +45,7 @@ namespace Squidex.Domain.Apps.Entities.Schemas
.Returns((ISchemaEntity)null);
sut = new SchemaGrain(Store, A.Dummy<ISemanticLog>(), appProvider, registry);
sut.OnActivateAsync(Id).Wait();
sut.ActivateAsync(Id).Wait();
}
[Fact]

6
tests/Squidex.Domain.Apps.Entities.Tests/Tags/TagGrainTests.cs

@ -19,16 +19,16 @@ namespace Squidex.Domain.Apps.Entities.Tags
public class TagGrainTests
{
private readonly IStore<string> store = A.Fake<IStore<string>>();
private readonly IPersistence<TagGrain.State> persistence = A.Fake<IPersistence<TagGrain.State>>();
private readonly IPersistence<TagGrain.GrainState> persistence = A.Fake<IPersistence<TagGrain.GrainState>>();
private readonly TagGrain sut;
public TagGrainTests()
{
A.CallTo(() => store.WithSnapshots(A<Type>.Ignored, A<string>.Ignored, A<Func<TagGrain.State, Task>>.Ignored))
A.CallTo(() => store.WithSnapshots(A<Type>.Ignored, A<string>.Ignored, A<Func<TagGrain.GrainState, Task>>.Ignored))
.Returns(persistence);
sut = new TagGrain(store);
sut.OnActivateAsync(string.Empty).Wait();
sut.ActivateAsync(string.Empty).Wait();
}
[Fact]

4
tests/Squidex.Infrastructure.Tests/Commands/DomainObjectGrainTests.cs

@ -239,7 +239,7 @@ namespace Squidex.Infrastructure.Commands
private async Task SetupCreatedAsync()
{
await sut.OnActivateAsync(id);
await sut.ActivateAsync(id);
await sut.ExecuteAsync(C(new CreateAuto { Value = 4 }));
}
@ -251,7 +251,7 @@ namespace Squidex.Infrastructure.Commands
private async Task SetupEmptyAsync()
{
await sut.OnActivateAsync(id);
await sut.ActivateAsync(id);
}
}
}

4
tests/Squidex.Infrastructure.Tests/Commands/LogSnapshotDomainObjectGrainTests.cs

@ -275,7 +275,7 @@ namespace Squidex.Infrastructure.Commands
private async Task SetupCreatedAsync()
{
await sut.OnActivateAsync(id);
await sut.ActivateAsync(id);
await sut.ExecuteAsync(C(new CreateAuto { Value = 4 }));
}
@ -289,7 +289,7 @@ namespace Squidex.Infrastructure.Commands
private async Task SetupEmptyAsync()
{
await sut.OnActivateAsync(id);
await sut.ActivateAsync(id);
}
private static J<IAggregateCommand> C(IAggregateCommand command)

30
tests/Squidex.Infrastructure.Tests/EventSourcing/Grains/EventConsumerGrainTests.cs

@ -98,7 +98,7 @@ namespace Squidex.Infrastructure.EventSourcing.Grains
{
state = state.Stopped();
await sut.OnActivateAsync(consumerName);
await sut.ActivateAsync(consumerName);
await sut.ActivateAsync();
state.Should().BeEquivalentTo(new EventConsumerState { IsStopped = true, Position = initialPosition, Error = null });
@ -110,7 +110,7 @@ namespace Squidex.Infrastructure.EventSourcing.Grains
[Fact]
public async Task Should_subscribe_to_event_store_when_not_found_in_db()
{
await sut.OnActivateAsync(consumerName);
await sut.ActivateAsync(consumerName);
await sut.ActivateAsync();
state.Should().BeEquivalentTo(new EventConsumerState { IsStopped = false, Position = initialPosition, Error = null });
@ -122,7 +122,7 @@ namespace Squidex.Infrastructure.EventSourcing.Grains
[Fact]
public async Task Should_subscribe_to_event_store_when_not_stopped_in_db()
{
await sut.OnActivateAsync(consumerName);
await sut.ActivateAsync(consumerName);
await sut.ActivateAsync();
state.Should().BeEquivalentTo(new EventConsumerState { IsStopped = false, Position = initialPosition, Error = null });
@ -134,7 +134,7 @@ namespace Squidex.Infrastructure.EventSourcing.Grains
[Fact]
public async Task Should_stop_subscription_when_stopped()
{
await sut.OnActivateAsync(consumerName);
await sut.ActivateAsync(consumerName);
await sut.ActivateAsync();
await sut.StopAsync();
await sut.StopAsync();
@ -151,7 +151,7 @@ namespace Squidex.Infrastructure.EventSourcing.Grains
[Fact]
public async Task Should_reset_consumer_when_resetting()
{
await sut.OnActivateAsync(consumerName);
await sut.ActivateAsync(consumerName);
await sut.ActivateAsync();
await sut.StopAsync();
await sut.ResetAsync();
@ -179,7 +179,7 @@ namespace Squidex.Infrastructure.EventSourcing.Grains
{
var @event = new StoredEvent("Stream", Guid.NewGuid().ToString(), 123, eventData);
await sut.OnActivateAsync(consumerName);
await sut.ActivateAsync(consumerName);
await sut.ActivateAsync();
await OnEventAsync(eventSubscription, @event);
@ -201,7 +201,7 @@ namespace Squidex.Infrastructure.EventSourcing.Grains
var @event = new StoredEvent("Stream", Guid.NewGuid().ToString(), 123, eventData);
await sut.OnActivateAsync(consumerName);
await sut.ActivateAsync(consumerName);
await sut.ActivateAsync();
await OnEventAsync(eventSubscription, @event);
@ -220,7 +220,7 @@ namespace Squidex.Infrastructure.EventSourcing.Grains
{
var @event = new StoredEvent("Stream", Guid.NewGuid().ToString(), 123, eventData);
await sut.OnActivateAsync(consumerName);
await sut.ActivateAsync(consumerName);
await sut.ActivateAsync();
await OnEventAsync(A.Fake<IEventSubscription>(), @event);
@ -234,7 +234,7 @@ namespace Squidex.Infrastructure.EventSourcing.Grains
[Fact]
public async Task Should_stop_if_consumer_failed()
{
await sut.OnActivateAsync(consumerName);
await sut.ActivateAsync(consumerName);
await sut.ActivateAsync();
var ex = new InvalidOperationException();
@ -255,7 +255,7 @@ namespace Squidex.Infrastructure.EventSourcing.Grains
{
var ex = new InvalidOperationException();
await sut.OnActivateAsync(consumerName);
await sut.ActivateAsync(consumerName);
await sut.ActivateAsync();
await OnErrorAsync(A.Fake<IEventSubscription>(), ex);
@ -269,7 +269,7 @@ namespace Squidex.Infrastructure.EventSourcing.Grains
[Fact]
public async Task Should_wakeup_when_already_subscribed()
{
await sut.OnActivateAsync(consumerName);
await sut.ActivateAsync(consumerName);
await sut.ActivateAsync();
await sut.ActivateAsync();
@ -285,7 +285,7 @@ namespace Squidex.Infrastructure.EventSourcing.Grains
A.CallTo(() => eventConsumer.ClearAsync())
.Throws(ex);
await sut.OnActivateAsync(consumerName);
await sut.ActivateAsync(consumerName);
await sut.ActivateAsync();
await sut.ResetAsync();
@ -308,7 +308,7 @@ namespace Squidex.Infrastructure.EventSourcing.Grains
var @event = new StoredEvent("Stream", Guid.NewGuid().ToString(), 123, eventData);
await sut.OnActivateAsync(consumerName);
await sut.ActivateAsync(consumerName);
await sut.ActivateAsync();
await OnEventAsync(eventSubscription, @event);
@ -335,7 +335,7 @@ namespace Squidex.Infrastructure.EventSourcing.Grains
var @event = new StoredEvent("Stream", Guid.NewGuid().ToString(), 123, eventData);
await sut.OnActivateAsync(consumerName);
await sut.ActivateAsync(consumerName);
await sut.ActivateAsync();
await OnEventAsync(eventSubscription, @event);
@ -362,7 +362,7 @@ namespace Squidex.Infrastructure.EventSourcing.Grains
var @event = new StoredEvent("Stream", Guid.NewGuid().ToString(), 123, eventData);
await sut.OnActivateAsync(consumerName);
await sut.ActivateAsync(consumerName);
await sut.ActivateAsync();
await OnEventAsync(eventSubscription, @event);

Loading…
Cancel
Save