mirror of https://github.com/Squidex/squidex.git
50 changed files with 958 additions and 612 deletions
@ -1,44 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using MongoDB.Bson; |
|||
using MongoDB.Bson.Serialization.Attributes; |
|||
using Squidex.Domain.Apps.Entities.Apps.State; |
|||
using Squidex.Infrastructure.MongoDb; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.MongoDb.Apps |
|||
{ |
|||
public sealed class MongoAppEntity : IVersionedEntity<Guid> |
|||
{ |
|||
[BsonId] |
|||
[BsonElement] |
|||
[BsonRepresentation(BsonType.String)] |
|||
public Guid Id { get; set; } |
|||
|
|||
[BsonElement] |
|||
[BsonRequired] |
|||
[BsonJson] |
|||
public AppState State { get; set; } |
|||
|
|||
[BsonElement] |
|||
[BsonRequired] |
|||
public long Version { get; set; } |
|||
|
|||
[BsonElement] |
|||
[BsonRequired] |
|||
public string Name { get; set; } |
|||
|
|||
[BsonElement] |
|||
[BsonRequired] |
|||
public string[] UserIds { get; set; } |
|||
|
|||
[BsonElement] |
|||
[BsonIgnoreIfDefault] |
|||
public bool IsArchived { get; set; } |
|||
} |
|||
} |
|||
@ -1,64 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using MongoDB.Bson; |
|||
using MongoDB.Driver; |
|||
using Squidex.Domain.Apps.Entities.Apps.Repositories; |
|||
using Squidex.Infrastructure.MongoDb; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.MongoDb.Apps |
|||
{ |
|||
public sealed partial class MongoAppRepository : MongoRepositoryBase<MongoAppEntity>, IAppRepository |
|||
{ |
|||
public MongoAppRepository(IMongoDatabase database) |
|||
: base(database) |
|||
{ |
|||
} |
|||
|
|||
protected override string CollectionName() |
|||
{ |
|||
return "States_Apps"; |
|||
} |
|||
|
|||
protected override async Task SetupCollectionAsync(IMongoCollection<MongoAppEntity> collection) |
|||
{ |
|||
await collection.Indexes.CreateOneAsync(Index.Ascending(x => x.UserIds)); |
|||
await collection.Indexes.CreateOneAsync(Index.Ascending(x => x.Name)); |
|||
} |
|||
|
|||
public async Task<IReadOnlyList<Guid>> QueryAppIdsAsync() |
|||
{ |
|||
var appEntities = |
|||
await Collection.Find(new BsonDocument()).Only(x => x.Id) |
|||
.ToListAsync(); |
|||
|
|||
return appEntities.Select(x => Guid.Parse(x["_id"].AsString)).ToList(); |
|||
} |
|||
|
|||
public async Task<IReadOnlyList<Guid>> QueryUserAppIdsAsync(string userId) |
|||
{ |
|||
var appEntities = |
|||
await Collection.Find(x => x.UserIds.Contains(userId) && x.IsArchived != true).Only(x => x.Id) |
|||
.ToListAsync(); |
|||
|
|||
return appEntities.Select(x => Guid.Parse(x["_id"].AsString)).ToList(); |
|||
} |
|||
|
|||
public async Task<Guid> FindAppIdByNameAsync(string name) |
|||
{ |
|||
var appEntity = |
|||
await Collection.Find(x => x.Name == name && x.IsArchived != true).Only(x => x.Id) |
|||
.FirstOrDefaultAsync(); |
|||
|
|||
return appEntity != null ? Guid.Parse(appEntity["_id"].AsString) : Guid.Empty; |
|||
} |
|||
} |
|||
} |
|||
@ -1,44 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using MongoDB.Driver; |
|||
using Squidex.Domain.Apps.Entities.Apps.State; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.MongoDb; |
|||
using Squidex.Infrastructure.States; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.MongoDb.Apps |
|||
{ |
|||
public sealed partial class MongoAppRepository : ISnapshotStore<AppState, Guid> |
|||
{ |
|||
public async Task<(AppState Value, long Version)> ReadAsync(Guid key) |
|||
{ |
|||
var existing = |
|||
await Collection.Find(x => x.Id == key) |
|||
.FirstOrDefaultAsync(); |
|||
|
|||
if (existing != null) |
|||
{ |
|||
return (existing.State, existing.Version); |
|||
} |
|||
|
|||
return (null, EtagVersion.NotFound); |
|||
} |
|||
|
|||
public Task WriteAsync(Guid key, AppState value, long oldVersion, long newVersion) |
|||
{ |
|||
return Collection.UpsertVersionedAsync(key, oldVersion, newVersion, u => u |
|||
.Set(x => x.Name, value.Name) |
|||
.Set(x => x.State, value) |
|||
.Set(x => x.UserIds, value.Contributors.Keys.ToArray()) |
|||
.Set(x => x.IsArchived, value.IsArchived)); |
|||
} |
|||
} |
|||
} |
|||
@ -1,41 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using MongoDB.Bson; |
|||
using MongoDB.Bson.Serialization.Attributes; |
|||
using Squidex.Domain.Apps.Entities.Rules.State; |
|||
using Squidex.Infrastructure.MongoDb; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.MongoDb.Rules |
|||
{ |
|||
public sealed class MongoRuleEntity : IVersionedEntity<Guid> |
|||
{ |
|||
[BsonId] |
|||
[BsonElement] |
|||
[BsonRepresentation(BsonType.String)] |
|||
public Guid Id { get; set; } |
|||
|
|||
[BsonElement] |
|||
[BsonRequired] |
|||
[BsonRepresentation(BsonType.String)] |
|||
public Guid AppId { get; set; } |
|||
|
|||
[BsonElement] |
|||
[BsonRequired] |
|||
[BsonJson] |
|||
public RuleState State { get; set; } |
|||
|
|||
[BsonElement] |
|||
[BsonRequired] |
|||
public long Version { get; set; } |
|||
|
|||
[BsonElement] |
|||
[BsonRequired] |
|||
public bool IsDeleted { get; set; } |
|||
} |
|||
} |
|||
@ -1,45 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using MongoDB.Driver; |
|||
using Squidex.Domain.Apps.Entities.Rules.Repositories; |
|||
using Squidex.Infrastructure.MongoDb; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.MongoDb.Rules |
|||
{ |
|||
public sealed partial class MongoRuleRepository : MongoRepositoryBase<MongoRuleEntity>, IRuleRepository |
|||
{ |
|||
public MongoRuleRepository(IMongoDatabase database) |
|||
: base(database) |
|||
{ |
|||
} |
|||
|
|||
protected override string CollectionName() |
|||
{ |
|||
return "States_Rules"; |
|||
} |
|||
|
|||
protected override async Task SetupCollectionAsync(IMongoCollection<MongoRuleEntity> collection) |
|||
{ |
|||
await collection.Indexes.CreateOneAsync(Index.Ascending(x => x.AppId)); |
|||
await collection.Indexes.CreateOneAsync(Index.Ascending(x => x.IsDeleted)); |
|||
} |
|||
|
|||
public async Task<IReadOnlyList<Guid>> QueryRuleIdsAsync(Guid appId) |
|||
{ |
|||
var ruleEntities = |
|||
await Collection.Find(x => x.AppId == appId && !x.IsDeleted).Only(x => x.Id) |
|||
.ToListAsync(); |
|||
|
|||
return ruleEntities.Select(x => Guid.Parse(x["_id"].AsString)).ToList(); |
|||
} |
|||
} |
|||
} |
|||
@ -1,42 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using MongoDB.Driver; |
|||
using Squidex.Domain.Apps.Entities.Rules.State; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.MongoDb; |
|||
using Squidex.Infrastructure.States; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.MongoDb.Rules |
|||
{ |
|||
public sealed partial class MongoRuleRepository : ISnapshotStore<RuleState, Guid> |
|||
{ |
|||
public async Task<(RuleState Value, long Version)> ReadAsync(Guid key) |
|||
{ |
|||
var existing = |
|||
await Collection.Find(x => x.Id == key) |
|||
.FirstOrDefaultAsync(); |
|||
|
|||
if (existing != null) |
|||
{ |
|||
return (existing.State, existing.Version); |
|||
} |
|||
|
|||
return (null, EtagVersion.NotFound); |
|||
} |
|||
|
|||
public Task WriteAsync(Guid key, RuleState value, long oldVersion, long newVersion) |
|||
{ |
|||
return Collection.UpsertVersionedAsync(key, oldVersion, newVersion, u => u |
|||
.Set(x => x.State, value) |
|||
.Set(x => x.AppId, value.AppId.Id) |
|||
.Set(x => x.IsDeleted, value.IsDeleted)); |
|||
} |
|||
} |
|||
} |
|||
@ -1,45 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using MongoDB.Bson; |
|||
using MongoDB.Bson.Serialization.Attributes; |
|||
using Squidex.Domain.Apps.Entities.Schemas.State; |
|||
using Squidex.Infrastructure.MongoDb; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.MongoDb.Schemas |
|||
{ |
|||
public sealed class MongoSchemaEntity : IVersionedEntity<Guid> |
|||
{ |
|||
[BsonId] |
|||
[BsonElement] |
|||
[BsonRepresentation(BsonType.String)] |
|||
public Guid Id { get; set; } |
|||
|
|||
[BsonElement] |
|||
[BsonRequired] |
|||
[BsonRepresentation(BsonType.String)] |
|||
public Guid AppId { get; set; } |
|||
|
|||
[BsonElement] |
|||
[BsonRequired] |
|||
[BsonJson] |
|||
public SchemaState State { get; set; } |
|||
|
|||
[BsonElement] |
|||
[BsonRequired] |
|||
public string Name { get; set; } |
|||
|
|||
[BsonElement] |
|||
[BsonRequired] |
|||
public long Version { get; set; } |
|||
|
|||
[BsonElement] |
|||
[BsonRequired] |
|||
public bool IsDeleted { get; set; } |
|||
} |
|||
} |
|||
@ -1,54 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using MongoDB.Driver; |
|||
using Squidex.Domain.Apps.Entities.Schemas.Repositories; |
|||
using Squidex.Infrastructure.MongoDb; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.MongoDb.Schemas |
|||
{ |
|||
public sealed partial class MongoSchemaRepository : MongoRepositoryBase<MongoSchemaEntity>, ISchemaRepository |
|||
{ |
|||
public MongoSchemaRepository(IMongoDatabase database) |
|||
: base(database) |
|||
{ |
|||
} |
|||
|
|||
protected override string CollectionName() |
|||
{ |
|||
return "States_Schemas"; |
|||
} |
|||
|
|||
protected override async Task SetupCollectionAsync(IMongoCollection<MongoSchemaEntity> collection) |
|||
{ |
|||
await collection.Indexes.CreateOneAsync(Index.Ascending(x => x.AppId).Ascending(x => x.IsDeleted)); |
|||
await collection.Indexes.CreateOneAsync(Index.Ascending(x => x.AppId).Ascending(x => x.Name).Ascending(x => x.IsDeleted)); |
|||
} |
|||
|
|||
public async Task<Guid> FindSchemaIdAsync(Guid appId, string name) |
|||
{ |
|||
var schemaEntity = |
|||
await Collection.Find(x => x.AppId == appId && x.Name == name && !x.IsDeleted).Only(x => x.Id).SortByDescending(x => x.Version) |
|||
.FirstOrDefaultAsync(); |
|||
|
|||
return schemaEntity != null ? Guid.Parse(schemaEntity["_id"].AsString) : Guid.Empty; |
|||
} |
|||
|
|||
public async Task<IReadOnlyList<Guid>> QuerySchemaIdsAsync(Guid appId) |
|||
{ |
|||
var schemaEntities = |
|||
await Collection.Find(x => x.AppId == appId && !x.IsDeleted).Only(x => x.Id) |
|||
.ToListAsync(); |
|||
|
|||
return schemaEntities.Select(x => Guid.Parse(x["_id"].AsString)).ToList(); |
|||
} |
|||
} |
|||
} |
|||
@ -1,43 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using MongoDB.Driver; |
|||
using Squidex.Domain.Apps.Entities.Schemas.State; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.MongoDb; |
|||
using Squidex.Infrastructure.States; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.MongoDb.Schemas |
|||
{ |
|||
public sealed partial class MongoSchemaRepository : ISnapshotStore<SchemaState, Guid> |
|||
{ |
|||
public async Task<(SchemaState Value, long Version)> ReadAsync(Guid key) |
|||
{ |
|||
var existing = |
|||
await Collection.Find(x => x.Id == key) |
|||
.FirstOrDefaultAsync(); |
|||
|
|||
if (existing != null) |
|||
{ |
|||
return (existing.State, existing.Version); |
|||
} |
|||
|
|||
return (null, EtagVersion.NotFound); |
|||
} |
|||
|
|||
public Task WriteAsync(Guid key, SchemaState value, long oldVersion, long newVersion) |
|||
{ |
|||
return Collection.UpsertVersionedAsync(key, oldVersion, newVersion, u => u |
|||
.Set(x => x.State, value) |
|||
.Set(x => x.AppId, value.AppId.Id) |
|||
.Set(x => x.Name, value.Name) |
|||
.Set(x => x.IsDeleted, value.IsDeleted)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,47 @@ |
|||
// ==========================================================================
|
|||
// 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.Domain.Apps.Entities.Apps.Commands; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Commands; |
|||
using Squidex.Infrastructure.Orleans; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Apps.Indexes |
|||
{ |
|||
public sealed class AppsByNameIndexCommandMiddleware : ICommandMiddleware |
|||
{ |
|||
private readonly IAppsByNameIndex index; |
|||
|
|||
public AppsByNameIndexCommandMiddleware(IGrainFactory grainFactory) |
|||
{ |
|||
Guard.NotNull(grainFactory, nameof(grainFactory)); |
|||
|
|||
index = grainFactory.GetGrain<IAppsByNameIndex>(SingleGrain.Id); |
|||
} |
|||
|
|||
public async Task HandleAsync(CommandContext context, Func<Task> next) |
|||
{ |
|||
if (context.IsCompleted) |
|||
{ |
|||
switch (context.Command) |
|||
{ |
|||
case CreateApp createApp: |
|||
await index.AddAppAsync(createApp.AppId, createApp.Name); |
|||
break; |
|||
case ArchiveApp archiveApp: |
|||
await index.RemoveAppAsync(archiveApp.AppId); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
await next(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,80 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
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 AppsByNameIndexGrain : GrainOfString, IAppsByNameIndex |
|||
{ |
|||
private readonly IStore<string> store; |
|||
private IPersistence<State> persistence; |
|||
private State state = new State(); |
|||
|
|||
[CollectionName("Index_AppsByName")] |
|||
private sealed class State |
|||
{ |
|||
public Dictionary<string, Guid> Apps { get; set; } = new Dictionary<string, Guid>(); |
|||
} |
|||
|
|||
public AppsByNameIndexGrain(IStore<string> 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 }; |
|||
|
|||
return persistence.WriteSnapshotAsync(state); |
|||
} |
|||
|
|||
public Task AddAppAsync(Guid appId, string name) |
|||
{ |
|||
state.Apps[name] = appId; |
|||
|
|||
return persistence.WriteSnapshotAsync(state); |
|||
} |
|||
|
|||
public Task RemoveAppAsync(Guid appId) |
|||
{ |
|||
state.Apps.Remove(state.Apps.FirstOrDefault(x => x.Value == appId).Key ?? string.Empty); |
|||
|
|||
return persistence.WriteSnapshotAsync(state); |
|||
} |
|||
|
|||
public Task<Guid> GetAppIdAsync(string appName) |
|||
{ |
|||
state.Apps.TryGetValue(appName, out var appId); |
|||
|
|||
return Task.FromResult(appId); |
|||
} |
|||
|
|||
public Task<List<Guid>> GetAppIdAsync() |
|||
{ |
|||
return Task.FromResult(state.Apps.Values.ToList()); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,80 @@ |
|||
// ==========================================================================
|
|||
// 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.Domain.Apps.Entities.Apps.Commands; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Commands; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Apps.Indexes |
|||
{ |
|||
public sealed class AppsByUserIndexCommandMiddleware : ICommandMiddleware |
|||
{ |
|||
private readonly IGrainFactory grainFactory; |
|||
|
|||
public AppsByUserIndexCommandMiddleware(IGrainFactory grainFactory) |
|||
{ |
|||
Guard.NotNull(grainFactory, nameof(grainFactory)); |
|||
|
|||
this.grainFactory = grainFactory; |
|||
} |
|||
|
|||
public async Task HandleAsync(CommandContext context, Func<Task> next) |
|||
{ |
|||
if (context.IsCompleted) |
|||
{ |
|||
switch (context.Command) |
|||
{ |
|||
case CreateApp createApp: |
|||
await Index(GetUserId(createApp)).AddAppAsync(createApp.AppId); |
|||
break; |
|||
case AssignContributor assignContributor: |
|||
await Index(GetUserId(context)).AddAppAsync(assignContributor.AppId); |
|||
break; |
|||
case RemoveContributor removeContributor: |
|||
await Index(GetUserId(removeContributor)).RemoveAppAsync(removeContributor.AppId); |
|||
break; |
|||
case ArchiveApp archiveApp: |
|||
{ |
|||
var appState = await grainFactory.GetGrain<IAppGrain>(archiveApp.AppId).GetStateAsync(); |
|||
|
|||
foreach (var contributorId in appState.Value.Contributors.Keys) |
|||
{ |
|||
await Index(contributorId).RemoveAppAsync(archiveApp.AppId); |
|||
} |
|||
|
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
await next(); |
|||
} |
|||
|
|||
private static string GetUserId(RemoveContributor removeContributor) |
|||
{ |
|||
return removeContributor.ContributorId; |
|||
} |
|||
|
|||
private static string GetUserId(CreateApp createApp) |
|||
{ |
|||
return createApp.Actor.Identifier; |
|||
} |
|||
|
|||
private static string GetUserId(CommandContext context) |
|||
{ |
|||
return context.Result<EntityCreatedResult<string>>().IdOrValue; |
|||
} |
|||
|
|||
private IAppsByUserIndex Index(string id) |
|||
{ |
|||
return grainFactory.GetGrain<IAppsByUserIndex>(id); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,73 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
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 |
|||
{ |
|||
private readonly IStore<string> store; |
|||
private IPersistence<State> persistence; |
|||
private State state = new State(); |
|||
|
|||
[CollectionName("Index_AppsByUser")] |
|||
private sealed class State |
|||
{ |
|||
public HashSet<Guid> Apps { get; set; } = new HashSet<Guid>(); |
|||
} |
|||
|
|||
public AppsByUserIndexGrain(IStore<string> 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 }; |
|||
|
|||
return persistence.WriteSnapshotAsync(state); |
|||
} |
|||
|
|||
public Task AddAppAsync(Guid appId) |
|||
{ |
|||
state.Apps.Add(appId); |
|||
|
|||
return persistence.WriteSnapshotAsync(state); |
|||
} |
|||
|
|||
public Task RemoveAppAsync(Guid appId) |
|||
{ |
|||
state.Apps.Remove(appId); |
|||
|
|||
return persistence.WriteSnapshotAsync(state); |
|||
} |
|||
|
|||
public Task<List<Guid>> GetAppIdsAsync() |
|||
{ |
|||
return Task.FromResult(state.Apps.ToList()); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using Orleans; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Apps |
|||
{ |
|||
public interface IAppsByNameIndex : IGrainWithStringKey |
|||
{ |
|||
Task AddAppAsync(Guid appId, string name); |
|||
|
|||
Task RemoveAppAsync(Guid appId); |
|||
|
|||
Task RebuildAsync(Dictionary<string, Guid> apps); |
|||
|
|||
Task<Guid> GetAppIdAsync(string name); |
|||
|
|||
Task<List<Guid>> GetAppIdAsync(); |
|||
} |
|||
} |
|||
@ -1,22 +1,25 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using Orleans; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Apps.Repositories |
|||
namespace Squidex.Domain.Apps.Entities.Apps |
|||
{ |
|||
public interface IAppRepository |
|||
public interface IAppsByUserIndex : IGrainWithStringKey |
|||
{ |
|||
Task<Guid> FindAppIdByNameAsync(string name); |
|||
Task AddAppAsync(Guid appId); |
|||
|
|||
Task<IReadOnlyList<Guid>> QueryAppIdsAsync(); |
|||
Task RemoveAppAsync(Guid appId); |
|||
|
|||
Task<IReadOnlyList<Guid>> QueryUserAppIdsAsync(string userId); |
|||
Task RebuildAsync(HashSet<Guid> apps); |
|||
|
|||
Task<List<Guid>> GetAppIdsAsync(); |
|||
} |
|||
} |
|||
@ -1,26 +0,0 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using Newtonsoft.Json; |
|||
using NodaTime; |
|||
using Squidex.Domain.Apps.Core.Contents; |
|||
using Squidex.Infrastructure; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Contents.State |
|||
{ |
|||
public sealed class ContentStateScheduleItem : IContentScheduleItem |
|||
{ |
|||
[JsonProperty] |
|||
public Instant ScheduledAt { get; set; } |
|||
|
|||
[JsonProperty] |
|||
public RefToken ScheduledBy { get; set; } |
|||
|
|||
[JsonProperty] |
|||
public Status ScheduledTo { get; set; } |
|||
} |
|||
} |
|||
@ -1,20 +1,25 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using Orleans; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Schemas.Repositories |
|||
namespace Squidex.Domain.Apps.Entities.Rules |
|||
{ |
|||
public interface ISchemaRepository |
|||
public interface IRulesByAppIndex : IGrainWithGuidKey |
|||
{ |
|||
Task<Guid> FindSchemaIdAsync(Guid appId, string name); |
|||
Task AddRuleAsync(Guid ruleId); |
|||
|
|||
Task<IReadOnlyList<Guid>> QuerySchemaIdsAsync(Guid appId); |
|||
Task RemoveRuleAsync(Guid ruleId); |
|||
|
|||
Task RebuildAsync(HashSet<Guid> rules); |
|||
|
|||
Task<List<Guid>> GetRuleIdsAsync(); |
|||
} |
|||
} |
|||
@ -0,0 +1,56 @@ |
|||
// ==========================================================================
|
|||
// 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.Domain.Apps.Entities.Rules.Commands; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Commands; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Rules.Indexes |
|||
{ |
|||
public sealed class RulesByAppIndexCommandMiddleware : ICommandMiddleware |
|||
{ |
|||
private readonly IGrainFactory grainFactory; |
|||
|
|||
public RulesByAppIndexCommandMiddleware(IGrainFactory grainFactory) |
|||
{ |
|||
Guard.NotNull(grainFactory, nameof(grainFactory)); |
|||
|
|||
this.grainFactory = grainFactory; |
|||
} |
|||
|
|||
public async Task HandleAsync(CommandContext context, Func<Task> next) |
|||
{ |
|||
if (context.IsCompleted) |
|||
{ |
|||
switch (context.Command) |
|||
{ |
|||
case CreateRule createRule: |
|||
await Index(createRule.AppId.Id).AddRuleAsync(createRule.RuleId); |
|||
break; |
|||
case DeleteRule deleteRule: |
|||
{ |
|||
var schema = await grainFactory.GetGrain<IRuleGrain>(deleteRule.RuleId).GetStateAsync(); |
|||
|
|||
await Index(schema.Value.AppId.Id).RemoveRuleAsync(deleteRule.RuleId); |
|||
|
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
await next(); |
|||
} |
|||
|
|||
private IRulesByAppIndex Index(Guid appId) |
|||
{ |
|||
return grainFactory.GetGrain<IRulesByAppIndex>(appId); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,73 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
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.Rules.Indexes |
|||
{ |
|||
public sealed class RulesByAppIndexGrain : GrainOfGuid, IRulesByAppIndex |
|||
{ |
|||
private readonly IStore<Guid> store; |
|||
private IPersistence<State> persistence; |
|||
private State state = new State(); |
|||
|
|||
[CollectionName("Index_RulesByApp")] |
|||
private sealed class State |
|||
{ |
|||
public HashSet<Guid> Rules { get; set; } = new HashSet<Guid>(); |
|||
} |
|||
|
|||
public RulesByAppIndexGrain(IStore<Guid> 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 RebuildAsync(HashSet<Guid> rules) |
|||
{ |
|||
state = new State { Rules = rules }; |
|||
|
|||
return persistence.WriteSnapshotAsync(state); |
|||
} |
|||
|
|||
public Task AddRuleAsync(Guid ruleId) |
|||
{ |
|||
state.Rules.Add(ruleId); |
|||
|
|||
return persistence.WriteSnapshotAsync(state); |
|||
} |
|||
|
|||
public Task RemoveRuleAsync(Guid ruleId) |
|||
{ |
|||
state.Rules.Remove(ruleId); |
|||
|
|||
return persistence.WriteSnapshotAsync(state); |
|||
} |
|||
|
|||
public Task<List<Guid>> GetRuleIdsAsync() |
|||
{ |
|||
return Task.FromResult(state.Rules.ToList()); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using Orleans; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Schemas |
|||
{ |
|||
public interface ISchemasByAppIndex : IGrainWithGuidKey |
|||
{ |
|||
Task AddSchemaAsync(Guid schemaId, string name); |
|||
|
|||
Task RemoveSchemaAsync(Guid schemaId); |
|||
|
|||
Task RebuildAsync(Dictionary<string, Guid> schemas); |
|||
|
|||
Task<Guid> GetSchemaIdAsync(string name); |
|||
|
|||
Task<List<Guid>> GetSchemaIdsAsync(); |
|||
} |
|||
} |
|||
@ -0,0 +1,56 @@ |
|||
// ==========================================================================
|
|||
// 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.Domain.Apps.Entities.Schemas.Commands; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Commands; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Schemas.Indexes |
|||
{ |
|||
public sealed class SchemasByAppIndexCommandMiddleware : ICommandMiddleware |
|||
{ |
|||
private readonly IGrainFactory grainFactory; |
|||
|
|||
public SchemasByAppIndexCommandMiddleware(IGrainFactory grainFactory) |
|||
{ |
|||
Guard.NotNull(grainFactory, nameof(grainFactory)); |
|||
|
|||
this.grainFactory = grainFactory; |
|||
} |
|||
|
|||
public async Task HandleAsync(CommandContext context, Func<Task> next) |
|||
{ |
|||
if (context.IsCompleted) |
|||
{ |
|||
switch (context.Command) |
|||
{ |
|||
case CreateSchema createSchema: |
|||
await Index(createSchema.AppId.Id).AddSchemaAsync(createSchema.SchemaId, createSchema.Name); |
|||
break; |
|||
case DeleteSchema deleteSchema: |
|||
{ |
|||
var schema = await grainFactory.GetGrain<ISchemaGrain>(deleteSchema.SchemaId).GetStateAsync(); |
|||
|
|||
await Index(schema.Value.AppId.Id).RemoveSchemaAsync(deleteSchema.SchemaId); |
|||
|
|||
break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
await next(); |
|||
} |
|||
|
|||
private ISchemasByAppIndex Index(Guid appId) |
|||
{ |
|||
return grainFactory.GetGrain<ISchemasByAppIndex>(appId); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,80 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
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.Schemas.Indexes |
|||
{ |
|||
public sealed class SchemasByAppIndexGrain : GrainOfGuid, ISchemasByAppIndex |
|||
{ |
|||
private readonly IStore<Guid> store; |
|||
private IPersistence<State> persistence; |
|||
private State state = new State(); |
|||
|
|||
[CollectionName("Index_SchemasByApp")] |
|||
private sealed class State |
|||
{ |
|||
public Dictionary<string, Guid> Schemas { get; set; } = new Dictionary<string, Guid>(); |
|||
} |
|||
|
|||
public SchemasByAppIndexGrain(IStore<Guid> 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 RebuildAsync(Dictionary<string, Guid> schemas) |
|||
{ |
|||
state = new State { Schemas = schemas }; |
|||
|
|||
return persistence.WriteSnapshotAsync(state); |
|||
} |
|||
|
|||
public Task AddSchemaAsync(Guid schemaId, string name) |
|||
{ |
|||
state.Schemas[name] = schemaId; |
|||
|
|||
return persistence.WriteSnapshotAsync(state); |
|||
} |
|||
|
|||
public Task RemoveSchemaAsync(Guid schemaId) |
|||
{ |
|||
state.Schemas.Remove(state.Schemas.FirstOrDefault(x => x.Value == schemaId).Key ?? string.Empty); |
|||
|
|||
return persistence.WriteSnapshotAsync(state); |
|||
} |
|||
|
|||
public Task<Guid> GetSchemaIdAsync(string name) |
|||
{ |
|||
state.Schemas.TryGetValue(name, out var schemaId); |
|||
|
|||
return Task.FromResult(schemaId); |
|||
} |
|||
|
|||
public Task<List<Guid>> GetSchemaIdsAsync() |
|||
{ |
|||
return Task.FromResult(state.Schemas.Values.ToList()); |
|||
} |
|||
} |
|||
} |
|||
@ -1,18 +1,14 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschränkt)
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Squidex.Domain.Apps.Entities.Rules.Repositories |
|||
namespace Squidex.Infrastructure.Orleans |
|||
{ |
|||
public interface IRuleRepository |
|||
public static class SingleGrain |
|||
{ |
|||
Task<IReadOnlyList<Guid>> QueryRuleIdsAsync(Guid appId); |
|||
public const string Id = "Default"; |
|||
} |
|||
} |
|||
@ -0,0 +1,44 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using MongoDB.Bson; |
|||
using MongoDB.Driver; |
|||
using Squidex.Infrastructure.Migrations; |
|||
|
|||
namespace Migrate_01.Migrations |
|||
{ |
|||
public sealed class ConvertOldSnapshotStores : IMigration |
|||
{ |
|||
private readonly IMongoDatabase database; |
|||
|
|||
public ConvertOldSnapshotStores(IMongoDatabase database) |
|||
{ |
|||
this.database = database; |
|||
} |
|||
|
|||
public Task UpdateAsync() |
|||
{ |
|||
var collections = new[] |
|||
{ |
|||
"States_Apps", |
|||
"States_Rules", |
|||
"States_Schemas" |
|||
}; |
|||
|
|||
var update = Builders<BsonDocument>.Update.Rename("State", "Doc"); |
|||
|
|||
var filter = new BsonDocument(); |
|||
|
|||
return Task.WhenAll( |
|||
collections |
|||
.Select(x => database.GetCollection<BsonDocument>(x)) |
|||
.Select(x => x.UpdateManyAsync(filter, update))); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,127 @@ |
|||
// ==========================================================================
|
|||
// Squidex Headless CMS
|
|||
// ==========================================================================
|
|||
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|||
// All rights reserved. Licensed under the MIT license.
|
|||
// ==========================================================================
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading.Tasks; |
|||
using Orleans; |
|||
using Squidex.Domain.Apps.Entities.Apps; |
|||
using Squidex.Domain.Apps.Entities.Apps.State; |
|||
using Squidex.Domain.Apps.Entities.Rules; |
|||
using Squidex.Domain.Apps.Entities.Rules.State; |
|||
using Squidex.Domain.Apps.Entities.Schemas; |
|||
using Squidex.Domain.Apps.Entities.Schemas.State; |
|||
using Squidex.Infrastructure; |
|||
using Squidex.Infrastructure.Migrations; |
|||
using Squidex.Infrastructure.Orleans; |
|||
using Squidex.Infrastructure.States; |
|||
using Squidex.Infrastructure.Tasks; |
|||
|
|||
namespace Migrate_01.Migrations |
|||
{ |
|||
public class PopulateGrainIndexes : IMigration |
|||
{ |
|||
private readonly IGrainFactory grainFactory; |
|||
private readonly ISnapshotStore<AppState, Guid> statesForApps; |
|||
private readonly ISnapshotStore<RuleState, Guid> statesForRules; |
|||
private readonly ISnapshotStore<SchemaState, Guid> statesForSchemas; |
|||
|
|||
public PopulateGrainIndexes( |
|||
IGrainFactory grainFactory, |
|||
ISnapshotStore<AppState, Guid> statesForApps, |
|||
ISnapshotStore<RuleState, Guid> statesForRules, |
|||
ISnapshotStore<SchemaState, Guid> statesForSchemas) |
|||
{ |
|||
this.grainFactory = grainFactory; |
|||
this.statesForApps = statesForApps; |
|||
this.statesForRules = statesForRules; |
|||
this.statesForSchemas = statesForSchemas; |
|||
} |
|||
|
|||
public Task UpdateAsync() |
|||
{ |
|||
return Task.WhenAll( |
|||
RebuildAppIndexes(), |
|||
RebuildRuleIndexes(), |
|||
RebuildSchemaIndexes()); |
|||
} |
|||
|
|||
private async Task RebuildAppIndexes() |
|||
{ |
|||
var appsByName = new Dictionary<string, Guid>(); |
|||
var appsByUser = new Dictionary<string, HashSet<Guid>>(); |
|||
|
|||
await statesForApps.ReadAllAsync((app, version) => |
|||
{ |
|||
if (!app.IsArchived) |
|||
{ |
|||
appsByName[app.Name] = app.Id; |
|||
|
|||
foreach (var contributor in app.Contributors.Keys) |
|||
{ |
|||
appsByUser.GetOrAddNew(contributor).Add(app.Id); |
|||
} |
|||
} |
|||
|
|||
return TaskHelper.Done; |
|||
}); |
|||
|
|||
var tasks = |
|||
appsByUser.Select(x => |
|||
grainFactory.GetGrain<IAppsByUserIndex>(x.Key).RebuildAsync(x.Value)) |
|||
.Union(new[] |
|||
{ |
|||
grainFactory.GetGrain<IAppsByNameIndex>(SingleGrain.Id).RebuildAsync(appsByName) |
|||
}); |
|||
|
|||
await Task.WhenAll(tasks); |
|||
} |
|||
|
|||
private async Task RebuildRuleIndexes() |
|||
{ |
|||
var schemasByApp = new Dictionary<Guid, HashSet<Guid>>(); |
|||
|
|||
await statesForRules.ReadAllAsync((schema, version) => |
|||
{ |
|||
if (!schema.IsDeleted) |
|||
{ |
|||
schemasByApp.GetOrAddNew(schema.AppId.Id).Add(schema.Id); |
|||
} |
|||
|
|||
return TaskHelper.Done; |
|||
}); |
|||
|
|||
var tasks = |
|||
schemasByApp.Select(x => |
|||
grainFactory.GetGrain<IRulesByAppIndex>(x.Key).RebuildAsync(x.Value)); |
|||
|
|||
await Task.WhenAll(tasks); |
|||
} |
|||
|
|||
private async Task RebuildSchemaIndexes() |
|||
{ |
|||
var schemasByApp = new Dictionary<Guid, Dictionary<string, Guid>>(); |
|||
|
|||
await statesForSchemas.ReadAllAsync((schema, version) => |
|||
{ |
|||
if (!schema.IsDeleted) |
|||
{ |
|||
schemasByApp.GetOrAddNew(schema.AppId.Id).Add(schema.Name, schema.Id); |
|||
} |
|||
|
|||
return TaskHelper.Done; |
|||
}); |
|||
|
|||
var tasks = |
|||
schemasByApp.Select(x => |
|||
grainFactory.GetGrain<ISchemasByAppIndex>(x.Key).RebuildAsync(x.Value)); |
|||
|
|||
await Task.WhenAll(tasks); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue