diff --git a/src/Squidex.Domain.Apps.Core.Model/Apps/Json/JsonAppPattern.cs b/src/Squidex.Domain.Apps.Core.Model/Apps/Json/JsonAppPattern.cs index 57364a197..be9dac550 100644 --- a/src/Squidex.Domain.Apps.Core.Model/Apps/Json/JsonAppPattern.cs +++ b/src/Squidex.Domain.Apps.Core.Model/Apps/Json/JsonAppPattern.cs @@ -5,7 +5,6 @@ // Copyright (c) Squidex Group // All rights reserved. // ========================================================================== -using System; using Newtonsoft.Json; using Squidex.Infrastructure.Reflection; diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Apps/MongoAppRepository.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Apps/MongoAppRepository.cs index 26cf396fe..dea2d0b06 100644 --- a/src/Squidex.Domain.Apps.Entities.MongoDb/Apps/MongoAppRepository.cs +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Apps/MongoAppRepository.cs @@ -13,14 +13,11 @@ using System.Threading.Tasks; using MongoDB.Bson; using MongoDB.Driver; using Squidex.Domain.Apps.Entities.Apps.Repositories; -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 class MongoAppRepository : MongoRepositoryBase, IAppRepository, ISnapshotStore + public sealed partial class MongoAppRepository : MongoRepositoryBase, IAppRepository { public MongoAppRepository(IMongoDatabase database) : base(database) @@ -38,15 +35,6 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Apps await collection.Indexes.CreateOneAsync(Index.Ascending(x => x.Name)); } - public async Task FindAppIdByNameAsync(string name) - { - var appEntity = - await Collection.Find(x => x.Name == name).Only(x => x.Id) - .FirstOrDefaultAsync(); - - return appEntity != null ? Guid.Parse(appEntity["_id"].AsString) : Guid.Empty; - } - public async Task> QueryAppIdsAsync() { var appEntities = @@ -65,50 +53,13 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Apps return appEntities.Select(x => Guid.Parse(x["_id"].AsString)).ToList(); } - public async Task<(AppState Value, long Version)> ReadAsync(Guid key) + public async Task FindAppIdByNameAsync(string name) { - var existing = - await Collection.Find(x => x.Id == key) + var appEntity = + await Collection.Find(x => x.Name == name).Only(x => x.Id) .FirstOrDefaultAsync(); - if (existing != null) - { - return (existing.State, existing.Version); - } - - return (null, EtagVersion.NotFound); - } - - public async Task WriteAsync(Guid key, AppState value, long oldVersion, long newVersion) - { - try - { - await Collection.UpdateOneAsync(x => x.Id == key && x.Version == oldVersion, - Update - .Set(x => x.UserIds, value.Contributors.Keys.ToArray()) - .Set(x => x.Name, value.Name) - .Set(x => x.State, value) - .Set(x => x.Version, newVersion), - Upsert); - } - catch (MongoWriteException ex) - { - if (ex.WriteError.Category == ServerErrorCategory.DuplicateKey) - { - var existingVersion = - await Collection.Find(x => x.Id == key) - .Project(Projection.Exclude(x => x.Id)).FirstOrDefaultAsync(); - - if (existingVersion != null) - { - throw new InconsistentStateException(existingVersion.Version, oldVersion, ex); - } - } - else - { - throw; - } - } + return appEntity != null ? Guid.Parse(appEntity["_id"].AsString) : Guid.Empty; } } } diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Apps/MongoAppRepository_SnapshotStore.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Apps/MongoAppRepository_SnapshotStore.cs new file mode 100644 index 000000000..c040a9fa8 --- /dev/null +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Apps/MongoAppRepository_SnapshotStore.cs @@ -0,0 +1,67 @@ +// ========================================================================== +// MongoAppRepository_SnapshotStore.cs +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex Group +// All rights reserved. +// ========================================================================== + +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.States; + +namespace Squidex.Domain.Apps.Entities.MongoDb.Apps +{ + public sealed partial class MongoAppRepository : ISnapshotStore + { + 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 async Task WriteAsync(Guid key, AppState value, long oldVersion, long newVersion) + { + try + { + await Collection.UpdateOneAsync(x => x.Id == key && x.Version == oldVersion, + Update + .Set(x => x.UserIds, value.Contributors.Keys.ToArray()) + .Set(x => x.Name, value.Name) + .Set(x => x.State, value) + .Set(x => x.Version, newVersion), + Upsert); + } + catch (MongoWriteException ex) + { + if (ex.WriteError.Category == ServerErrorCategory.DuplicateKey) + { + var existingVersion = + await Collection.Find(x => x.Id == key) + .Project(Projection.Exclude(x => x.Id)).FirstOrDefaultAsync(); + + if (existingVersion != null) + { + throw new InconsistentStateException(existingVersion.Version, oldVersion, ex); + } + } + else + { + throw; + } + } + } + } +} diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository.cs index fc0581b80..ea08ad032 100644 --- a/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository.cs +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository.cs @@ -14,14 +14,12 @@ using MongoDB.Bson; using MongoDB.Driver; using Squidex.Domain.Apps.Entities.Assets; using Squidex.Domain.Apps.Entities.Assets.Repositories; -using Squidex.Domain.Apps.Entities.Assets.State; using Squidex.Infrastructure; using Squidex.Infrastructure.MongoDb; -using Squidex.Infrastructure.States; namespace Squidex.Domain.Apps.Entities.MongoDb.Assets { - public sealed class MongoAssetRepository : MongoRepositoryBase, IAssetRepository, ISnapshotStore + public sealed partial class MongoAssetRepository : MongoRepositoryBase, IAssetRepository { public MongoAssetRepository(IMongoDatabase database) : base(database) @@ -71,67 +69,21 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets var find = Collection.Find(filter); - var assetEntities = - Collection.Find(filter).Skip(skip).Limit(take).SortByDescending(x => x.State.LastModified) - .ToListAsync(); - var assetCount = - Collection.Find(filter) - .CountAsync(); + var assetItems = find.Skip(skip).Limit(take).SortByDescending(x => x.State.LastModified).ToListAsync(); + var assetCount = find.CountAsync(); - await Task.WhenAll(assetEntities, assetCount); + await Task.WhenAll(assetItems, assetCount); - return ResultList.Create(assetEntities.Result.Select(x => x.State), assetCount.Result); + return ResultList.Create(assetItems.Result.Select(x => x.State), assetCount.Result); } public async Task FindAssetAsync(Guid id) { - var (state, etag) = await ReadAsync(id); - - return state; - } - - public async Task<(AssetState Value, long Version)> ReadAsync(Guid key) - { - var existing = - await Collection.Find(x => x.Id == key) + var assetEntity = + await Collection.Find(x => x.Id == id) .FirstOrDefaultAsync(); - if (existing != null) - { - return (existing.State, existing.Version); - } - - return (null, EtagVersion.NotFound); - } - - public async Task WriteAsync(Guid key, AssetState value, long oldVersion, long newVersion) - { - try - { - await Collection.UpdateOneAsync(x => x.Id == key && x.Version == oldVersion, - Update - .Set(x => x.State, value) - .Set(x => x.Version, newVersion), - Upsert); - } - catch (MongoWriteException ex) - { - if (ex.WriteError.Category == ServerErrorCategory.DuplicateKey) - { - var existingVersion = - await Collection.Find(x => x.Id == key).Only(x => x.Id, x => x.Version) - .FirstOrDefaultAsync(); - - if (existingVersion != null) - { - throw new InconsistentStateException(existingVersion["Version"].AsInt64, oldVersion, ex); - } - } - else - { - throw; - } - } + return assetEntity?.State; } } } diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository_SnapshotStore.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository_SnapshotStore.cs new file mode 100644 index 000000000..70355a5bf --- /dev/null +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository_SnapshotStore.cs @@ -0,0 +1,65 @@ +// ========================================================================== +// MongoAssetRepository_SnapshotStore.cs +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex Group +// All rights reserved. +// ========================================================================== + +using System; +using System.Threading.Tasks; +using MongoDB.Driver; +using Squidex.Domain.Apps.Entities.Assets.State; +using Squidex.Infrastructure; +using Squidex.Infrastructure.MongoDb; +using Squidex.Infrastructure.States; + +namespace Squidex.Domain.Apps.Entities.MongoDb.Assets +{ + public sealed partial class MongoAssetRepository : ISnapshotStore + { + public async Task<(AssetState 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 async Task WriteAsync(Guid key, AssetState value, long oldVersion, long newVersion) + { + try + { + await Collection.UpdateOneAsync(x => x.Id == key && x.Version == oldVersion, + Update + .Set(x => x.State, value) + .Set(x => x.Version, newVersion), + Upsert); + } + catch (MongoWriteException ex) + { + if (ex.WriteError.Category == ServerErrorCategory.DuplicateKey) + { + var existingVersion = + await Collection.Find(x => x.Id == key).Only(x => x.Id, x => x.Version) + .FirstOrDefaultAsync(); + + if (existingVersion != null) + { + throw new InconsistentStateException(existingVersion["Version"].AsInt64, oldVersion, ex); + } + } + else + { + throw; + } + } + } + } +} diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository.cs index fdbb52b7c..dbdad15dc 100644 --- a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository.cs +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository.cs @@ -13,25 +13,17 @@ using System.Threading.Tasks; using Microsoft.OData.UriParser; using MongoDB.Driver; using Squidex.Domain.Apps.Core.Contents; -using Squidex.Domain.Apps.Core.ConvertContent; using Squidex.Domain.Apps.Entities.Apps; using Squidex.Domain.Apps.Entities.Contents; using Squidex.Domain.Apps.Entities.Contents.Repositories; -using Squidex.Domain.Apps.Entities.Contents.State; using Squidex.Domain.Apps.Entities.MongoDb.Contents.Visitors; using Squidex.Domain.Apps.Entities.Schemas; using Squidex.Infrastructure; -using Squidex.Infrastructure.EventSourcing; using Squidex.Infrastructure.MongoDb; -using Squidex.Infrastructure.Reflection; -using Squidex.Infrastructure.States; namespace Squidex.Domain.Apps.Entities.MongoDb.Contents { - public partial class MongoContentRepository : MongoRepositoryBase, - IEventConsumer, - IContentRepository, - ISnapshotStore + public partial class MongoContentRepository : MongoRepositoryBase, IContentRepository { private readonly IAppProvider appProvider; @@ -71,92 +63,12 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents await collection.Indexes.CreateOneAsync(Index.Text(x => x.DataText)); } - public async Task WriteAsync(Guid key, ContentState value, long oldVersion, long newVersion) + public async Task> QueryAsync(IAppEntity app, ISchemaEntity schema, Status[] status, ODataUriParser odataQuery) { - var documentId = $"{key}_{newVersion}"; - - if (value.SchemaId == Guid.Empty) - { - return; - } - - var schema = await appProvider.GetSchemaAsync(value.AppId, value.SchemaId, true); - - if (schema == null) - { - throw new InvalidOperationException($"Cannot find schema {value.SchemaId}"); - } - - var idData = value.Data?.ToIdModel(schema.SchemaDef, true); - - var document = SimpleMapper.Map(value, new MongoContentEntity - { - DocumentId = documentId, - DataText = idData?.ToFullText(), - DataByIds = idData, - IsLatest = !value.IsDeleted, - ReferencedIds = idData?.ToReferencedIds(schema.SchemaDef), - }); - + IFindFluent find; try { - await Collection.InsertOneAsync(document); - await Collection.UpdateManyAsync(x => x.Id == value.Id && x.Version < value.Version, Update.Set(x => x.IsLatest, false)); - } - catch (MongoWriteException ex) - { - if (ex.WriteError.Category == ServerErrorCategory.DuplicateKey) - { - var existingVersion = - await Collection.Find(x => x.Id == value.Id && x.IsLatest).Only(x => x.Id, x => x.Version) - .FirstOrDefaultAsync(); - - if (existingVersion != null) - { - throw new InconsistentStateException(existingVersion["vs"].AsInt64, oldVersion, ex); - } - } - else - { - throw; - } - } - } - - public async Task<(ContentState Value, long Version)> ReadAsync(Guid key) - { - var contentEntity = - await Collection.Find(x => x.Id == key).SortByDescending(x => x.Version) - .FirstOrDefaultAsync(); - - if (contentEntity != null) - { - var schema = await appProvider.GetSchemaAsync(contentEntity.AppId, contentEntity.SchemaId, true); - - if (schema == null) - { - throw new InvalidOperationException($"Cannot find schema {contentEntity.SchemaId}"); - } - - contentEntity?.ParseData(schema.SchemaDef); - - return (SimpleMapper.Map(contentEntity, new ContentState()), contentEntity.Version); - } - - return (null, EtagVersion.NotFound); - } - - public async Task> QueryAsync(IAppEntity app, ISchemaEntity schema, Status[] status, ODataUriParser odataQuery) - { - IFindFluent cursor; - try - { - cursor = - Collection - .Find(odataQuery, schema.Id, schema.SchemaDef, status) - .Take(odataQuery) - .Skip(odataQuery) - .Sort(odataQuery, schema.SchemaDef); + find = Collection.Find(odataQuery, schema.Id, schema.SchemaDef, status); } catch (NotSupportedException) { @@ -167,56 +79,34 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents throw new ValidationException("This odata operation is not supported."); } - var contentEntities = await cursor.ToListAsync(); + var contentItems = find.Take(odataQuery).Skip(odataQuery).Sort(odataQuery, schema.SchemaDef).ToListAsync(); + var contentCount = find.CountAsync(); - foreach (var entity in contentEntities) - { - entity.ParseData(schema.SchemaDef); - } - - return contentEntities; - } + await Task.WhenAll(contentItems, contentCount); - public async Task CountAsync(IAppEntity app, ISchemaEntity schema, Status[] status, ODataUriParser odataQuery) - { - IFindFluent cursor; - try + foreach (var entity in contentItems.Result) { - cursor = Collection.Find(odataQuery, schema.Id, schema.SchemaDef, status); - } - catch (NotSupportedException) - { - throw new ValidationException("This odata operation is not supported."); - } - catch (NotImplementedException) - { - throw new ValidationException("This odata operation is not supported."); + entity.ParseData(schema.SchemaDef); } - return await cursor.CountAsync(); + return ResultList.Create(contentItems.Result, contentCount.Result); } - public async Task CountAsync(IAppEntity app, ISchemaEntity schema, Status[] status, HashSet ids) + public async Task> QueryAsync(IAppEntity app, ISchemaEntity schema, Status[] status, HashSet ids) { - var contentsCount = - await Collection.Find(x => ids.Contains(x.Id) && x.IsLatest) - .CountAsync(); + var find = Collection.Find(x => ids.Contains(x.Id) && x.IsLatest); - return contentsCount; - } + var contentItems = find.ToListAsync(); + var contentCount = find.CountAsync(); - public async Task> QueryAsync(IAppEntity app, ISchemaEntity schema, Status[] status, HashSet ids) - { - var contentEntities = - await Collection.Find(x => ids.Contains(x.Id) && x.IsLatest) - .ToListAsync(); + await Task.WhenAll(contentItems, contentCount); - foreach (var entity in contentEntities) + foreach (var entity in contentItems.Result) { entity.ParseData(schema.SchemaDef); } - return contentEntities.OfType().ToList(); + return ResultList.Create(contentItems.Result, contentCount.Result); } public async Task> QueryNotFoundAsync(Guid appId, Guid schemaId, IList contentIds) diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository_EventHandling.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository_EventHandling.cs index f3c489a91..81c52dff6 100644 --- a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository_EventHandling.cs +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository_EventHandling.cs @@ -15,7 +15,7 @@ using Squidex.Infrastructure.Tasks; namespace Squidex.Domain.Apps.Entities.MongoDb.Contents { - public partial class MongoContentRepository + public partial class MongoContentRepository : IEventConsumer { public string Name { diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository_SnapshotStore.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository_SnapshotStore.cs new file mode 100644 index 000000000..8eadcba64 --- /dev/null +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository_SnapshotStore.cs @@ -0,0 +1,98 @@ +// ========================================================================== +// MongoContentRepository_SnapshotStore.cs +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex Group +// All rights reserved. +// ========================================================================== + +using System; +using System.Threading.Tasks; +using MongoDB.Driver; +using Squidex.Domain.Apps.Core.ConvertContent; +using Squidex.Domain.Apps.Entities.Contents.State; +using Squidex.Infrastructure; +using Squidex.Infrastructure.MongoDb; +using Squidex.Infrastructure.Reflection; +using Squidex.Infrastructure.States; + +namespace Squidex.Domain.Apps.Entities.MongoDb.Contents +{ + public partial class MongoContentRepository : ISnapshotStore + { + public async Task<(ContentState Value, long Version)> ReadAsync(Guid key) + { + var contentEntity = + await Collection.Find(x => x.Id == key).SortByDescending(x => x.Version) + .FirstOrDefaultAsync(); + + if (contentEntity != null) + { + var schema = await appProvider.GetSchemaAsync(contentEntity.AppId, contentEntity.SchemaId, true); + + if (schema == null) + { + throw new InvalidOperationException($"Cannot find schema {contentEntity.SchemaId}"); + } + + contentEntity?.ParseData(schema.SchemaDef); + + return (SimpleMapper.Map(contentEntity, new ContentState()), contentEntity.Version); + } + + return (null, EtagVersion.NotFound); + } + + public async Task WriteAsync(Guid key, ContentState value, long oldVersion, long newVersion) + { + var documentId = $"{key}_{newVersion}"; + + if (value.SchemaId == Guid.Empty) + { + return; + } + + var schema = await appProvider.GetSchemaAsync(value.AppId, value.SchemaId, true); + + if (schema == null) + { + throw new InvalidOperationException($"Cannot find schema {value.SchemaId}"); + } + + var idData = value.Data?.ToIdModel(schema.SchemaDef, true); + + var document = SimpleMapper.Map(value, new MongoContentEntity + { + DocumentId = documentId, + DataText = idData?.ToFullText(), + DataByIds = idData, + IsLatest = !value.IsDeleted, + ReferencedIds = idData?.ToReferencedIds(schema.SchemaDef), + }); + + try + { + await Collection.InsertOneAsync(document); + await Collection.UpdateManyAsync(x => x.Id == value.Id && x.Version < value.Version, Update.Set(x => x.IsLatest, false)); + } + catch (MongoWriteException ex) + { + if (ex.WriteError.Category == ServerErrorCategory.DuplicateKey) + { + var existingVersion = + await Collection.Find(x => x.Id == value.Id && x.IsLatest).Only(x => x.Id, x => x.Version) + .FirstOrDefaultAsync(); + + if (existingVersion != null) + { + throw new InconsistentStateException(existingVersion["vs"].AsInt64, oldVersion, ex); + } + } + else + { + throw; + } + } + } + } +} diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Rules/MongoRuleRepository.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Rules/MongoRuleRepository.cs index ff579d0f3..66a259730 100644 --- a/src/Squidex.Domain.Apps.Entities.MongoDb/Rules/MongoRuleRepository.cs +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Rules/MongoRuleRepository.cs @@ -12,14 +12,11 @@ using System.Linq; using System.Threading.Tasks; using MongoDB.Driver; using Squidex.Domain.Apps.Entities.Rules.Repositories; -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 class MongoRuleRepository : MongoRepositoryBase, IRuleRepository, ISnapshotStore + public sealed partial class MongoRuleRepository : MongoRepositoryBase, IRuleRepository { public MongoRuleRepository(IMongoDatabase database) : base(database) @@ -37,20 +34,6 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Rules await collection.Indexes.CreateOneAsync(Index.Ascending(x => x.IsDeleted)); } - 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 async Task> QueryRuleIdsAsync(Guid appId) { var ruleEntities = @@ -59,37 +42,5 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Rules return ruleEntities.Select(x => Guid.Parse(x["_id"].AsString)).ToList(); } - - public async Task WriteAsync(Guid key, RuleState value, long oldVersion, long newVersion) - { - try - { - await Collection.UpdateOneAsync(x => x.Id == key && x.Version == oldVersion, - Update - .Set(x => x.State, value) - .Set(x => x.AppId, value.AppId) - .Set(x => x.IsDeleted, value.IsDeleted) - .Set(x => x.Version, newVersion), - Upsert); - } - catch (MongoWriteException ex) - { - if (ex.WriteError.Category == ServerErrorCategory.DuplicateKey) - { - var existingVersion = - await Collection.Find(x => x.Id == key).Only(x => x.Id, x => x.Version) - .FirstOrDefaultAsync(); - - if (existingVersion != null) - { - throw new InconsistentStateException(existingVersion["Version"].AsInt64, oldVersion, ex); - } - } - else - { - throw; - } - } - } } } diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Rules/MongoRuleRepository_SnapshotStore.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Rules/MongoRuleRepository_SnapshotStore.cs new file mode 100644 index 000000000..faa7d0783 --- /dev/null +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Rules/MongoRuleRepository_SnapshotStore.cs @@ -0,0 +1,67 @@ +// ========================================================================== +// MongoRuleRepository_SnapshotStore.cs +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex Group +// All rights reserved. +// ========================================================================== + +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 + { + 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 async Task WriteAsync(Guid key, RuleState value, long oldVersion, long newVersion) + { + try + { + await Collection.UpdateOneAsync(x => x.Id == key && x.Version == oldVersion, + Update + .Set(x => x.State, value) + .Set(x => x.AppId, value.AppId) + .Set(x => x.IsDeleted, value.IsDeleted) + .Set(x => x.Version, newVersion), + Upsert); + } + catch (MongoWriteException ex) + { + if (ex.WriteError.Category == ServerErrorCategory.DuplicateKey) + { + var existingVersion = + await Collection.Find(x => x.Id == key).Only(x => x.Id, x => x.Version) + .FirstOrDefaultAsync(); + + if (existingVersion != null) + { + throw new InconsistentStateException(existingVersion["Version"].AsInt64, oldVersion, ex); + } + } + else + { + throw; + } + } + } + } +} diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Schemas/MongoSchemaRepository.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Schemas/MongoSchemaRepository.cs index f010e987c..e04a1564c 100644 --- a/src/Squidex.Domain.Apps.Entities.MongoDb/Schemas/MongoSchemaRepository.cs +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Schemas/MongoSchemaRepository.cs @@ -12,14 +12,11 @@ using System.Linq; using System.Threading.Tasks; using MongoDB.Driver; using Squidex.Domain.Apps.Entities.Schemas.Repositories; -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 class MongoSchemaRepository : MongoRepositoryBase, ISchemaRepository, ISnapshotStore + public sealed partial class MongoSchemaRepository : MongoRepositoryBase, ISchemaRepository { public MongoSchemaRepository(IMongoDatabase database) : base(database) @@ -37,20 +34,6 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Schemas await collection.Indexes.CreateOneAsync(Index.Ascending(x => x.Name)); } - 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 async Task> QuerySchemaIdsAsync(Guid appId, string name) { var schemaEntities = @@ -68,37 +51,5 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Schemas return schemaEntities.Select(x => Guid.Parse(x["_id"].AsString)).ToList(); } - - public async Task WriteAsync(Guid key, SchemaState value, long oldVersion, long newVersion) - { - try - { - await Collection.UpdateOneAsync(x => x.Id == key && x.Version == oldVersion, - Update - .Set(x => x.State, value) - .Set(x => x.AppId, value.AppId) - .Set(x => x.Name, value.Name) - .Set(x => x.Version, newVersion), - Upsert); - } - catch (MongoWriteException ex) - { - if (ex.WriteError.Category == ServerErrorCategory.DuplicateKey) - { - var existingVersion = - await Collection.Find(x => x.Id == key).Only(x => x.Version) - .FirstOrDefaultAsync(); - - if (existingVersion != null) - { - throw new InconsistentStateException(existingVersion["Version"].AsInt64, oldVersion, ex); - } - } - else - { - throw; - } - } - } } } diff --git a/src/Squidex.Domain.Apps.Entities.MongoDb/Schemas/MongoSchemaRepository_SnapshotStore.cs b/src/Squidex.Domain.Apps.Entities.MongoDb/Schemas/MongoSchemaRepository_SnapshotStore.cs new file mode 100644 index 000000000..a2ad87135 --- /dev/null +++ b/src/Squidex.Domain.Apps.Entities.MongoDb/Schemas/MongoSchemaRepository_SnapshotStore.cs @@ -0,0 +1,67 @@ +// ========================================================================== +// MongoSchemaRepository_SnapshotStore.cs +// Squidex Headless CMS +// ========================================================================== +// Copyright (c) Squidex Group +// All rights reserved. +// ========================================================================== + +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 + { + 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 async Task WriteAsync(Guid key, SchemaState value, long oldVersion, long newVersion) + { + try + { + await Collection.UpdateOneAsync(x => x.Id == key && x.Version == oldVersion, + Update + .Set(x => x.State, value) + .Set(x => x.AppId, value.AppId) + .Set(x => x.Name, value.Name) + .Set(x => x.Version, newVersion), + Upsert); + } + catch (MongoWriteException ex) + { + if (ex.WriteError.Category == ServerErrorCategory.DuplicateKey) + { + var existingVersion = + await Collection.Find(x => x.Id == key).Only(x => x.Version) + .FirstOrDefaultAsync(); + + if (existingVersion != null) + { + throw new InconsistentStateException(existingVersion["Version"].AsInt64, oldVersion, ex); + } + } + else + { + throw; + } + } + } + } +} diff --git a/src/Squidex.Domain.Apps.Entities/Contents/ContentQueryService.cs b/src/Squidex.Domain.Apps.Entities/Contents/ContentQueryService.cs index 95f95ee31..738269233 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/ContentQueryService.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/ContentQueryService.cs @@ -70,12 +70,12 @@ namespace Squidex.Domain.Apps.Entities.Contents throw new DomainObjectNotFoundException(id.ToString(), typeof(ISchemaEntity)); } - content = TransformContent(user, schema, new List { content })[0]; + content = TransformContent(user, schema, Enumerable.Repeat(content, 1)).FirstOrDefault(); return (schema, content); } - public async Task<(ISchemaEntity Schema, long Total, IReadOnlyList Items)> QueryWithCountAsync(IAppEntity app, string schemaIdOrName, ClaimsPrincipal user, bool archived, string query) + public async Task<(ISchemaEntity Schema, IResultList Contents)> QueryAsync(IAppEntity app, string schemaIdOrName, ClaimsPrincipal user, bool archived, string query) { Guard.NotNull(app, nameof(app)); Guard.NotNull(user, nameof(user)); @@ -84,20 +84,14 @@ namespace Squidex.Domain.Apps.Entities.Contents var schema = await FindSchemaAsync(app, schemaIdOrName); var parsedQuery = ParseQuery(app, query, schema); + var parsedStatus = ParseStatus(user, archived); - var status = ParseStatus(user, archived); + var contents = await contentRepository.QueryAsync(app, schema, parsedStatus.ToArray(), parsedQuery); - var taskForItems = contentRepository.QueryAsync(app, schema, status.ToArray(), parsedQuery); - var taskForCount = contentRepository.CountAsync(app, schema, status.ToArray(), parsedQuery); - - await Task.WhenAll(taskForItems, taskForCount); - - var list = TransformContent(user, schema, taskForItems.Result.ToList()); - - return (schema, taskForCount.Result, list); + return TransformContents(user, schema, contents); } - public async Task<(ISchemaEntity Schema, long Total, IReadOnlyList Items)> QueryWithCountAsync(IAppEntity app, string schemaIdOrName, ClaimsPrincipal user, bool archived, HashSet ids) + public async Task<(ISchemaEntity Schema, IResultList Contents)> QueryAsync(IAppEntity app, string schemaIdOrName, ClaimsPrincipal user, bool archived, HashSet ids) { Guard.NotNull(ids, nameof(ids)); Guard.NotNull(app, nameof(app)); @@ -106,34 +100,41 @@ namespace Squidex.Domain.Apps.Entities.Contents var schema = await FindSchemaAsync(app, schemaIdOrName); - var status = ParseStatus(user, archived); + var parsedStatus = ParseStatus(user, archived); - var taskForItems = contentRepository.QueryAsync(app, schema, status.ToArray(), ids); - var taskForCount = contentRepository.CountAsync(app, schema, status.ToArray(), ids); + var contents = await contentRepository.QueryAsync(app, schema, parsedStatus.ToArray(), ids); - await Task.WhenAll(taskForItems, taskForCount); + return TransformContents(user, schema, contents); + } - var list = TransformContent(user, schema, taskForItems.Result.ToList()); + private (ISchemaEntity Schema, IResultList Contents) TransformContents(ClaimsPrincipal user, ISchemaEntity schema, IResultList contents) + { + var transformed = TransformContent(user, schema, contents); - return (schema, taskForCount.Result, list); + return (schema, ResultList.Create(transformed, contents.Total)); } - private List TransformContent(ClaimsPrincipal user, ISchemaEntity schema, List contents) + private IEnumerable TransformContent(ClaimsPrincipal user, ISchemaEntity schema, IEnumerable contents) { var scriptText = schema.ScriptQuery; if (!string.IsNullOrWhiteSpace(scriptText)) { - for (var i = 0; i < contents.Count; i++) + foreach (var content in contents) { - var content = contents[i]; var contentData = scriptEngine.Transform(new ScriptContext { User = user, Data = content.Data, ContentId = content.Id }, scriptText); + var contentResult = SimpleMapper.Map(content, new Content()); + + contentResult.Data = contentData; - contents[i] = SimpleMapper.Map(content, new Content { Data = contentData }); + yield return contentResult; } } - return contents; + foreach (var content in contents) + { + yield return content; + } } private ODataUriParser ParseQuery(IAppEntity app, string query, ISchemaEntity schema) diff --git a/src/Squidex.Domain.Apps.Entities/Contents/IContentQueryService.cs b/src/Squidex.Domain.Apps.Entities/Contents/IContentQueryService.cs index 8baaccd33..a670a15fe 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/IContentQueryService.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/IContentQueryService.cs @@ -18,9 +18,9 @@ namespace Squidex.Domain.Apps.Entities.Contents { public interface IContentQueryService { - Task<(ISchemaEntity Schema, long Total, IReadOnlyList Items)> QueryWithCountAsync(IAppEntity app, string schemaIdOrName, ClaimsPrincipal user, bool archived, HashSet ids); + Task<(ISchemaEntity Schema, IResultList Contents)> QueryAsync(IAppEntity app, string schemaIdOrName, ClaimsPrincipal user, bool archived, HashSet ids); - Task<(ISchemaEntity Schema, long Total, IReadOnlyList Items)> QueryWithCountAsync(IAppEntity app, string schemaIdOrName, ClaimsPrincipal user, bool archived, string query); + Task<(ISchemaEntity Schema, IResultList Contents)> QueryAsync(IAppEntity app, string schemaIdOrName, ClaimsPrincipal user, bool archived, string query); Task<(ISchemaEntity Schema, IContentEntity Content)> FindContentAsync(IAppEntity app, string schemaIdOrName, ClaimsPrincipal user, Guid id, long version = EtagVersion.Any); diff --git a/src/Squidex.Domain.Apps.Entities/Contents/QueryContext.cs b/src/Squidex.Domain.Apps.Entities/Contents/QueryContext.cs index 01288799e..92fa75702 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/QueryContext.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/QueryContext.cs @@ -95,14 +95,14 @@ namespace Squidex.Domain.Apps.Entities.Contents public async Task> QueryContentsAsync(string schemaIdOrName, string query) { - var contents = await contentQuery.QueryWithCountAsync(app, schemaIdOrName, user, false, query); + var result = await contentQuery.QueryAsync(app, schemaIdOrName, user, false, query); - foreach (var content in contents.Items) + foreach (var content in result.Contents) { cachedContents[content.Id] = content; } - return contents.Items; + return result.Contents; } public async Task> GetReferencedAssetsAsync(ICollection ids) @@ -132,9 +132,9 @@ namespace Squidex.Domain.Apps.Entities.Contents if (notLoadedContents.Count > 0) { - var contents = await contentQuery.QueryWithCountAsync(app, schemaId.ToString(), user, false, notLoadedContents); + var result = await contentQuery.QueryAsync(app, schemaId.ToString(), user, false, notLoadedContents); - foreach (var content in contents.Items) + foreach (var content in result.Contents) { cachedContents[content.Id] = content; } diff --git a/src/Squidex.Domain.Apps.Entities/Contents/Repositories/IContentRepository.cs b/src/Squidex.Domain.Apps.Entities/Contents/Repositories/IContentRepository.cs index 857cc189a..2d5ed609c 100644 --- a/src/Squidex.Domain.Apps.Entities/Contents/Repositories/IContentRepository.cs +++ b/src/Squidex.Domain.Apps.Entities/Contents/Repositories/IContentRepository.cs @@ -13,21 +13,18 @@ using Microsoft.OData.UriParser; using Squidex.Domain.Apps.Core.Contents; using Squidex.Domain.Apps.Entities.Apps; using Squidex.Domain.Apps.Entities.Schemas; +using Squidex.Infrastructure; namespace Squidex.Domain.Apps.Entities.Contents.Repositories { public interface IContentRepository { - Task> QueryAsync(IAppEntity app, ISchemaEntity schema, Status[] status, HashSet ids); + Task> QueryAsync(IAppEntity app, ISchemaEntity schema, Status[] status, HashSet ids); - Task> QueryAsync(IAppEntity app, ISchemaEntity schema, Status[] status, ODataUriParser odataQuery); + Task> QueryAsync(IAppEntity app, ISchemaEntity schema, Status[] status, ODataUriParser odataQuery); Task> QueryNotFoundAsync(Guid appId, Guid schemaId, IList contentIds); - Task CountAsync(IAppEntity app, ISchemaEntity schema, Status[] status, HashSet ids); - - Task CountAsync(IAppEntity app, ISchemaEntity schema, Status[] status, ODataUriParser odataQuery); - Task FindContentAsync(IAppEntity app, ISchemaEntity schema, Guid id); Task FindContentAsync(IAppEntity app, ISchemaEntity schema, Guid id, long version); diff --git a/src/Squidex.Domain.Apps.Entities/Rules/RuleEnqueuer.cs b/src/Squidex.Domain.Apps.Entities/Rules/RuleEnqueuer.cs index 90fe5c1d5..a57c4e162 100644 --- a/src/Squidex.Domain.Apps.Entities/Rules/RuleEnqueuer.cs +++ b/src/Squidex.Domain.Apps.Entities/Rules/RuleEnqueuer.cs @@ -7,7 +7,6 @@ // ========================================================================== using System.Threading.Tasks; -using NodaTime; using Squidex.Domain.Apps.Core.HandleRules; using Squidex.Domain.Apps.Entities.Rules.Repositories; using Squidex.Domain.Apps.Events; diff --git a/src/Squidex/Areas/Api/Controllers/Content/ContentsController.cs b/src/Squidex/Areas/Api/Controllers/Content/ContentsController.cs index 875b451cc..68d8a08a3 100644 --- a/src/Squidex/Areas/Api/Controllers/Content/ContentsController.cs +++ b/src/Squidex/Areas/Api/Controllers/Content/ContentsController.cs @@ -86,21 +86,21 @@ namespace Squidex.Areas.Api.Controllers.Contents var isFrontendClient = User.IsFrontendClient(); - var contents = + var result = idsList != null ? - await contentQuery.QueryWithCountAsync(App, name, User, archived, idsList) : - await contentQuery.QueryWithCountAsync(App, name, User, archived, Request.QueryString.ToString()); + await contentQuery.QueryAsync(App, name, User, archived, idsList) : + await contentQuery.QueryAsync(App, name, User, archived, Request.QueryString.ToString()); var response = new AssetsDto { - Total = contents.Total, - Items = contents.Items.Take(200).Select(item => + Total = result.Contents.Total, + Items = result.Contents.Take(200).Select(item => { var itemModel = SimpleMapper.Map(item, new ContentDto()); if (item.Data != null) { - itemModel.Data = item.Data.ToApiModel(contents.Schema.SchemaDef, App.LanguagesConfig, !isFrontendClient); + itemModel.Data = item.Data.ToApiModel(result.Schema.SchemaDef, App.LanguagesConfig, !isFrontendClient); } return itemModel; diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentQueryServiceTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentQueryServiceTests.cs index ecb503b83..adb46576b 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentQueryServiceTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentQueryServiceTests.cs @@ -8,6 +8,7 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Security.Claims; using System.Threading.Tasks; using FakeItEasy; @@ -36,8 +37,8 @@ namespace Squidex.Domain.Apps.Entities.Contents private readonly Guid schemaId = Guid.NewGuid(); private readonly Guid contentId = Guid.NewGuid(); private readonly string appName = "my-app"; - private readonly NamedContentData data = new NamedContentData(); - private readonly NamedContentData transformedData = new NamedContentData(); + private readonly NamedContentData contentData = new NamedContentData(); + private readonly NamedContentData contentTransformed = new NamedContentData(); private readonly ClaimsPrincipal user; private readonly ClaimsIdentity identity = new ClaimsIdentity(); private readonly EdmModelBuilder modelBuilder = A.Fake(); @@ -51,7 +52,7 @@ namespace Squidex.Domain.Apps.Entities.Contents A.CallTo(() => app.Name).Returns(appName); A.CallTo(() => content.Id).Returns(contentId); - A.CallTo(() => content.Data).Returns(data); + A.CallTo(() => content.Data).Returns(contentData); A.CallTo(() => content.Status).Returns(Status.Published); sut = new ContentQueryService(contentRepository, appProvider, scriptEngine, modelBuilder); @@ -99,13 +100,14 @@ namespace Squidex.Domain.Apps.Entities.Contents A.CallTo(() => schema.ScriptQuery) .Returns(""); - A.CallTo(() => scriptEngine.Transform(A.That.Matches(x => x.User == user && x.ContentId == contentId && ReferenceEquals(x.Data, data)), "")) - .Returns(transformedData); + A.CallTo(() => scriptEngine.Transform(A.That.Matches(x => x.User == user && x.ContentId == contentId && ReferenceEquals(x.Data, contentData)), "")) + .Returns(contentTransformed); var result = await sut.FindContentAsync(app, schemaId.ToString(), user, contentId); Assert.Equal(schema, result.Schema); - Assert.Equal(data, result.Content.Data); + + Assert.Equal(contentTransformed, result.Content.Data); Assert.Equal(content.Id, result.Content.Id); } @@ -157,12 +159,14 @@ namespace Squidex.Domain.Apps.Entities.Contents SetupFakeWithOdataQuery(status); SetupFakeWithScripting(); - var result = await sut.QueryWithCountAsync(app, schemaId.ToString(), user, archive, string.Empty); + var result = await sut.QueryAsync(app, schemaId.ToString(), user, archive, string.Empty); - Assert.Equal(123, result.Total); Assert.Equal(schema, result.Schema); - Assert.Equal(data, result.Items[0].Data); - Assert.Equal(content.Id, result.Items[0].Id); + + Assert.Equal(contentData, result.Contents[0].Data); + Assert.Equal(content.Id, result.Contents[0].Id); + + Assert.Equal(123, result.Contents.Total); } private async Task TestManyIdRequest(bool isFrontend, bool archive, HashSet ids, params Status[] status) @@ -172,12 +176,14 @@ namespace Squidex.Domain.Apps.Entities.Contents SetupFakeWithIdQuery(status, ids); SetupFakeWithScripting(); - var result = await sut.QueryWithCountAsync(app, schemaId.ToString(), user, archive, ids); + var result = await sut.QueryAsync(app, schemaId.ToString(), user, archive, ids); - Assert.Equal(123, result.Total); Assert.Equal(schema, result.Schema); - Assert.Equal(data, result.Items[0].Data); - Assert.Equal(content.Id, result.Items[0].Id); + + Assert.Equal(contentData, result.Contents[0].Data); + Assert.Equal(content.Id, result.Contents[0].Id); + + Assert.Equal(123, result.Contents.Total); } private void SetupClaims(bool isFrontend) @@ -192,20 +198,18 @@ namespace Squidex.Domain.Apps.Entities.Contents { A.CallTo(() => appProvider.GetSchemaAsync(appId, schemaId, false)) .Returns(schema); + A.CallTo(() => contentRepository.QueryAsync(app, schema, A.That.IsSameSequenceAs(status), ids)) - .Returns(new List { content }); - A.CallTo(() => contentRepository.CountAsync(app, schema, A.That.IsSameSequenceAs(status), ids)) - .Returns(123); + .Returns(ResultList.Create(Enumerable.Repeat(content, 1), 123)); } private void SetupFakeWithOdataQuery(Status[] status) { A.CallTo(() => appProvider.GetSchemaAsync(appId, schemaId, false)) .Returns(schema); + A.CallTo(() => contentRepository.QueryAsync(app, schema, A.That.IsSameSequenceAs(status), A.Ignored)) - .Returns(new List { content }); - A.CallTo(() => contentRepository.CountAsync(app, schema, A.That.IsSameSequenceAs(status), A.Ignored)) - .Returns(123); + .Returns(ResultList.Create(Enumerable.Repeat(content, 1), 123)); } private void SetupFakeWithScripting() @@ -213,8 +217,8 @@ namespace Squidex.Domain.Apps.Entities.Contents A.CallTo(() => schema.ScriptQuery) .Returns(""); - A.CallTo(() => scriptEngine.Transform(A.That.Matches(x => x.User == user && x.ContentId == contentId && ReferenceEquals(x.Data, data)), "")) - .Returns(transformedData); + A.CallTo(() => scriptEngine.Transform(A.That.Matches(x => x.User == user && x.ContentId == contentId && ReferenceEquals(x.Data, contentData)), "")) + .Returns(contentTransformed); } } } diff --git a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLTests.cs b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLTests.cs index f75622415..3a9542230 100644 --- a/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLTests.cs +++ b/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLTests.cs @@ -278,8 +278,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL var contents = new List { content }; - A.CallTo(() => contentQuery.QueryWithCountAsync(app, schema.Id.ToString(), user, false, "?$top=30&$skip=5")) - .Returns((schema, 0L, (IReadOnlyList)contents)); + A.CallTo(() => contentQuery.QueryAsync(app, schema.Id.ToString(), user, false, "?$top=30&$skip=5")) + .Returns((schema, ResultList.Create(contents, 0))); var result = await sut.QueryAsync(app, user, new GraphQLQuery { Query = query }); @@ -485,8 +485,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL A.CallTo(() => contentQuery.FindContentAsync(app, schema.Id.ToString(), user, contentId, EtagVersion.Any)) .Returns((schema, content)); - A.CallTo(() => contentQuery.QueryWithCountAsync(app, schema.Id.ToString(), user, false, A>.That.Matches(x => x.Contains(contentRefId)))) - .Returns((schema, 0L, (IReadOnlyList)refContents)); + A.CallTo(() => contentQuery.QueryAsync(app, schema.Id.ToString(), user, false, A>.That.Matches(x => x.Contains(contentRefId)))) + .Returns((schema, ResultList.Create(refContents, 0))); var result = await sut.QueryAsync(app, user, new GraphQLQuery { Query = query });