Browse Source

CancellationToken

pull/711/head
Sebastian Stehle 5 years ago
parent
commit
21bcad84b2
  1. 3
      backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/ExecutionContext.cs
  2. 5
      backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/IScriptEngine.cs
  3. 108
      backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/JintScriptEngine.cs
  4. 18
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetFolderRepository.cs
  5. 5
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetFolderRepository_SnapshotStore.cs
  6. 50
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository.cs
  7. 5
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository_SnapshotStore.cs
  8. 58
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentCollection.cs
  9. 53
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository.cs
  10. 3
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository_SnapshotStore.cs
  11. 6
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Operations/Extensions.cs
  12. 2
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Operations/OperationBase.cs
  13. 2
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Operations/QueryAsStream.cs
  14. 6
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Operations/QueryById.cs
  15. 11
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Operations/QueryByIds.cs
  16. 30
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Operations/QueryByQuery.cs
  17. 8
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Operations/QueryReferences.cs
  18. 9
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Operations/QueryReferrers.cs
  19. 7
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Operations/QueryScheduled.cs
  20. 3
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/FullText/MongoTextIndex.cs
  21. 3
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/History/MongoHistoryEventRepository.cs
  22. 19
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Rules/MongoRuleEventRepository.cs
  23. 8
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Rules/MongoRuleStatisticsCollection.cs
  24. 6
      backend/src/Squidex.Domain.Apps.Entities/Apps/AppSettingsSearchSource.cs
  25. 6
      backend/src/Squidex.Domain.Apps.Entities/Apps/DefaultAppImageStore.cs
  26. 3
      backend/src/Squidex.Domain.Apps.Entities/Apps/DefaultAppLogStore.cs
  27. 6
      backend/src/Squidex.Domain.Apps.Entities/Assets/AssetsSearchSource.cs
  28. 15
      backend/src/Squidex.Domain.Apps.Entities/Assets/DefaultAssetFileStore.cs
  29. 2
      backend/src/Squidex.Domain.Apps.Entities/Assets/DomainObject/AssetCommandMiddleware.cs
  30. 4
      backend/src/Squidex.Domain.Apps.Entities/Assets/DomainObject/Guards/GuardAsset.cs
  31. 7
      backend/src/Squidex.Domain.Apps.Entities/Assets/IAssetEnricher.cs
  32. 17
      backend/src/Squidex.Domain.Apps.Entities/Assets/IAssetQueryService.cs
  33. 16
      backend/src/Squidex.Domain.Apps.Entities/Assets/Queries/AssetEnricher.cs
  34. 66
      backend/src/Squidex.Domain.Apps.Entities/Assets/Queries/AssetQueryService.cs
  35. 75
      backend/src/Squidex.Domain.Apps.Entities/Assets/RebuildFiles.cs
  36. 4
      backend/src/Squidex.Domain.Apps.Entities/Assets/RecursiveDeleter.cs
  37. 7
      backend/src/Squidex.Domain.Apps.Entities/Assets/Repositories/IAssetFolderRepository.cs
  38. 16
      backend/src/Squidex.Domain.Apps.Entities/Assets/Repositories/IAssetRepository.cs
  39. 8
      backend/src/Squidex.Domain.Apps.Entities/Backup/BackupGrain.cs
  40. 4
      backend/src/Squidex.Domain.Apps.Entities/Contents/ContentSchedulerGrain.cs
  41. 6
      backend/src/Squidex.Domain.Apps.Entities/Contents/ContentsSearchSource.cs
  42. 2
      backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/Guards/ValidationExtensions.cs
  43. 9
      backend/src/Squidex.Domain.Apps.Entities/Contents/IContentQueryService.cs
  44. 20
      backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentEnricher.cs
  45. 37
      backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentQueryService.cs
  46. 5
      backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/IContentEnricher.cs
  47. 5
      backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/IContentEnricherStep.cs
  48. 25
      backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/Steps/ConvertData.cs
  49. 9
      backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/Steps/EnrichForCaching.cs
  50. 6
      backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/Steps/EnrichWithSchema.cs
  51. 6
      backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/Steps/EnrichWithWorkflows.cs
  52. 11
      backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/Steps/ResolveAssets.cs
  53. 16
      backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/Steps/ResolveReferences.cs
  54. 11
      backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/Steps/ScriptContent.cs
  55. 18
      backend/src/Squidex.Domain.Apps.Entities/Contents/Repositories/IContentRepository.cs
  56. 8
      backend/src/Squidex.Domain.Apps.Entities/Contents/Validation/DependencyValidatorsFactory.cs
  57. 6
      backend/src/Squidex.Domain.Apps.Entities/Rules/Repositories/IRuleEventRepository.cs
  58. 4
      backend/src/Squidex.Domain.Apps.Entities/Schemas/SchemasSearchSource.cs
  59. 3
      backend/src/Squidex.Domain.Apps.Entities/Search/ISearchManager.cs
  60. 3
      backend/src/Squidex.Domain.Apps.Entities/Search/ISearchSource.cs
  61. 11
      backend/src/Squidex.Domain.Apps.Entities/Search/SearchManager.cs
  62. 5
      backend/src/Squidex.Domain.Users.MongoDb/MongoRoleStore.cs
  63. 5
      backend/src/Squidex.Domain.Users.MongoDb/MongoUserStore.cs
  64. 3
      backend/src/Squidex.Infrastructure.MongoDb/EventSourcing/MongoEventStore.cs
  65. 3
      backend/src/Squidex.Infrastructure.MongoDb/Log/MongoRequestLogRepository.cs
  66. 5
      backend/src/Squidex.Infrastructure.MongoDb/MongoDb/MongoRepositoryBase.cs
  67. 5
      backend/src/Squidex.Infrastructure.MongoDb/UsageTracking/MongoUsageRepository.cs
  68. 10
      backend/src/Squidex/Areas/Api/Controllers/Assets/AssetContentController.cs
  69. 4
      backend/src/Squidex/Areas/Api/Controllers/Assets/AssetFoldersController.cs
  70. 6
      backend/src/Squidex/Areas/Api/Controllers/Assets/AssetsController.cs
  71. 16
      backend/src/Squidex/Areas/Api/Controllers/Contents/ContentsController.cs
  72. 2
      backend/src/Squidex/Areas/Api/Controllers/Search/SearchController.cs
  73. 50
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Apps/AppSettingsSearchSourceTests.cs
  74. 5
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetsFluidExtensionTests.cs
  75. 5
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetsJintExtensionTests.cs
  76. 9
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetsSearchSourceTests.cs
  77. 4
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/BackupAssetsTests.cs
  78. 10
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/DomainObject/AssetCommandMiddlewareTests.cs
  79. 9
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/DomainObject/AssetDomainObjectTests.cs
  80. 3
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/DomainObject/AssetFolderDomainObjectTests.cs
  81. 13
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/DomainObject/Guards/GuardAssetFolderTests.cs
  82. 8
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/DomainObject/Guards/GuardAssetTests.cs
  83. 12
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/Queries/AssetEnricherTests.cs
  84. 45
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/Queries/AssetQueryServiceTests.cs
  85. 7
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/RecursiveDeleterTests.cs
  86. 2
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/BackupContentsTests.cs
  87. 11
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentsSearchSourceTests.cs
  88. 7
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DomainObject/ContentCommandMiddlewareTests.cs
  89. 79
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DomainObject/ContentDomainObjectTests.cs
  90. 7
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DomainObject/ContentsBulkUpdateCommandMiddlewareTests.cs
  91. 43
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLQueriesTests.cs
  92. 30
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/ContentEnricherTests.cs
  93. 31
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/ContentQueryServiceTests.cs
  94. 15
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/ConvertDataTests.cs
  95. 4
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/EnrichForCachingTests.cs
  96. 6
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/EnrichWithSchemaTests.cs
  97. 18
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/EnrichWithWorkflowsTests.cs
  98. 25
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/ResolveAssetsTests.cs
  99. 25
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/ResolveReferencesTests.cs
  100. 15
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/ScriptContentTests.cs

3
backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/ExecutionContext.cs

@ -40,7 +40,8 @@ namespace Squidex.Domain.Apps.Core.Scripting
completion?.Invoke(exception);
}
public ExecutionContext ExtendAsync(IEnumerable<IJintExtension> extensions, Func<Exception, bool> completion, CancellationToken ct)
public ExecutionContext ExtendAsync(IEnumerable<IJintExtension> extensions, Func<Exception, bool> completion,
CancellationToken ct)
{
CancellationToken = ct;

5
backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/IScriptEngine.cs

@ -5,6 +5,7 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Threading;
using System.Threading.Tasks;
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Infrastructure.Json.Objects;
@ -13,9 +14,9 @@ namespace Squidex.Domain.Apps.Core.Scripting
{
public interface IScriptEngine
{
Task<IJsonValue> ExecuteAsync(ScriptVars vars, string script, ScriptOptions options = default);
Task<IJsonValue> ExecuteAsync(ScriptVars vars, string script, ScriptOptions options = default, CancellationToken ct = default);
Task<ContentData> TransformAsync(ScriptVars vars, string script, ScriptOptions options = default);
Task<ContentData> TransformAsync(ScriptVars vars, string script, ScriptOptions options = default, CancellationToken ct = default);
IJsonValue Execute(ScriptVars vars, string script, ScriptOptions options = default);

108
backend/src/Squidex.Domain.Apps.Core.Operations/Scripting/JintScriptEngine.cs

@ -1,4 +1,4 @@
// ==========================================================================
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
@ -68,90 +68,98 @@ namespace Squidex.Domain.Apps.Core.Scripting
this.extensions = extensions?.ToArray() ?? Array.Empty<IJintExtension>();
}
public async Task<IJsonValue> ExecuteAsync(ScriptVars vars, string script, ScriptOptions options = default)
public async Task<IJsonValue> ExecuteAsync(ScriptVars vars, string script, ScriptOptions options = default,
CancellationToken ct = default)
{
Guard.NotNull(vars, nameof(vars));
Guard.NotNullOrEmpty(script, nameof(script));
using (var cts = new CancellationTokenSource(ActualTimeoutExecution))
{
var tcs = new TaskCompletionSource<IJsonValue>();
using (cts.Token.Register(() => tcs.TrySetCanceled()))
using (var combined = CancellationTokenSource.CreateLinkedTokenSource(cts.Token, ct))
{
var context =
CreateEngine(options)
.Extend(vars, options)
.Extend(extensions)
.ExtendAsync(extensions, tcs.TrySetException, cts.Token);
var tcs = new TaskCompletionSource<IJsonValue>();
context.Engine.SetValue("complete", new Action<JsValue?>(value =>
using (combined.Token.Register(() => tcs.TrySetCanceled()))
{
tcs.TrySetResult(JsonMapper.Map(value));
}));
var context =
CreateEngine(options)
.Extend(vars, options)
.Extend(extensions)
.ExtendAsync(extensions, tcs.TrySetException, combined.Token);
Execute(context.Engine, script);
context.Engine.SetValue("complete", new Action<JsValue?>(value =>
{
tcs.TrySetResult(JsonMapper.Map(value));
}));
if (!context.IsAsync)
{
tcs.TrySetResult(JsonMapper.Map(context.Engine.GetCompletionValue()));
}
Execute(context.Engine, script);
return await tcs.Task;
if (!context.IsAsync)
{
tcs.TrySetResult(JsonMapper.Map(context.Engine.GetCompletionValue()));
}
return await tcs.Task;
}
}
}
}
public async Task<ContentData> TransformAsync(ScriptVars vars, string script, ScriptOptions options = default)
public async Task<ContentData> TransformAsync(ScriptVars vars, string script, ScriptOptions options = default,
CancellationToken ct = default)
{
Guard.NotNull(vars, nameof(vars));
Guard.NotNullOrEmpty(script, nameof(script));
using (var cts = new CancellationTokenSource(ActualTimeoutExecution))
{
var tcs = new TaskCompletionSource<ContentData>();
using (cts.Token.Register(() => tcs.TrySetCanceled()))
using (var combined = CancellationTokenSource.CreateLinkedTokenSource(cts.Token, ct))
{
var context =
CreateEngine(options)
.Extend(vars, options)
.Extend(extensions)
.ExtendAsync(extensions, tcs.TrySetException, cts.Token);
var tcs = new TaskCompletionSource<ContentData>();
context.Engine.SetValue("complete", new Action<JsValue?>(_ =>
using (combined.Token.Register(() => tcs.TrySetCanceled()))
{
tcs.TrySetResult(vars.Data!);
}));
var context =
CreateEngine(options)
.Extend(vars, options)
.Extend(extensions)
.ExtendAsync(extensions, tcs.TrySetException, combined.Token);
context.Engine.SetValue("replace", new Action(() =>
{
var dataInstance = context.Engine.GetValue("ctx").AsObject().Get("data");
context.Engine.SetValue("complete", new Action<JsValue?>(_ =>
{
tcs.TrySetResult(vars.Data!);
}));
if (dataInstance != null && dataInstance.IsObject() && dataInstance.AsObject() is ContentDataObject data)
context.Engine.SetValue("replace", new Action(() =>
{
if (!tcs.Task.IsCompleted)
var dataInstance = context.Engine.GetValue("ctx").AsObject().Get("data");
if (dataInstance != null && dataInstance.IsObject() && dataInstance.AsObject() is ContentDataObject data)
{
if (data.TryUpdate(out var modified))
if (!tcs.Task.IsCompleted)
{
tcs.TrySetResult(modified);
}
else
{
tcs.TrySetResult(vars.Data!);
if (data.TryUpdate(out var modified))
{
tcs.TrySetResult(modified);
}
else
{
tcs.TrySetResult(vars.Data!);
}
}
}
}
}));
}));
Execute(context.Engine, script);
Execute(context.Engine, script);
if (!context.IsAsync)
{
tcs.TrySetResult(vars.Data!);
}
if (!context.IsAsync)
{
tcs.TrySetResult(vars.Data!);
}
return await tcs.Task;
return await tcs.Task;
}
}
}
}

18
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetFolderRepository.cs

@ -30,7 +30,8 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
return "States_AssetFolders2";
}
protected override Task SetupCollectionAsync(IMongoCollection<MongoAssetFolderEntity> collection, CancellationToken ct = default)
protected override Task SetupCollectionAsync(IMongoCollection<MongoAssetFolderEntity> collection,
CancellationToken ct = default)
{
return collection.Indexes.CreateManyAsync(new[]
{
@ -42,7 +43,8 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
}, ct);
}
public async Task<IResultList<IAssetFolderEntity>> QueryAsync(DomainId appId, DomainId parentId)
public async Task<IResultList<IAssetFolderEntity>> QueryAsync(DomainId appId, DomainId parentId,
CancellationToken ct = default)
{
using (Profiler.TraceMethod<MongoAssetFolderRepository>("QueryAsyncByQuery"))
{
@ -50,13 +52,14 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
var assetFolderEntities =
await Collection.Find(filter).SortBy(x => x.FolderName)
.ToListAsync();
.ToListAsync(ct = default);
return ResultList.Create<IAssetFolderEntity>(assetFolderEntities.Count, assetFolderEntities);
}
}
public async Task<IReadOnlyList<DomainId>> QueryChildIdsAsync(DomainId appId, DomainId parentId)
public async Task<IReadOnlyList<DomainId>> QueryChildIdsAsync(DomainId appId, DomainId parentId,
CancellationToken ct = default)
{
using (Profiler.TraceMethod<MongoAssetRepository>())
{
@ -64,7 +67,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
var assetFolderEntities =
await Collection.Find(filter).Only(x => x.Id)
.ToListAsync();
.ToListAsync(ct = default);
var field = Field.Of<MongoAssetFolderEntity>(x => nameof(x.Id));
@ -72,7 +75,8 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
}
}
public async Task<IAssetFolderEntity?> FindAssetFolderAsync(DomainId appId, DomainId id)
public async Task<IAssetFolderEntity?> FindAssetFolderAsync(DomainId appId, DomainId id,
CancellationToken ct = default)
{
using (Profiler.TraceMethod<MongoAssetFolderRepository>())
{
@ -80,7 +84,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
var assetFolderEntity =
await Collection.Find(x => x.DocumentId == documentId && !x.IsDeleted)
.FirstOrDefaultAsync();
.FirstOrDefaultAsync(ct = default);
return assetFolderEntity;
}

5
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetFolderRepository_SnapshotStore.cs

@ -65,11 +65,12 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
}
}
async Task ISnapshotStore<AssetFolderDomainObject.State>.ReadAllAsync(Func<AssetFolderDomainObject.State, long, Task> callback, CancellationToken ct)
async Task ISnapshotStore<AssetFolderDomainObject.State>.ReadAllAsync(Func<AssetFolderDomainObject.State, long, Task> callback,
CancellationToken ct)
{
using (Profiler.TraceMethod<MongoAssetFolderRepository>())
{
await Collection.Find(new BsonDocument(), options: Batching.Options).ForEachPipedAsync(x => callback(Map(x), x.Version), ct);
await Collection.Find(new BsonDocument(), Batching.Options).ForEachPipedAsync(x => callback(Map(x), x.Version), ct);
}
}

50
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository.cs

@ -1,4 +1,4 @@
// ==========================================================================
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
@ -39,7 +39,8 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
return "States_Assets2";
}
protected override Task SetupCollectionAsync(IMongoCollection<MongoAssetEntity> collection, CancellationToken ct = default)
protected override Task SetupCollectionAsync(IMongoCollection<MongoAssetEntity> collection,
CancellationToken ct = default)
{
return collection.Indexes.CreateManyAsync(new[]
{
@ -74,9 +75,9 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
{
var find = Collection.Find(x => x.IndexedAppId == appId && !x.IsDeleted);
using (var cursor = await find.ToCursorAsync(ct))
using (var cursor = await find.ToCursorAsync(ct = default))
{
while (await cursor.MoveNextAsync(ct))
while (await cursor.MoveNextAsync(ct = default))
{
foreach (var entity in cursor.Current)
{
@ -86,7 +87,8 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
}
}
public async Task<IResultList<IAssetEntity>> QueryAsync(DomainId appId, DomainId? parentId, Q q)
public async Task<IResultList<IAssetEntity>> QueryAsync(DomainId appId, DomainId? parentId, Q q,
CancellationToken ct = default)
{
using (Profiler.TraceMethod<MongoAssetRepository>("QueryAsyncByQuery"))
{
@ -100,7 +102,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
await Collection.Find(filter).SortByDescending(x => x.LastModified)
.QueryLimit(q.Query)
.QuerySkip(q.Query)
.ToListAsync();
.ToListAsync(ct = default);
long assetTotal = assetEntities.Count;
if (q.NoTotal)
@ -109,7 +111,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
}
else if (assetEntities.Count >= q.Query.Take || q.Query.Skip > 0)
{
assetTotal = await Collection.Find(filter).CountDocumentsAsync();
assetTotal = await Collection.Find(filter).CountDocumentsAsync(ct = default);
}
return ResultList.Create(assetTotal, assetEntities.OfType<IAssetEntity>());
@ -125,7 +127,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
.QueryLimit(query)
.QuerySkip(query)
.QuerySort(query)
.ToListAsync();
.ToListAsync(ct = default);
long assetTotal = assetEntities.Count;
if (q.NoTotal)
@ -134,7 +136,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
}
else if (assetEntities.Count >= q.Query.Take || q.Query.Skip > 0)
{
assetTotal = await Collection.Find(filter).CountDocumentsAsync();
assetTotal = await Collection.Find(filter).CountDocumentsAsync(ct = default);
}
return ResultList.Create<IAssetEntity>(assetTotal, assetEntities);
@ -147,13 +149,14 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
}
}
public async Task<IReadOnlyList<DomainId>> QueryIdsAsync(DomainId appId, HashSet<DomainId> ids)
public async Task<IReadOnlyList<DomainId>> QueryIdsAsync(DomainId appId, HashSet<DomainId> ids,
CancellationToken ct = default)
{
using (Profiler.TraceMethod<MongoAssetRepository>("QueryAsyncByIds"))
{
var assetEntities =
await Collection.Find(BuildFilter(appId, ids)).Only(x => x.Id)
.ToListAsync();
.ToListAsync(ct = default);
var field = Field.Of<MongoAssetFolderEntity>(x => nameof(x.Id));
@ -161,13 +164,14 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
}
}
public async Task<IReadOnlyList<DomainId>> QueryChildIdsAsync(DomainId appId, DomainId parentId)
public async Task<IReadOnlyList<DomainId>> QueryChildIdsAsync(DomainId appId, DomainId parentId,
CancellationToken ct = default)
{
using (Profiler.TraceMethod<MongoAssetRepository>())
{
var assetEntities =
await Collection.Find(x => x.IndexedAppId == appId && !x.IsDeleted && x.ParentId == parentId).Only(x => x.Id)
.ToListAsync();
.ToListAsync(ct = default);
var field = Field.Of<MongoAssetFolderEntity>(x => nameof(x.Id));
@ -175,31 +179,34 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
}
}
public async Task<IAssetEntity?> FindAssetByHashAsync(DomainId appId, string hash, string fileName, long fileSize)
public async Task<IAssetEntity?> FindAssetByHashAsync(DomainId appId, string hash, string fileName, long fileSize,
CancellationToken ct = default)
{
using (Profiler.TraceMethod<MongoAssetRepository>())
{
var assetEntity =
await Collection.Find(x => x.IndexedAppId == appId && !x.IsDeleted && x.FileHash == hash && x.FileName == fileName && x.FileSize == fileSize)
.FirstOrDefaultAsync();
.FirstOrDefaultAsync(ct = default);
return assetEntity;
}
}
public async Task<IAssetEntity?> FindAssetBySlugAsync(DomainId appId, string slug)
public async Task<IAssetEntity?> FindAssetBySlugAsync(DomainId appId, string slug,
CancellationToken ct = default)
{
using (Profiler.TraceMethod<MongoAssetRepository>())
{
var assetEntity =
await Collection.Find(x => x.IndexedAppId == appId && !x.IsDeleted && x.Slug == slug)
.FirstOrDefaultAsync();
.FirstOrDefaultAsync(ct = default);
return assetEntity;
}
}
public async Task<IAssetEntity?> FindAssetAsync(DomainId appId, DomainId id)
public async Task<IAssetEntity?> FindAssetAsync(DomainId appId, DomainId id,
CancellationToken ct = default)
{
using (Profiler.TraceMethod<MongoAssetRepository>())
{
@ -207,19 +214,20 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
var assetEntity =
await Collection.Find(x => x.DocumentId == documentId && !x.IsDeleted)
.FirstOrDefaultAsync();
.FirstOrDefaultAsync(ct = default);
return assetEntity;
}
}
public async Task<IAssetEntity?> FindAssetAsync(DomainId id)
public async Task<IAssetEntity?> FindAssetAsync(DomainId id,
CancellationToken ct = default)
{
using (Profiler.TraceMethod<MongoAssetRepository>())
{
var assetEntity =
await Collection.Find(x => x.Id == id && !x.IsDeleted)
.FirstOrDefaultAsync();
.FirstOrDefaultAsync(ct = default);
return assetEntity;
}

5
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Assets/MongoAssetRepository_SnapshotStore.cs

@ -65,11 +65,12 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Assets
}
}
async Task ISnapshotStore<AssetDomainObject.State>.ReadAllAsync(Func<AssetDomainObject.State, long, Task> callback, CancellationToken ct)
async Task ISnapshotStore<AssetDomainObject.State>.ReadAllAsync(Func<AssetDomainObject.State, long, Task> callback,
CancellationToken ct)
{
using (Profiler.TraceMethod<MongoAssetRepository>())
{
await Collection.Find(new BsonDocument(), options: Batching.Options).ForEachPipedAsync(x => callback(Map(x), x.Version), ct);
await Collection.Find(new BsonDocument(), Batching.Options).ForEachPipedAsync(x => callback(Map(x), x.Version), ct);
}
}

58
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentCollection.cs

@ -61,7 +61,8 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
return name;
}
protected override async Task SetupCollectionAsync(IMongoCollection<MongoContentEntity> collection, CancellationToken ct = default)
protected override async Task SetupCollectionAsync(IMongoCollection<MongoContentEntity> collection,
CancellationToken ct)
{
if (useWildcardIndex)
{
@ -82,89 +83,103 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
await queryScheduled.PrepareAsync(collection, skipIndex, ct);
}
public IAsyncEnumerable<IContentEntity> StreamAll(DomainId appId, HashSet<DomainId>? schemaIds, CancellationToken ct)
public Task ResetScheduledAsync(DomainId documentId,
CancellationToken ct)
{
return Collection.UpdateOneAsync(x => x.DocumentId == documentId, Update.Unset(x => x.ScheduleJob).Unset(x => x.ScheduledAt), cancellationToken: ct);
}
public IAsyncEnumerable<IContentEntity> StreamAll(DomainId appId, HashSet<DomainId>? schemaIds,
CancellationToken ct)
{
return queryAsStream.StreamAll(appId, schemaIds, ct);
}
public async Task<IResultList<IContentEntity>> QueryAsync(IAppEntity app, List<ISchemaEntity> schemas, Q q)
public async Task<IResultList<IContentEntity>> QueryAsync(IAppEntity app, List<ISchemaEntity> schemas, Q q,
CancellationToken ct)
{
using (Profiler.TraceMethod<MongoContentRepository>())
{
if (q.Ids != null && q.Ids.Count > 0)
{
return await queryByIds.QueryAsync(app.Id, schemas, q);
return await queryByIds.QueryAsync(app.Id, schemas, q, ct);
}
if (q.Referencing != default)
{
return await queryReferences.QueryAsync(app.Id, schemas, q);
return await queryReferences.QueryAsync(app.Id, schemas, q, ct);
}
if (q.Reference != default)
{
return await queryByQuery.QueryAsync(app, schemas, q);
return await queryByQuery.QueryAsync(app, schemas, q, ct);
}
return ResultList.CreateFrom<IContentEntity>(0);
}
}
public async Task<IResultList<IContentEntity>> QueryAsync(IAppEntity app, ISchemaEntity schema, Q q)
public async Task<IResultList<IContentEntity>> QueryAsync(IAppEntity app, ISchemaEntity schema, Q q,
CancellationToken ct)
{
using (Profiler.TraceMethod<MongoContentRepository>())
{
if (q.Ids != null && q.Ids.Count > 0)
{
return await queryByIds.QueryAsync(app.Id, new List<ISchemaEntity> { schema }, q);
return await queryByIds.QueryAsync(app.Id, new List<ISchemaEntity> { schema }, q, ct);
}
if (q.Referencing == default)
{
return await queryByQuery.QueryAsync(app, schema, q);
return await queryByQuery.QueryAsync(app, schema, q, ct);
}
return ResultList.CreateFrom<IContentEntity>(0);
}
}
public async Task<IContentEntity?> FindContentAsync(ISchemaEntity schema, DomainId id)
public async Task<IContentEntity?> FindContentAsync(ISchemaEntity schema, DomainId id,
CancellationToken ct)
{
using (Profiler.TraceMethod<MongoContentRepository>())
{
return await queryBdId.QueryAsync(schema, id);
return await queryBdId.QueryAsync(schema, id, ct);
}
}
public async Task QueryScheduledWithoutDataAsync(Instant now, Func<IContentEntity, Task> callback)
public async Task QueryScheduledWithoutDataAsync(Instant now, Func<IContentEntity, Task> callback,
CancellationToken ct)
{
using (Profiler.TraceMethod<MongoContentRepository>())
{
await queryScheduled.QueryAsync(now, callback);
await queryScheduled.QueryAsync(now, callback, ct);
}
}
public async Task<IReadOnlyList<(DomainId SchemaId, DomainId Id, Status Status)>> QueryIdsAsync(DomainId appId, HashSet<DomainId> ids)
public async Task<IReadOnlyList<(DomainId SchemaId, DomainId Id, Status Status)>> QueryIdsAsync(DomainId appId, HashSet<DomainId> ids,
CancellationToken ct)
{
using (Profiler.TraceMethod<MongoContentRepository>())
{
return await queryByIds.QueryIdsAsync(appId, ids);
return await queryByIds.QueryIdsAsync(appId, ids, ct);
}
}
public async Task<IReadOnlyList<(DomainId SchemaId, DomainId Id, Status Status)>> QueryIdsAsync(DomainId appId, DomainId schemaId, FilterNode<ClrValue> filterNode)
public async Task<IReadOnlyList<(DomainId SchemaId, DomainId Id, Status Status)>> QueryIdsAsync(DomainId appId, DomainId schemaId, FilterNode<ClrValue> filterNode,
CancellationToken ct)
{
using (Profiler.TraceMethod<MongoContentRepository>())
{
return await queryByQuery.QueryIdsAsync(appId, schemaId, filterNode);
return await queryByQuery.QueryIdsAsync(appId, schemaId, filterNode, ct);
}
}
public async Task<bool> HasReferrersAsync(DomainId appId, DomainId contentId)
public async Task<bool> HasReferrersAsync(DomainId appId, DomainId contentId,
CancellationToken ct)
{
using (Profiler.TraceMethod<MongoContentRepository>())
{
return await queryReferrers.CheckExistsAsync(appId, contentId);
return await queryReferrers.CheckExistsAsync(appId, contentId, ct);
}
}
@ -175,11 +190,6 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
return result?["vs"].AsInt64 ?? EtagVersion.Empty;
}
public Task ResetScheduledAsync(DomainId documentId)
{
return Collection.UpdateOneAsync(x => x.DocumentId == documentId, Update.Unset(x => x.ScheduleJob).Unset(x => x.ScheduledAt));
}
public Task UpsertVersionedAsync(DomainId documentId, long oldVersion, MongoContentEntity entity)
{
return Collection.UpsertVersionedAsync(documentId, oldVersion, entity.Version, entity);

53
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository.cs

@ -55,84 +55,93 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
await collectionPublished.InitializeAsync(ct);
}
public IAsyncEnumerable<IContentEntity> StreamAll(DomainId appId, HashSet<DomainId>? schemaIds, CancellationToken ct)
public IAsyncEnumerable<IContentEntity> StreamAll(DomainId appId, HashSet<DomainId>? schemaIds,
CancellationToken ct = default)
{
return collectionAll.StreamAll(appId, schemaIds, ct);
}
public Task<IResultList<IContentEntity>> QueryAsync(IAppEntity app, List<ISchemaEntity> schemas, Q q, SearchScope scope)
public Task<IResultList<IContentEntity>> QueryAsync(IAppEntity app, List<ISchemaEntity> schemas, Q q, SearchScope scope,
CancellationToken ct = default)
{
if (scope == SearchScope.All)
{
return collectionAll.QueryAsync(app, schemas, q);
return collectionAll.QueryAsync(app, schemas, q, ct);
}
else
{
return collectionPublished.QueryAsync(app, schemas, q);
return collectionPublished.QueryAsync(app, schemas, q, ct);
}
}
public Task<IResultList<IContentEntity>> QueryAsync(IAppEntity app, ISchemaEntity schema, Q q, SearchScope scope)
public Task<IResultList<IContentEntity>> QueryAsync(IAppEntity app, ISchemaEntity schema, Q q, SearchScope scope,
CancellationToken ct = default)
{
if (scope == SearchScope.All)
{
return collectionAll.QueryAsync(app, schema, q);
return collectionAll.QueryAsync(app, schema, q, ct);
}
else
{
return collectionPublished.QueryAsync(app, schema, q);
return collectionPublished.QueryAsync(app, schema, q, ct);
}
}
public Task<IContentEntity?> FindContentAsync(IAppEntity app, ISchemaEntity schema, DomainId id, SearchScope scope)
public Task<IContentEntity?> FindContentAsync(IAppEntity app, ISchemaEntity schema, DomainId id, SearchScope scope,
CancellationToken ct = default)
{
if (scope == SearchScope.All)
{
return collectionAll.FindContentAsync(schema, id);
return collectionAll.FindContentAsync(schema, id, ct);
}
else
{
return collectionPublished.FindContentAsync(schema, id);
return collectionPublished.FindContentAsync(schema, id, ct);
}
}
public Task<IReadOnlyList<(DomainId SchemaId, DomainId Id, Status Status)>> QueryIdsAsync(DomainId appId, HashSet<DomainId> ids, SearchScope scope)
public Task<IReadOnlyList<(DomainId SchemaId, DomainId Id, Status Status)>> QueryIdsAsync(DomainId appId, HashSet<DomainId> ids, SearchScope scope,
CancellationToken ct = default)
{
if (scope == SearchScope.All)
{
return collectionAll.QueryIdsAsync(appId, ids);
return collectionAll.QueryIdsAsync(appId, ids, ct);
}
else
{
return collectionPublished.QueryIdsAsync(appId, ids);
return collectionPublished.QueryIdsAsync(appId, ids, ct);
}
}
public Task<bool> HasReferrersAsync(DomainId appId, DomainId contentId, SearchScope scope)
public Task<bool> HasReferrersAsync(DomainId appId, DomainId contentId, SearchScope scope,
CancellationToken ct = default)
{
if (scope == SearchScope.All)
{
return collectionAll.HasReferrersAsync(appId, contentId);
return collectionAll.HasReferrersAsync(appId, contentId, ct);
}
else
{
return collectionPublished.HasReferrersAsync(appId, contentId);
return collectionPublished.HasReferrersAsync(appId, contentId, ct);
}
}
public Task ResetScheduledAsync(DomainId documentId)
public Task ResetScheduledAsync(DomainId documentId,
CancellationToken ct = default)
{
return collectionAll.ResetScheduledAsync(documentId);
return collectionAll.ResetScheduledAsync(documentId, ct);
}
public Task QueryScheduledWithoutDataAsync(Instant now, Func<IContentEntity, Task> callback)
public Task QueryScheduledWithoutDataAsync(Instant now, Func<IContentEntity, Task> callback,
CancellationToken ct = default)
{
return collectionAll.QueryScheduledWithoutDataAsync(now, callback);
return collectionAll.QueryScheduledWithoutDataAsync(now, callback, ct);
}
public Task<IReadOnlyList<(DomainId SchemaId, DomainId Id, Status Status)>> QueryIdsAsync(DomainId appId, DomainId schemaId, FilterNode<ClrValue> filterNode)
public Task<IReadOnlyList<(DomainId SchemaId, DomainId Id, Status Status)>> QueryIdsAsync(DomainId appId, DomainId schemaId, FilterNode<ClrValue> filterNode,
CancellationToken ct = default)
{
return collectionAll.QueryIdsAsync(appId, schemaId, filterNode);
return collectionAll.QueryIdsAsync(appId, schemaId, filterNode, ct);
}
public IEnumerable<IMongoCollection<MongoContentEntity>> GetInternalCollections()

3
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository_SnapshotStore.cs

@ -21,7 +21,8 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
{
public partial class MongoContentRepository : ISnapshotStore<ContentDomainObject.State>
{
Task ISnapshotStore<ContentDomainObject.State>.ReadAllAsync(Func<ContentDomainObject.State, long, Task> callback, CancellationToken ct)
Task ISnapshotStore<ContentDomainObject.State>.ReadAllAsync(Func<ContentDomainObject.State, long, Task> callback,
CancellationToken ct)
{
return Task.CompletedTask;
}

6
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Operations/Extensions.cs

@ -6,6 +6,7 @@
// ==========================================================================
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Driver;
@ -35,7 +36,8 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
public Status Status { get; set; }
}
public static Task<List<StatusModel>> FindStatusAsync(this IMongoCollection<MongoContentEntity> collection, FilterDefinition<MongoContentEntity> filter)
public static Task<List<StatusModel>> FindStatusAsync(this IMongoCollection<MongoContentEntity> collection, FilterDefinition<MongoContentEntity> filter,
CancellationToken ct)
{
var projections = Builders<MongoContentEntity>.Projection;
@ -44,7 +46,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
.Include(x => x.Id)
.Include(x => x.IndexedSchemaId)
.Include(x => x.Status))
.ToListAsync();
.ToListAsync(ct);
}
}
}

2
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Operations/OperationBase.cs

@ -31,7 +31,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
}
}
protected virtual Task PrepareAsync(CancellationToken ct = default)
protected virtual Task PrepareAsync(CancellationToken ct)
{
return Task.CompletedTask;
}

2
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Operations/QueryAsStream.cs

@ -17,7 +17,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
{
public sealed class QueryAsStream : OperationBase
{
protected override async Task PrepareAsync(CancellationToken ct = default)
protected override async Task PrepareAsync(CancellationToken ct)
{
var indexBySchema =
new CreateIndexModel<MongoContentEntity>(Index

6
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Operations/QueryById.cs

@ -5,6 +5,7 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Threading;
using System.Threading.Tasks;
using MongoDB.Driver;
using Squidex.Domain.Apps.Entities.Contents;
@ -15,7 +16,8 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
{
internal sealed class QueryById : OperationBase
{
public async Task<IContentEntity?> QueryAsync(ISchemaEntity schema, DomainId id)
public async Task<IContentEntity?> QueryAsync(ISchemaEntity schema, DomainId id,
CancellationToken ct)
{
Guard.NotNull(schema, nameof(schema));
@ -23,7 +25,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
var find = Collection.Find(x => x.DocumentId == documentId);
var contentEntity = await find.FirstOrDefaultAsync();
var contentEntity = await find.FirstOrDefaultAsync(ct);
if (contentEntity != null)
{

11
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Operations/QueryByIds.cs

@ -7,6 +7,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MongoDB.Driver;
using Squidex.Domain.Apps.Core.Contents;
@ -20,7 +21,8 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
{
internal sealed class QueryByIds : OperationBase
{
public async Task<IReadOnlyList<(DomainId SchemaId, DomainId Id, Status Status)>> QueryIdsAsync(DomainId appId, HashSet<DomainId> ids)
public async Task<IReadOnlyList<(DomainId SchemaId, DomainId Id, Status Status)>> QueryIdsAsync(DomainId appId, HashSet<DomainId> ids,
CancellationToken ct)
{
if (ids == null || ids.Count == 0)
{
@ -29,12 +31,13 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
var filter = CreateFilter(appId, null, ids);
var contentItems = await Collection.FindStatusAsync(filter);
var contentItems = await Collection.FindStatusAsync(filter, ct);
return contentItems.Select(x => (x.IndexedSchemaId, x.Id, x.Status)).ToList();
}
public async Task<IResultList<IContentEntity>> QueryAsync(DomainId appId, List<ISchemaEntity> schemas, Q q)
public async Task<IResultList<IContentEntity>> QueryAsync(DomainId appId, List<ISchemaEntity> schemas, Q q,
CancellationToken ct)
{
Guard.NotNull(q, nameof(q));
@ -54,7 +57,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
}
else if (contentTotal >= q.Query.Take || q.Query.Skip > 0)
{
contentTotal = await Collection.Find(filter).CountDocumentsAsync();
contentTotal = await Collection.Find(filter).CountDocumentsAsync(ct);
}
return ResultList.Create(contentTotal, contentEntities);

30
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Operations/QueryByQuery.cs

@ -1,4 +1,4 @@
// ==========================================================================
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
@ -41,7 +41,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
this.appProvider = appProvider;
}
protected override async Task PrepareAsync(CancellationToken ct = default)
protected override async Task PrepareAsync(CancellationToken ct)
{
var indexBySchemaWithRefs =
new CreateIndexModel<MongoContentEntity>(Index
@ -62,7 +62,8 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
await Collection.Indexes.CreateOneAsync(indexBySchema, cancellationToken: ct);
}
public async Task<IReadOnlyList<(DomainId SchemaId, DomainId Id, Status Status)>> QueryIdsAsync(DomainId appId, DomainId schemaId, FilterNode<ClrValue> filterNode)
public async Task<IReadOnlyList<(DomainId SchemaId, DomainId Id, Status Status)>> QueryIdsAsync(DomainId appId, DomainId schemaId, FilterNode<ClrValue> filterNode,
CancellationToken ct)
{
Guard.NotNull(filterNode, nameof(filterNode));
@ -77,7 +78,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
var filter = BuildFilter(appId, schemaId, filterNode.AdjustToModel(appId));
var contentItems = await Collection.FindStatusAsync(filter);
var contentItems = await Collection.FindStatusAsync(filter, ct);
return contentItems.Select(x => (x.IndexedSchemaId, x.Id, x.Status)).ToList();
}
@ -91,7 +92,8 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
}
}
public async Task<IResultList<IContentEntity>> QueryAsync(IAppEntity app, List<ISchemaEntity> schemas, Q q)
public async Task<IResultList<IContentEntity>> QueryAsync(IAppEntity app, List<ISchemaEntity> schemas, Q q,
CancellationToken ct)
{
Guard.NotNull(app, nameof(app));
Guard.NotNull(q, nameof(q));
@ -102,7 +104,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
var filter = CreateFilter(app.Id, schemas.Select(x => x.Id), query, q.Reference, q.CreatedBy);
var contentEntities = await FindContentsAsync(query, filter);
var contentEntities = await FindContentsAsync(query, filter, ct);
var contentTotal = (long)contentEntities.Count;
if (q.NoTotal)
@ -111,7 +113,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
}
else if (contentTotal >= q.Query.Take || q.Query.Skip > 0)
{
contentTotal = await Collection.Find(filter).CountDocumentsAsync();
contentTotal = await Collection.Find(filter).CountDocumentsAsync(ct);
}
return ResultList.Create<IContentEntity>(contentTotal, contentEntities);
@ -126,7 +128,8 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
}
}
public async Task<IResultList<IContentEntity>> QueryAsync(IAppEntity app, ISchemaEntity schema, Q q)
public async Task<IResultList<IContentEntity>> QueryAsync(IAppEntity app, ISchemaEntity schema, Q q,
CancellationToken ct)
{
Guard.NotNull(app, nameof(app));
Guard.NotNull(schema, nameof(schema));
@ -138,7 +141,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
var filter = CreateFilter(schema.AppId.Id, Enumerable.Repeat(schema.Id, 1), query, q.Reference, q.CreatedBy);
var contentEntities = await FindContentsAsync(query, filter);
var contentEntities = await FindContentsAsync(query, filter, ct);
var contentTotal = (long)contentEntities.Count;
if (q.NoTotal)
@ -147,7 +150,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
}
else if (contentTotal >= q.Query.Take || q.Query.Skip > 0)
{
contentTotal = await Collection.Find(filter).CountDocumentsAsync();
contentTotal = await Collection.Find(filter).CountDocumentsAsync(ct);
}
return ResultList.Create<IContentEntity>(contentTotal, contentEntities);
@ -162,7 +165,8 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
}
}
private async Task<List<MongoContentEntity>> FindContentsAsync(ClrQuery query, FilterDefinition<MongoContentEntity> filter)
private async Task<List<MongoContentEntity>> FindContentsAsync(ClrQuery query, FilterDefinition<MongoContentEntity> filter,
CancellationToken ct)
{
if (query.Skip > 0 && !IsSatisfiedByIndex(query))
{
@ -181,7 +185,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
.QuerySkip(query)
.QueryLimit(query)
.Lookup<IdOnly, MongoContentEntity, IdOnly>(Collection, x => x.Id, x => x.DocumentId, x => x.Joined)
.ToListAsync();
.ToListAsync(ct);
return joined.Select(x => x.Joined[0]).ToList();
}
@ -191,7 +195,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
.QuerySort(query)
.QueryLimit(query)
.QuerySkip(query)
.ToListAsync();
.ToListAsync(ct);
return await result;
}

8
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Operations/QueryReferences.cs

@ -6,6 +6,7 @@
// ==========================================================================
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Driver;
@ -36,7 +37,8 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
this.queryByIds = queryByIds;
}
public async Task<IResultList<IContentEntity>> QueryAsync(DomainId appId, List<ISchemaEntity> schemas, Q q)
public async Task<IResultList<IContentEntity>> QueryAsync(DomainId appId, List<ISchemaEntity> schemas, Q q,
CancellationToken ct)
{
var documentId = DomainId.Combine(appId, q.Referencing);
@ -45,7 +47,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
.Find(x => x.DocumentId == documentId)
.Project<ReferencedIdsOnly>(Projection.Include(x => x.ReferencedIds));
var contentEntity = await find.FirstOrDefaultAsync();
var contentEntity = await find.FirstOrDefaultAsync(ct);
if (contentEntity == null)
{
@ -59,7 +61,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
q = q.WithReferencing(default).WithIds(contentEntity.ReferencedIds!);
return await queryByIds.QueryAsync(appId, schemas, q);
return await queryByIds.QueryAsync(appId, schemas, q, ct);
}
}
}

9
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Operations/QueryReferrers.cs

@ -15,7 +15,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
{
internal sealed class QueryReferrers : OperationBase
{
protected override Task PrepareAsync(CancellationToken ct = default)
protected override Task PrepareAsync(CancellationToken ct)
{
var index =
new CreateIndexModel<MongoContentEntity>(Index
@ -26,7 +26,8 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
return Collection.Indexes.CreateOneAsync(index, cancellationToken: ct);
}
public async Task<bool> CheckExistsAsync(DomainId appId, DomainId contentId)
public async Task<bool> CheckExistsAsync(DomainId appId, DomainId contentId,
CancellationToken ct)
{
var filter =
Filter.And(
@ -37,9 +38,9 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
var hasReferrerAsync =
await Collection.Find(filter).Only(x => x.Id)
.AnyAsync();
.AnyAsync(ct);
return hasReferrerAsync;
}
}
}
}

7
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Operations/QueryScheduled.cs

@ -18,7 +18,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
{
internal sealed class QueryScheduled : OperationBase
{
protected override Task PrepareAsync(CancellationToken ct = default)
protected override Task PrepareAsync(CancellationToken ct)
{
var index =
new CreateIndexModel<MongoContentEntity>(Index
@ -28,7 +28,8 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
return Collection.Indexes.CreateOneAsync(index, cancellationToken: ct);
}
public Task QueryAsync(Instant now, Func<IContentEntity, Task> callback)
public Task QueryAsync(Instant now, Func<IContentEntity, Task> callback,
CancellationToken ct)
{
Guard.NotNull(callback, nameof(callback));
@ -36,7 +37,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
.ForEachAsync(c =>
{
callback(c);
});
}, ct);
}
}
}

3
backend/src/Squidex.Domain.Apps.Entities.MongoDb/FullText/MongoTextIndex.cs

@ -30,7 +30,8 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.FullText
{
}
protected override Task SetupCollectionAsync(IMongoCollection<MongoTextIndexEntity> collection, CancellationToken ct = default)
protected override Task SetupCollectionAsync(IMongoCollection<MongoTextIndexEntity> collection,
CancellationToken ct)
{
return collection.Indexes.CreateManyAsync(new[]
{

3
backend/src/Squidex.Domain.Apps.Entities.MongoDb/History/MongoHistoryEventRepository.cs

@ -41,7 +41,8 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.History
return "Projections_History";
}
protected override Task SetupCollectionAsync(IMongoCollection<HistoryEvent> collection, CancellationToken ct = default)
protected override Task SetupCollectionAsync(IMongoCollection<HistoryEvent> collection,
CancellationToken ct = default)
{
return collection.Indexes.CreateManyAsync(new[]
{

19
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Rules/MongoRuleEventRepository.cs

@ -36,9 +36,10 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Rules
return "RuleEvents";
}
protected override async Task SetupCollectionAsync(IMongoCollection<MongoRuleEventEntity> collection, CancellationToken ct = default)
protected override async Task SetupCollectionAsync(IMongoCollection<MongoRuleEventEntity> collection,
CancellationToken ct = default)
{
await statisticsCollection.InitializeAsync(ct);
await statisticsCollection.InitializeAsync(ct = default);
await collection.Indexes.CreateManyAsync(new[]
{
@ -63,7 +64,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Rules
return Collection.Find(x => x.NextAttempt < now).ForEachAsync(callback, ct);
}
public async Task<IResultList<IRuleEventEntity>> QueryByAppAsync(DomainId appId, DomainId? ruleId = null, int skip = 0, int take = 20)
public async Task<IResultList<IRuleEventEntity>> QueryByAppAsync(DomainId appId, DomainId? ruleId = null, int skip = 0, int take = 20, CancellationToken ct = default)
{
var filter = Filter.Eq(x => x.AppId, appId);
@ -72,22 +73,22 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Rules
filter = Filter.And(filter, Filter.Eq(x => x.RuleId, ruleId.Value));
}
var ruleEventEntities = await Collection.Find(filter).Skip(skip).Limit(take).SortByDescending(x => x.Created).ToListAsync();
var ruleEventEntities = await Collection.Find(filter).Skip(skip).Limit(take).SortByDescending(x => x.Created).ToListAsync(ct = default);
var ruleEventTotal = (long)ruleEventEntities.Count;
if (ruleEventTotal >= take || skip > 0)
{
ruleEventTotal = await Collection.Find(filter).CountDocumentsAsync();
ruleEventTotal = await Collection.Find(filter).CountDocumentsAsync(ct = default);
}
return ResultList.Create(ruleEventTotal, ruleEventEntities);
}
public async Task<IRuleEventEntity> FindAsync(DomainId id)
public async Task<IRuleEventEntity> FindAsync(DomainId id, CancellationToken ct = default)
{
var ruleEvent =
await Collection.Find(x => x.DocumentId == id)
.FirstOrDefaultAsync();
.FirstOrDefaultAsync(ct = default);
return ruleEvent;
}
@ -149,9 +150,9 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Rules
}
}
public Task<IReadOnlyList<RuleStatistics>> QueryStatisticsByAppAsync(DomainId appId)
public Task<IReadOnlyList<RuleStatistics>> QueryStatisticsByAppAsync(DomainId appId, CancellationToken ct = default)
{
return statisticsCollection.QueryByAppAsync(appId);
return statisticsCollection.QueryByAppAsync(appId, ct);
}
}
}

8
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Rules/MongoRuleStatisticsCollection.cs

@ -39,7 +39,8 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Rules
return "RuleStatistics";
}
protected override Task SetupCollectionAsync(IMongoCollection<RuleStatistics> collection, CancellationToken ct = default)
protected override Task SetupCollectionAsync(IMongoCollection<RuleStatistics> collection,
CancellationToken ct)
{
return collection.Indexes.CreateOneAsync(
new CreateIndexModel<RuleStatistics>(
@ -49,9 +50,10 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Rules
cancellationToken: ct);
}
public async Task<IReadOnlyList<RuleStatistics>> QueryByAppAsync(DomainId appId)
public async Task<IReadOnlyList<RuleStatistics>> QueryByAppAsync(DomainId appId,
CancellationToken ct)
{
var statistics = await Collection.Find(x => x.AppId == appId).ToListAsync();
var statistics = await Collection.Find(x => x.AppId == appId).ToListAsync(ct);
return statistics;
}

6
backend/src/Squidex.Domain.Apps.Entities/Apps/AppSettingsSearchSource.cs

@ -6,6 +6,7 @@
// ==========================================================================
using System;
using System.Threading;
using System.Threading.Tasks;
using Squidex.Domain.Apps.Core;
using Squidex.Domain.Apps.Entities.Search;
@ -26,7 +27,8 @@ namespace Squidex.Domain.Apps.Entities.Apps
this.urlGenerator = urlGenerator;
}
public Task<SearchResults> SearchAsync(string query, Context context)
public Task<SearchResults> SearchAsync(string query, Context context,
CancellationToken ct)
{
var result = new SearchResults();
@ -81,4 +83,4 @@ namespace Squidex.Domain.Apps.Entities.Apps
return Task.FromResult(result);
}
}
}
}

6
backend/src/Squidex.Domain.Apps.Entities/Apps/DefaultAppImageStore.cs

@ -24,14 +24,16 @@ namespace Squidex.Domain.Apps.Entities.Apps
this.assetStore = assetStore;
}
public Task DownloadAsync(DomainId appId, Stream stream, CancellationToken ct = default)
public Task DownloadAsync(DomainId appId, Stream stream,
CancellationToken ct = default)
{
var fileName = GetFileName(appId);
return assetStore.DownloadAsync(fileName, stream, default, ct);
}
public Task UploadAsync(DomainId appId, Stream stream, CancellationToken ct = default)
public Task UploadAsync(DomainId appId, Stream stream,
CancellationToken ct = default)
{
var fileName = GetFileName(appId);

3
backend/src/Squidex.Domain.Apps.Entities/Apps/DefaultAppLogStore.cs

@ -74,7 +74,8 @@ namespace Squidex.Domain.Apps.Entities.Apps
return requestLogStore.LogAsync(storedRequest);
}
public async Task ReadLogAsync(DomainId appId, DateTime fromDate, DateTime toDate, Stream stream, CancellationToken ct = default)
public async Task ReadLogAsync(DomainId appId, DateTime fromDate, DateTime toDate, Stream stream,
CancellationToken ct = default)
{
Guard.NotNull(appId, nameof(appId));

6
backend/src/Squidex.Domain.Apps.Entities/Assets/AssetsSearchSource.cs

@ -5,6 +5,7 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Threading;
using System.Threading.Tasks;
using Squidex.Domain.Apps.Core;
using Squidex.Domain.Apps.Entities.Apps;
@ -30,7 +31,8 @@ namespace Squidex.Domain.Apps.Entities.Assets
this.urlGenerator = urlGenerator;
}
public async Task<SearchResults> SearchAsync(string query, Context context)
public async Task<SearchResults> SearchAsync(string query, Context context,
CancellationToken ct)
{
var result = new SearchResults();
@ -40,7 +42,7 @@ namespace Squidex.Domain.Apps.Entities.Assets
var clrQuery = new ClrQuery { Filter = filter, Take = 5 };
var assets = await assetQuery.QueryAsync(context, null, Q.Empty.WithQuery(clrQuery));
var assets = await assetQuery.QueryAsync(context, null, Q.Empty.WithQuery(clrQuery), ct);
if (assets.Count > 0)
{

15
backend/src/Squidex.Domain.Apps.Entities/Assets/DefaultAssetFileStore.cs

@ -29,7 +29,8 @@ namespace Squidex.Domain.Apps.Entities.Assets
return assetStore.GeneratePublicUrl(fileName);
}
public async Task<long> GetFileSizeAsync(DomainId appId, DomainId id, long fileVersion, CancellationToken ct = default)
public async Task<long> GetFileSizeAsync(DomainId appId, DomainId id, long fileVersion,
CancellationToken ct = default)
{
try
{
@ -45,7 +46,8 @@ namespace Squidex.Domain.Apps.Entities.Assets
}
}
public async Task DownloadAsync(DomainId appId, DomainId id, long fileVersion, Stream stream, BytesRange range = default, CancellationToken ct = default)
public async Task DownloadAsync(DomainId appId, DomainId id, long fileVersion, Stream stream, BytesRange range = default,
CancellationToken ct = default)
{
try
{
@ -61,19 +63,22 @@ namespace Squidex.Domain.Apps.Entities.Assets
}
}
public Task UploadAsync(DomainId appId, DomainId id, long fileVersion, Stream stream, CancellationToken ct = default)
public Task UploadAsync(DomainId appId, DomainId id, long fileVersion, Stream stream,
CancellationToken ct = default)
{
var fileName = GetFileName(appId, id, fileVersion);
return assetStore.UploadAsync(fileName, stream, true, ct);
}
public Task UploadAsync(string tempFile, Stream stream, CancellationToken ct = default)
public Task UploadAsync(string tempFile, Stream stream,
CancellationToken ct = default)
{
return assetStore.UploadAsync(tempFile, stream, false, ct);
}
public Task CopyAsync(string tempFile, DomainId appId, DomainId id, long fileVersion, CancellationToken ct = default)
public Task CopyAsync(string tempFile, DomainId appId, DomainId id, long fileVersion,
CancellationToken ct = default)
{
var fileName = GetFileName(appId, id, fileVersion);

2
backend/src/Squidex.Domain.Apps.Entities/Assets/DomainObject/AssetCommandMiddleware.cs

@ -158,7 +158,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
if (payload is not IEnrichedAssetEntity)
{
payload = await assetEnricher.EnrichAsync(asset, contextProvider.Context);
payload = await assetEnricher.EnrichAsync(asset, contextProvider.Context, default);
}
}

4
backend/src/Squidex.Domain.Apps.Entities/Assets/DomainObject/Guards/GuardAsset.cs

@ -1,4 +1,4 @@
// ==========================================================================
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
@ -43,7 +43,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject.Guards
if (command.CheckReferrers)
{
var hasReferrer = await contentRepository.HasReferrersAsync(asset.AppId.Id, asset.Id, SearchScope.All);
var hasReferrer = await contentRepository.HasReferrersAsync(asset.AppId.Id, asset.Id, SearchScope.All, default);
if (hasReferrer)
{

7
backend/src/Squidex.Domain.Apps.Entities/Assets/IAssetEnricher.cs

@ -6,14 +6,15 @@
// ==========================================================================
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace Squidex.Domain.Apps.Entities.Assets
{
public interface IAssetEnricher
{
Task<IEnrichedAssetEntity> EnrichAsync(IAssetEntity asset, Context context);
Task<IEnrichedAssetEntity> EnrichAsync(IAssetEntity asset, Context context, CancellationToken ct = default);
Task<IReadOnlyList<IEnrichedAssetEntity>> EnrichAsync(IEnumerable<IAssetEntity> assets, Context context);
Task<IReadOnlyList<IEnrichedAssetEntity>> EnrichAsync(IEnumerable<IAssetEntity> assets, Context context, CancellationToken ct = default);
}
}
}

17
backend/src/Squidex.Domain.Apps.Entities/Assets/IAssetQueryService.cs

@ -6,6 +6,7 @@
// ==========================================================================
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Squidex.Infrastructure;
@ -13,20 +14,20 @@ namespace Squidex.Domain.Apps.Entities.Assets
{
public interface IAssetQueryService
{
Task<IResultList<IEnrichedAssetEntity>> QueryAsync(Context context, DomainId? parentId, Q q);
Task<IResultList<IEnrichedAssetEntity>> QueryAsync(Context context, DomainId? parentId, Q q, CancellationToken ct = default);
Task<IResultList<IAssetFolderEntity>> QueryAssetFoldersAsync(Context context, DomainId parentId);
Task<IResultList<IAssetFolderEntity>> QueryAssetFoldersAsync(Context context, DomainId parentId, CancellationToken ct = default);
Task<IResultList<IAssetFolderEntity>> QueryAssetFoldersAsync(DomainId appId, DomainId parentId);
Task<IResultList<IAssetFolderEntity>> QueryAssetFoldersAsync(DomainId appId, DomainId parentId, CancellationToken ct = default);
Task<IReadOnlyList<IAssetFolderEntity>> FindAssetFolderAsync(DomainId appId, DomainId id);
Task<IReadOnlyList<IAssetFolderEntity>> FindAssetFolderAsync(DomainId appId, DomainId id, CancellationToken ct = default);
Task<IEnrichedAssetEntity?> FindByHashAsync(Context context, string hash, string fileName, long fileSize);
Task<IEnrichedAssetEntity?> FindByHashAsync(Context context, string hash, string fileName, long fileSize, CancellationToken ct = default);
Task<IEnrichedAssetEntity?> FindAsync(Context context, DomainId id, long version = EtagVersion.Any);
Task<IEnrichedAssetEntity?> FindAsync(Context context, DomainId id, long version = EtagVersion.Any, CancellationToken ct = default);
Task<IEnrichedAssetEntity?> FindBySlugAsync(Context context, string slug);
Task<IEnrichedAssetEntity?> FindBySlugAsync(Context context, string slug, CancellationToken ct = default);
Task<IEnrichedAssetEntity?> FindGlobalAsync(Context context, DomainId id);
Task<IEnrichedAssetEntity?> FindGlobalAsync(Context context, DomainId id, CancellationToken ct = default);
}
}

16
backend/src/Squidex.Domain.Apps.Entities/Assets/Queries/AssetEnricher.cs

@ -8,6 +8,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Squidex.Domain.Apps.Core.Tags;
using Squidex.Infrastructure;
@ -34,17 +35,19 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
this.requestCache = requestCache;
}
public async Task<IEnrichedAssetEntity> EnrichAsync(IAssetEntity asset, Context context)
public async Task<IEnrichedAssetEntity> EnrichAsync(IAssetEntity asset, Context context,
CancellationToken ct)
{
Guard.NotNull(asset, nameof(asset));
Guard.NotNull(context, nameof(context));
var enriched = await EnrichAsync(Enumerable.Repeat(asset, 1), context);
var enriched = await EnrichAsync(Enumerable.Repeat(asset, 1), context, ct);
return enriched[0];
}
public async Task<IReadOnlyList<IEnrichedAssetEntity>> EnrichAsync(IEnumerable<IAssetEntity> assets, Context context)
public async Task<IReadOnlyList<IEnrichedAssetEntity>> EnrichAsync(IEnumerable<IAssetEntity> assets, Context context,
CancellationToken ct)
{
Guard.NotNull(assets, nameof(assets));
Guard.NotNull(context, nameof(context));
@ -60,7 +63,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
if (!context.ShouldSkipAssetEnrichment())
{
await EnrichTagsAsync(results);
await EnrichTagsAsync(results, ct);
EnrichWithMetadataText(results);
}
@ -104,10 +107,13 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
}
}
private async Task EnrichTagsAsync(List<AssetEntity> assets)
private async Task EnrichTagsAsync(List<AssetEntity> assets,
CancellationToken ct)
{
foreach (var group in assets.GroupBy(x => x.AppId.Id))
{
ct.ThrowIfCancellationRequested();
var tagsById = await CalculateTags(group);
foreach (var asset in group)

66
backend/src/Squidex.Domain.Apps.Entities/Assets/Queries/AssetQueryService.cs

@ -7,6 +7,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Squidex.Domain.Apps.Entities.Assets.Repositories;
using Squidex.Infrastructure;
@ -43,7 +44,8 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
this.queryParser = queryParser;
}
public async Task<IReadOnlyList<IAssetFolderEntity>> FindAssetFolderAsync(DomainId appId, DomainId id)
public async Task<IReadOnlyList<IAssetFolderEntity>> FindAssetFolderAsync(DomainId appId, DomainId id,
CancellationToken ct = default)
{
using (Profiler.TraceMethod<AssetQueryService>())
{
@ -51,7 +53,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
while (id != DomainId.Empty)
{
var folder = await assetFolderRepository.FindAssetFolderAsync(appId, id);
var folder = await assetFolderRepository.FindAssetFolderAsync(appId, id, ct);
if (folder == null || result.Any(x => x.Id == folder.Id))
{
@ -68,78 +70,84 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
}
}
public async Task<IResultList<IAssetFolderEntity>> QueryAssetFoldersAsync(DomainId appId, DomainId parentId)
public async Task<IResultList<IAssetFolderEntity>> QueryAssetFoldersAsync(DomainId appId, DomainId parentId,
CancellationToken ct = default)
{
using (Profiler.TraceMethod<AssetQueryService>())
{
var assetFolders = await assetFolderRepository.QueryAsync(appId, parentId);
var assetFolders = await assetFolderRepository.QueryAsync(appId, parentId, ct);
return assetFolders;
}
}
public async Task<IResultList<IAssetFolderEntity>> QueryAssetFoldersAsync(Context context, DomainId parentId)
public async Task<IResultList<IAssetFolderEntity>> QueryAssetFoldersAsync(Context context, DomainId parentId,
CancellationToken ct = default)
{
using (Profiler.TraceMethod<AssetQueryService>())
{
var assetFolders = await assetFolderRepository.QueryAsync(context.App.Id, parentId);
var assetFolders = await assetFolderRepository.QueryAsync(context.App.Id, parentId, ct);
return assetFolders;
}
}
public async Task<IEnrichedAssetEntity?> FindByHashAsync(Context context, string hash, string fileName, long fileSize)
public async Task<IEnrichedAssetEntity?> FindByHashAsync(Context context, string hash, string fileName, long fileSize,
CancellationToken ct = default)
{
Guard.NotNull(context, nameof(context));
using (Profiler.TraceMethod<AssetQueryService>())
{
var asset = await assetRepository.FindAssetByHashAsync(context.App.Id, hash, fileName, fileSize);
var asset = await assetRepository.FindAssetByHashAsync(context.App.Id, hash, fileName, fileSize, ct);
if (asset == null)
{
return null;
}
return await TransformAsync(context, asset);
return await TransformAsync(context, asset, ct);
}
}
public async Task<IEnrichedAssetEntity?> FindBySlugAsync(Context context, string slug)
public async Task<IEnrichedAssetEntity?> FindBySlugAsync(Context context, string slug,
CancellationToken ct = default)
{
Guard.NotNull(context, nameof(context));
using (Profiler.TraceMethod<AssetQueryService>())
{
var asset = await assetRepository.FindAssetBySlugAsync(context.App.Id, slug);
var asset = await assetRepository.FindAssetBySlugAsync(context.App.Id, slug, ct);
if (asset == null)
{
return null;
}
return await TransformAsync(context, asset);
return await TransformAsync(context, asset, ct);
}
}
public async Task<IEnrichedAssetEntity?> FindGlobalAsync(Context context, DomainId id)
public async Task<IEnrichedAssetEntity?> FindGlobalAsync(Context context, DomainId id,
CancellationToken ct = default)
{
Guard.NotNull(context, nameof(context));
using (Profiler.TraceMethod<AssetQueryService>())
{
var asset = await assetRepository.FindAssetAsync(id);
var asset = await assetRepository.FindAssetAsync(id, ct);
if (asset == null)
{
return null;
}
return await TransformAsync(context, asset);
return await TransformAsync(context, asset, ct);
}
}
public async Task<IEnrichedAssetEntity?> FindAsync(Context context, DomainId id, long version = EtagVersion.Any)
public async Task<IEnrichedAssetEntity?> FindAsync(Context context, DomainId id, long version = EtagVersion.Any,
CancellationToken ct = default)
{
Guard.NotNull(context, nameof(context));
@ -153,7 +161,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
}
else
{
asset = await assetRepository.FindAssetAsync(context.App.Id, id);
asset = await assetRepository.FindAssetAsync(context.App.Id, id, ct);
}
if (asset == null)
@ -161,11 +169,12 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
return null;
}
return await TransformAsync(context, asset);
return await TransformAsync(context, asset, ct);
}
}
public async Task<IResultList<IEnrichedAssetEntity>> QueryAsync(Context context, DomainId? parentId, Q q)
public async Task<IResultList<IEnrichedAssetEntity>> QueryAsync(Context context, DomainId? parentId, Q q,
CancellationToken ct = default)
{
Guard.NotNull(context, nameof(context));
@ -178,36 +187,39 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
{
q = await queryParser.ParseAsync(context, q);
var assets = await assetRepository.QueryAsync(context.App.Id, parentId, q);
var assets = await assetRepository.QueryAsync(context.App.Id, parentId, q, ct);
if (q.Ids != null && q.Ids.Count > 0)
{
assets = assets.SortSet(x => x.Id, q.Ids);
}
return await TransformAsync(context, assets);
return await TransformAsync(context, assets, ct);
}
}
private async Task<IResultList<IEnrichedAssetEntity>> TransformAsync(Context context, IResultList<IAssetEntity> assets)
private async Task<IResultList<IEnrichedAssetEntity>> TransformAsync(Context context, IResultList<IAssetEntity> assets,
CancellationToken ct)
{
var transformed = await TransformCoreAsync(context, assets);
var transformed = await TransformCoreAsync(context, assets, ct);
return ResultList.Create(assets.Total, transformed);
}
private async Task<IEnrichedAssetEntity> TransformAsync(Context context, IAssetEntity asset)
private async Task<IEnrichedAssetEntity> TransformAsync(Context context, IAssetEntity asset,
CancellationToken ct)
{
var transformed = await TransformCoreAsync(context, Enumerable.Repeat(asset, 1));
var transformed = await TransformCoreAsync(context, Enumerable.Repeat(asset, 1), ct);
return transformed[0];
}
private async Task<IReadOnlyList<IEnrichedAssetEntity>> TransformCoreAsync(Context context, IEnumerable<IAssetEntity> assets)
private async Task<IReadOnlyList<IEnrichedAssetEntity>> TransformCoreAsync(Context context, IEnumerable<IAssetEntity> assets,
CancellationToken ct)
{
using (Profiler.TraceMethod<AssetQueryService>())
{
return await assetEnricher.EnrichAsync(assets, context);
return await assetEnricher.EnrichAsync(assets, context, ct);
}
}
}

75
backend/src/Squidex.Domain.Apps.Entities/Assets/RebuildFiles.cs

@ -0,0 +1,75 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.IO;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Squidex.Assets;
using Squidex.Domain.Apps.Events.Assets;
using Squidex.Infrastructure;
using Squidex.Infrastructure.EventSourcing;
namespace Squidex.Domain.Apps.Entities.Assets
{
public sealed class RebuildFiles
{
private static readonly MemoryStream DummyStream = new MemoryStream(Encoding.UTF8.GetBytes("dummy"));
private readonly IAssetFileStore assetFileStore;
private readonly IEventStore eventStore;
private readonly IEventDataFormatter eventDataFormatter;
public RebuildFiles(
IAssetFileStore assetFileStore,
IEventStore eventStore,
IEventDataFormatter eventDataFormatter)
{
Guard.NotNull(assetFileStore, nameof(assetFileStore));
Guard.NotNull(eventStore, nameof(eventStore));
Guard.NotNull(eventDataFormatter, nameof(eventDataFormatter));
this.assetFileStore = assetFileStore;
this.eventStore = eventStore;
this.eventDataFormatter = eventDataFormatter;
}
public async Task RepairAsync(CancellationToken ct = default)
{
await foreach (var storedEvent in eventStore.QueryAllAsync("^asset\\-", ct: ct))
{
var @event = eventDataFormatter.ParseIfKnown(storedEvent);
if (@event != null)
{
switch (@event.Payload)
{
case AssetCreated assetCreated:
await TryRepairAsync(assetCreated.AppId, assetCreated.AssetId, assetCreated.FileVersion, ct);
break;
case AssetUpdated assetUpdated:
await TryRepairAsync(assetUpdated.AppId, assetUpdated.AssetId, assetUpdated.FileVersion, ct);
break;
}
}
}
}
private async Task TryRepairAsync(NamedId<DomainId> appId, DomainId id, long fileVersion, CancellationToken ct)
{
try
{
await assetFileStore.GetFileSizeAsync(appId.Id, id, fileVersion, ct);
}
catch (AssetNotFoundException)
{
DummyStream.Position = 0;
await assetFileStore.UploadAsync(appId.Id, id, fileVersion, DummyStream, ct);
}
}
}
}

4
backend/src/Squidex.Domain.Apps.Entities/Assets/RecursiveDeleter.cs

@ -88,14 +88,14 @@ namespace Squidex.Domain.Apps.Entities.Assets
var appId = folderDeleted.AppId;
var childAssetFolders = await assetFolderRepository.QueryChildIdsAsync(appId.Id, folderDeleted.AssetFolderId);
var childAssetFolders = await assetFolderRepository.QueryChildIdsAsync(appId.Id, folderDeleted.AssetFolderId, default);
foreach (var assetFolderId in childAssetFolders)
{
await PublishAsync(new DeleteAssetFolder { AppId = appId, AssetFolderId = assetFolderId });
}
var childAssets = await assetRepository.QueryChildIdsAsync(appId.Id, folderDeleted.AssetFolderId);
var childAssets = await assetRepository.QueryChildIdsAsync(appId.Id, folderDeleted.AssetFolderId, default);
foreach (var assetId in childAssets)
{

7
backend/src/Squidex.Domain.Apps.Entities/Assets/Repositories/IAssetFolderRepository.cs

@ -6,6 +6,7 @@
// ==========================================================================
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Squidex.Infrastructure;
@ -13,10 +14,10 @@ namespace Squidex.Domain.Apps.Entities.Assets.Repositories
{
public interface IAssetFolderRepository
{
Task<IResultList<IAssetFolderEntity>> QueryAsync(DomainId appId, DomainId parentId);
Task<IResultList<IAssetFolderEntity>> QueryAsync(DomainId appId, DomainId parentId, CancellationToken ct = default);
Task<IReadOnlyList<DomainId>> QueryChildIdsAsync(DomainId appId, DomainId parentId);
Task<IReadOnlyList<DomainId>> QueryChildIdsAsync(DomainId appId, DomainId parentId, CancellationToken ct = default);
Task<IAssetFolderEntity?> FindAssetFolderAsync(DomainId appId, DomainId id);
Task<IAssetFolderEntity?> FindAssetFolderAsync(DomainId appId, DomainId id, CancellationToken ct = default);
}
}

16
backend/src/Squidex.Domain.Apps.Entities/Assets/Repositories/IAssetRepository.cs

@ -14,20 +14,20 @@ namespace Squidex.Domain.Apps.Entities.Assets.Repositories
{
public interface IAssetRepository
{
IAsyncEnumerable<IAssetEntity> StreamAll(DomainId appId, CancellationToken ct);
IAsyncEnumerable<IAssetEntity> StreamAll(DomainId appId, CancellationToken ct = default);
Task<IResultList<IAssetEntity>> QueryAsync(DomainId appId, DomainId? parentId, Q q);
Task<IResultList<IAssetEntity>> QueryAsync(DomainId appId, DomainId? parentId, Q q, CancellationToken ct = default);
Task<IReadOnlyList<DomainId>> QueryIdsAsync(DomainId appId, HashSet<DomainId> ids);
Task<IReadOnlyList<DomainId>> QueryIdsAsync(DomainId appId, HashSet<DomainId> ids, CancellationToken ct = default);
Task<IReadOnlyList<DomainId>> QueryChildIdsAsync(DomainId appId, DomainId parentId);
Task<IReadOnlyList<DomainId>> QueryChildIdsAsync(DomainId appId, DomainId parentId, CancellationToken ct = default);
Task<IAssetEntity?> FindAssetByHashAsync(DomainId appId, string hash, string fileName, long fileSize);
Task<IAssetEntity?> FindAssetByHashAsync(DomainId appId, string hash, string fileName, long fileSize, CancellationToken ct = default);
Task<IAssetEntity?> FindAssetBySlugAsync(DomainId appId, string slug);
Task<IAssetEntity?> FindAssetBySlugAsync(DomainId appId, string slug, CancellationToken ct = default);
Task<IAssetEntity?> FindAssetAsync(DomainId appId);
Task<IAssetEntity?> FindAssetAsync(DomainId id, CancellationToken ct = default);
Task<IAssetEntity?> FindAssetAsync(DomainId appId, DomainId id);
Task<IAssetEntity?> FindAssetAsync(DomainId appId, DomainId id, CancellationToken ct = default);
}
}

8
backend/src/Squidex.Domain.Apps.Entities/Backup/BackupGrain.cs

@ -1,4 +1,4 @@
// ==========================================================================
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
@ -119,12 +119,14 @@ namespace Squidex.Domain.Apps.Entities.Backup
Process(job, actor, currentJobToken.Token);
}
private void Process(BackupJob job, RefToken actor, CancellationToken ct)
private void Process(BackupJob job, RefToken actor,
CancellationToken ct)
{
ProcessAsync(job, actor, ct).Forget();
}
private async Task ProcessAsync(BackupJob job, RefToken actor, CancellationToken ct)
private async Task ProcessAsync(BackupJob job, RefToken actor,
CancellationToken ct)
{
var handlers = CreateHandlers();

4
backend/src/Squidex.Domain.Apps.Entities/Contents/ContentSchedulerGrain.cs

@ -94,7 +94,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
}
catch (DomainObjectNotFoundException)
{
await contentRepository.ResetScheduledAsync(content.UniqueId);
await contentRepository.ResetScheduledAsync(content.UniqueId, default);
}
catch (Exception ex)
{
@ -104,7 +104,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
.WriteProperty("contentId", logContentId));
}
});
});
}, default);
}
public Task ReceiveReminder(string reminderName, TickStatus status)

6
backend/src/Squidex.Domain.Apps.Entities/Contents/ContentsSearchSource.cs

@ -7,6 +7,7 @@
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Squidex.Domain.Apps.Core;
using Squidex.Domain.Apps.Core.Contents;
@ -45,7 +46,8 @@ namespace Squidex.Domain.Apps.Entities.Contents
this.urlGenerator = urlGenerator;
}
public async Task<SearchResults> SearchAsync(string query, Context context)
public async Task<SearchResults> SearchAsync(string query, Context context,
CancellationToken ct)
{
var result = new SearchResults();
@ -67,7 +69,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
var appId = context.App.NamedId();
var contents = await contentQuery.QueryAsync(context, Q.Empty.WithIds(ids));
var contents = await contentQuery.QueryAsync(context, Q.Empty.WithIds(ids), ct);
foreach (var content in contents)
{

2
backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/Guards/ValidationExtensions.cs

@ -94,7 +94,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject.Guards
{
var contentRepository = context.Resolve<IContentRepository>();
var hasReferrer = await contentRepository.HasReferrersAsync(context.App.Id, context.ContentId, SearchScope.All);
var hasReferrer = await contentRepository.HasReferrersAsync(context.App.Id, context.ContentId, SearchScope.All, default);
if (hasReferrer)
{

9
backend/src/Squidex.Domain.Apps.Entities/Contents/IContentQueryService.cs

@ -5,6 +5,7 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Threading;
using System.Threading.Tasks;
using Squidex.Domain.Apps.Entities.Schemas;
using Squidex.Infrastructure;
@ -13,14 +14,14 @@ namespace Squidex.Domain.Apps.Entities.Contents
{
public interface IContentQueryService
{
Task<IResultList<IEnrichedContentEntity>> QueryAsync(Context context, Q q);
Task<IResultList<IEnrichedContentEntity>> QueryAsync(Context context, Q q, CancellationToken ct = default);
Task<IResultList<IEnrichedContentEntity>> QueryAsync(Context context, string schemaIdOrName, Q query);
Task<IResultList<IEnrichedContentEntity>> QueryAsync(Context context, string schemaIdOrName, Q query, CancellationToken ct = default);
Task<IEnrichedContentEntity?> FindAsync(Context context, string schemaIdOrName, DomainId id, long version = EtagVersion.Any);
Task<IEnrichedContentEntity?> FindAsync(Context context, string schemaIdOrName, DomainId id, long version = EtagVersion.Any, CancellationToken ct = default);
Task<ISchemaEntity> GetSchemaOrThrowAsync(Context context, string schemaIdOrName);
Task<ISchemaEntity?> GetSchemaAsync(Context context, string schemaIdOrName);
Task<ISchemaEntity?> GetSchemaAsync(Context context, string schemaIdOrNama);
}
}

20
backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentEnricher.cs

@ -8,6 +8,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Squidex.Domain.Apps.Entities.Schemas;
using Squidex.Infrastructure;
@ -36,24 +37,27 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
this.contentQuery = contentQuery;
}
public async Task<IEnrichedContentEntity> EnrichAsync(IContentEntity content, bool cloneData, Context context)
public async Task<IEnrichedContentEntity> EnrichAsync(IContentEntity content, bool cloneData, Context context,
CancellationToken ct)
{
Guard.NotNull(content, nameof(content));
var enriched = await EnrichInternalAsync(Enumerable.Repeat(content, 1), cloneData, context);
var enriched = await EnrichInternalAsync(Enumerable.Repeat(content, 1), cloneData, context, ct);
return enriched[0];
}
public Task<IReadOnlyList<IEnrichedContentEntity>> EnrichAsync(IEnumerable<IContentEntity> contents, Context context)
public Task<IReadOnlyList<IEnrichedContentEntity>> EnrichAsync(IEnumerable<IContentEntity> contents, Context context,
CancellationToken ct)
{
Guard.NotNull(contents, nameof(contents));
Guard.NotNull(context, nameof(context));
return EnrichInternalAsync(contents, false, context);
return EnrichInternalAsync(contents, false, context, ct);
}
private async Task<IReadOnlyList<IEnrichedContentEntity>> EnrichInternalAsync(IEnumerable<IContentEntity> contents, bool cloneData, Context context)
private async Task<IReadOnlyList<IEnrichedContentEntity>> EnrichInternalAsync(IEnumerable<IContentEntity> contents, bool cloneData, Context context,
CancellationToken ct)
{
using (Profiler.TraceMethod<ContentEnricher>())
{
@ -63,7 +67,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
{
foreach (var step in steps)
{
await step.EnrichAsync(context);
await step.EnrichAsync(context, ct);
}
}
@ -92,9 +96,11 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
foreach (var step in steps)
{
ct.ThrowIfCancellationRequested();
using (Profiler.TraceMethod(step.ToString()!))
{
await step.EnrichAsync(context, results, GetSchema);
await step.EnrichAsync(context, results, GetSchema, ct);
}
}
}

37
backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/ContentQueryService.cs

@ -8,6 +8,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Squidex.Domain.Apps.Entities.Contents.Repositories;
using Squidex.Domain.Apps.Entities.Schemas;
@ -49,7 +50,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
this.queryParser = queryParser;
}
public async Task<IEnrichedContentEntity?> FindAsync(Context context, string schemaIdOrName, DomainId id, long version = EtagVersion.Any)
public async Task<IEnrichedContentEntity?> FindAsync(Context context, string schemaIdOrName, DomainId id, long version = EtagVersion.Any,
CancellationToken ct = default)
{
Guard.NotNull(context, nameof(context));
@ -65,7 +67,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
}
else
{
content = await contentRepository.FindContentAsync(context.App, schema, id, context.Scope());
content = await contentRepository.FindContentAsync(context.App, schema, id, context.Scope(), ct);
}
if (content == null || content.SchemaId.Id != schema.Id)
@ -73,11 +75,12 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
return null;
}
return await TransformAsync(context, content);
return await TransformAsync(context, content, ct);
}
}
public async Task<IResultList<IEnrichedContentEntity>> QueryAsync(Context context, string schemaIdOrName, Q q)
public async Task<IResultList<IEnrichedContentEntity>> QueryAsync(Context context, string schemaIdOrName, Q q,
CancellationToken ct = default)
{
Guard.NotNull(context, nameof(context));
@ -97,18 +100,19 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
q = await queryParser.ParseAsync(context, q, schema);
var contents = await contentRepository.QueryAsync(context.App, schema, q, context.Scope());
var contents = await contentRepository.QueryAsync(context.App, schema, q, context.Scope(), ct);
if (q.Ids != null && q.Ids.Count > 0)
{
contents = contents.SortSet(x => x.Id, q.Ids);
}
return await TransformAsync(context, contents);
return await TransformAsync(context, contents, ct);
}
}
public async Task<IResultList<IEnrichedContentEntity>> QueryAsync(Context context, Q q)
public async Task<IResultList<IEnrichedContentEntity>> QueryAsync(Context context, Q q,
CancellationToken ct = default)
{
Guard.NotNull(context, nameof(context));
@ -128,36 +132,39 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
q = await queryParser.ParseAsync(context, q);
var contents = await contentRepository.QueryAsync(context.App, schemas, q, context.Scope());
var contents = await contentRepository.QueryAsync(context.App, schemas, q, context.Scope(), ct);
if (q.Ids != null && q.Ids.Count > 0)
{
contents = contents.SortSet(x => x.Id, q.Ids);
}
return await TransformAsync(context, contents);
return await TransformAsync(context, contents, ct);
}
}
private async Task<IResultList<IEnrichedContentEntity>> TransformAsync(Context context, IResultList<IContentEntity> contents)
private async Task<IResultList<IEnrichedContentEntity>> TransformAsync(Context context, IResultList<IContentEntity> contents,
CancellationToken ct)
{
var transformed = await TransformCoreAsync(context, contents);
var transformed = await TransformCoreAsync(context, contents, ct);
return ResultList.Create(contents.Total, transformed);
}
private async Task<IEnrichedContentEntity> TransformAsync(Context context, IContentEntity content)
private async Task<IEnrichedContentEntity> TransformAsync(Context context, IContentEntity content,
CancellationToken ct)
{
var transformed = await TransformCoreAsync(context, Enumerable.Repeat(content, 1));
var transformed = await TransformCoreAsync(context, Enumerable.Repeat(content, 1), ct);
return transformed[0];
}
private async Task<IReadOnlyList<IEnrichedContentEntity>> TransformCoreAsync(Context context, IEnumerable<IContentEntity> contents)
private async Task<IReadOnlyList<IEnrichedContentEntity>> TransformCoreAsync(Context context, IEnumerable<IContentEntity> contents,
CancellationToken ct)
{
using (Profiler.TraceMethod<ContentQueryService>())
{
return await contentEnricher.EnrichAsync(contents, context);
return await contentEnricher.EnrichAsync(contents, context, ct);
}
}

5
backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/IContentEnricher.cs

@ -6,14 +6,15 @@
// ==========================================================================
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace Squidex.Domain.Apps.Entities.Contents.Queries
{
public interface IContentEnricher
{
Task<IEnrichedContentEntity> EnrichAsync(IContentEntity content, bool cloneData, Context context);
Task<IEnrichedContentEntity> EnrichAsync(IContentEntity content, bool cloneData, Context context, CancellationToken ct = default);
Task<IReadOnlyList<IEnrichedContentEntity>> EnrichAsync(IEnumerable<IContentEntity> contents, Context context);
Task<IReadOnlyList<IEnrichedContentEntity>> EnrichAsync(IEnumerable<IContentEntity> contents, Context context, CancellationToken ct = default);
}
}

5
backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/IContentEnricherStep.cs

@ -6,6 +6,7 @@
// ==========================================================================
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Squidex.Domain.Apps.Entities.Schemas;
using Squidex.Infrastructure;
@ -16,9 +17,9 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
public interface IContentEnricherStep
{
Task EnrichAsync(Context context, IEnumerable<ContentEntity> contents, ProvideSchema schemas);
Task EnrichAsync(Context context, IEnumerable<ContentEntity> contents, ProvideSchema schemas, CancellationToken ct);
Task EnrichAsync(Context context)
Task EnrichAsync(Context context, CancellationToken ct)
{
return Task.CompletedTask;
}

25
backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/Steps/ConvertData.cs

@ -7,6 +7,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Squidex.Domain.Apps.Core;
using Squidex.Domain.Apps.Core.ConvertContent;
@ -49,14 +50,17 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries.Steps
excludedHiddenValue = FieldConverters.ForValues(ValueConverters.ExcludeHidden);
}
public async Task EnrichAsync(Context context, IEnumerable<ContentEntity> contents, ProvideSchema schemas)
public async Task EnrichAsync(Context context, IEnumerable<ContentEntity> contents, ProvideSchema schemas,
CancellationToken ct)
{
var referenceCleaner = await CleanReferencesAsync(context, contents, schemas);
var referenceCleaner = await CleanReferencesAsync(context, contents, schemas, ct);
var converters = GenerateConverters(context, referenceCleaner).ToArray();
foreach (var group in contents.GroupBy(x => x.SchemaId.Id))
{
ct.ThrowIfCancellationRequested();
var schema = await schemas(group.Key);
foreach (var content in group)
@ -66,7 +70,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries.Steps
}
}
private async Task<ValueConverter?> CleanReferencesAsync(Context context, IEnumerable<ContentEntity> contents, ProvideSchema schemas)
private async Task<ValueConverter?> CleanReferencesAsync(Context context, IEnumerable<ContentEntity> contents, ProvideSchema schemas,
CancellationToken ct)
{
if (!context.ShouldSkipCleanup())
{
@ -85,8 +90,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries.Steps
if (ids.Count > 0)
{
var (assets, refContents) = await AsyncHelper.WhenAll(
QueryAssetIdsAsync(context, ids),
QueryContentIdsAsync(context, ids));
QueryAssetIdsAsync(context, ids, ct),
QueryContentIdsAsync(context, ids, ct));
var foundIds = assets.Union(refContents).ToHashSet();
@ -97,16 +102,18 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries.Steps
return null;
}
private async Task<IEnumerable<DomainId>> QueryContentIdsAsync(Context context, HashSet<DomainId> ids)
private async Task<IEnumerable<DomainId>> QueryContentIdsAsync(Context context, HashSet<DomainId> ids,
CancellationToken ct)
{
var result = await contentRepository.QueryIdsAsync(context.App.Id, ids, context.Scope());
var result = await contentRepository.QueryIdsAsync(context.App.Id, ids, context.Scope(), ct);
return result.Select(x => x.Id);
}
private async Task<IEnumerable<DomainId>> QueryAssetIdsAsync(Context context, HashSet<DomainId> ids)
private async Task<IEnumerable<DomainId>> QueryAssetIdsAsync(Context context, HashSet<DomainId> ids,
CancellationToken ct)
{
var result = await assetRepository.QueryIdsAsync(context.App.Id, ids);
var result = await assetRepository.QueryIdsAsync(context.App.Id, ids, ct);
return result;
}

9
backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/Steps/EnrichForCaching.cs

@ -7,6 +7,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Caching;
@ -24,19 +25,23 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries.Steps
this.requestCache = requestCache;
}
public Task EnrichAsync(Context context)
public Task EnrichAsync(Context context,
CancellationToken ct)
{
context.AddCacheHeaders(requestCache);
return Task.CompletedTask;
}
public async Task EnrichAsync(Context context, IEnumerable<ContentEntity> contents, ProvideSchema schemas)
public async Task EnrichAsync(Context context, IEnumerable<ContentEntity> contents, ProvideSchema schemas,
CancellationToken ct)
{
var app = context.App;
foreach (var group in contents.GroupBy(x => x.SchemaId.Id))
{
ct.ThrowIfCancellationRequested();
var schema = await schemas(group.Key);
foreach (var content in group)

6
backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/Steps/EnrichWithSchema.cs

@ -7,6 +7,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Squidex.Domain.Apps.Core.Schemas;
@ -14,10 +15,13 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries.Steps
{
public sealed class EnrichWithSchema : IContentEnricherStep
{
public async Task EnrichAsync(Context context, IEnumerable<ContentEntity> contents, ProvideSchema schemas)
public async Task EnrichAsync(Context context, IEnumerable<ContentEntity> contents, ProvideSchema schemas,
CancellationToken ct)
{
foreach (var group in contents.GroupBy(x => x.SchemaId.Id))
{
ct.ThrowIfCancellationRequested();
var schema = await schemas(group.Key);
var schemaName = schema.SchemaDef.Name;

6
backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/Steps/EnrichWithWorkflows.cs

@ -7,6 +7,7 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Infrastructure;
@ -26,12 +27,15 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries.Steps
this.contentWorkflow = contentWorkflow;
}
public async Task EnrichAsync(Context context, IEnumerable<ContentEntity> contents, ProvideSchema schemas)
public async Task EnrichAsync(Context context, IEnumerable<ContentEntity> contents, ProvideSchema schemas,
CancellationToken ct)
{
var cache = new Dictionary<(DomainId, Status), StatusInfo>();
foreach (var content in contents)
{
ct.ThrowIfCancellationRequested();
await EnrichColorAsync(content, content, cache);
if (ShouldEnrichWithStatuses(context))

11
backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/Steps/ResolveAssets.cs

@ -7,6 +7,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Squidex.Domain.Apps.Core;
using Squidex.Domain.Apps.Core.Assets;
@ -40,7 +41,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries.Steps
this.requestCache = requestCache;
}
public async Task EnrichAsync(Context context, IEnumerable<ContentEntity> contents, ProvideSchema schemas)
public async Task EnrichAsync(Context context, IEnumerable<ContentEntity> contents, ProvideSchema schemas,
CancellationToken ct)
{
if (ShouldEnrich(context))
{
@ -53,7 +55,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries.Steps
AddAssetIds(ids, schema, group);
}
var assets = await GetAssetsAsync(context, ids);
var assets = await GetAssetsAsync(context, ids, ct);
foreach (var group in contents.GroupBy(x => x.SchemaId.Id))
{
@ -111,7 +113,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries.Steps
}
}
private async Task<ILookup<DomainId, IEnrichedAssetEntity>> GetAssetsAsync(Context context, HashSet<DomainId> ids)
private async Task<ILookup<DomainId, IEnrichedAssetEntity>> GetAssetsAsync(Context context, HashSet<DomainId> ids,
CancellationToken ct)
{
if (ids.Count == 0)
{
@ -122,7 +125,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries.Steps
.WithoutAssetEnrichment(true)
.WithoutTotal());
var assets = await assetQuery.QueryAsync(queryContext, null, Q.Empty.WithIds(ids));
var assets = await assetQuery.QueryAsync(queryContext, null, Q.Empty.WithIds(ids), ct);
return assets.ToLookup(x => x.Id);
}

16
backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/Steps/ResolveReferences.cs

@ -1,4 +1,4 @@
// ==========================================================================
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
@ -8,6 +8,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Domain.Apps.Core.ExtractReferenceIds;
@ -41,7 +42,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries.Steps
this.requestCache = requestCache;
}
public async Task EnrichAsync(Context context, IEnumerable<ContentEntity> contents, ProvideSchema schemas)
public async Task EnrichAsync(Context context, IEnumerable<ContentEntity> contents, ProvideSchema schemas,
CancellationToken ct)
{
if (ShouldEnrich(context))
{
@ -54,7 +56,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries.Steps
AddReferenceIds(ids, schema, group);
}
var references = await GetReferencesAsync(context, ids);
var references = await GetReferencesAsync(context, ids, ct);
foreach (var group in contents.GroupBy(x => x.SchemaId.Id))
{
@ -65,7 +67,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries.Steps
}
}
private async Task ResolveReferencesAsync(Context context, ISchemaEntity schema, IEnumerable<ContentEntity> contents, ILookup<DomainId, IEnrichedContentEntity> references, ProvideSchema schemas)
private async Task ResolveReferencesAsync(Context context, ISchemaEntity schema, IEnumerable<ContentEntity> contents, ILookup<DomainId, IEnrichedContentEntity> references,
ProvideSchema schemas)
{
var formatted = new Dictionary<IContentEntity, JsonObject>();
@ -146,7 +149,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries.Steps
}
}
private async Task<ILookup<DomainId, IEnrichedContentEntity>> GetReferencesAsync(Context context, HashSet<DomainId> ids)
private async Task<ILookup<DomainId, IEnrichedContentEntity>> GetReferencesAsync(Context context, HashSet<DomainId> ids,
CancellationToken ct)
{
if (ids.Count == 0)
{
@ -157,7 +161,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries.Steps
.WithoutContentEnrichment(true)
.WithoutTotal());
var references = await ContentQuery.QueryAsync(queryContext, Q.Empty.WithIds(ids));
var references = await ContentQuery.QueryAsync(queryContext, Q.Empty.WithIds(ids), ct);
return references.ToLookup(x => x.Id);
}

11
backend/src/Squidex.Domain.Apps.Entities/Contents/Queries/Steps/ScriptContent.cs

@ -7,6 +7,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Squidex.Domain.Apps.Core.Scripting;
using Squidex.Infrastructure;
@ -24,7 +25,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries.Steps
this.scriptEngine = scriptEngine;
}
public async Task EnrichAsync(Context context, IEnumerable<ContentEntity> contents, ProvideSchema schemas)
public async Task EnrichAsync(Context context, IEnumerable<ContentEntity> contents, ProvideSchema schemas,
CancellationToken ct)
{
if (ShouldEnrich(context))
{
@ -36,13 +38,14 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries.Steps
if (!string.IsNullOrWhiteSpace(script))
{
await Task.WhenAll(group.Select(x => TransformAsync(context, script, x)));
await Task.WhenAll(group.Select(x => TransformAsync(context, script, x, ct)));
}
}
}
}
private async Task TransformAsync(Context context, string script, ContentEntity content)
private async Task TransformAsync(Context context, string script, ContentEntity content,
CancellationToken ct)
{
var vars = new ScriptVars
{
@ -58,7 +61,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries.Steps
AsContext = true
};
content.Data = await scriptEngine.TransformAsync(vars, script, options);
content.Data = await scriptEngine.TransformAsync(vars, script, options, ct);
}
private static bool ShouldEnrich(Context context)

18
backend/src/Squidex.Domain.Apps.Entities/Contents/Repositories/IContentRepository.cs

@ -20,22 +20,22 @@ namespace Squidex.Domain.Apps.Entities.Contents.Repositories
{
public interface IContentRepository
{
IAsyncEnumerable<IContentEntity> StreamAll(DomainId appId, HashSet<DomainId>? schemaIds, CancellationToken ct);
IAsyncEnumerable<IContentEntity> StreamAll(DomainId appId, HashSet<DomainId>? schemaIds, CancellationToken ct = default);
Task<IResultList<IContentEntity>> QueryAsync(IAppEntity app, List<ISchemaEntity> schemas, Q q, SearchScope scope);
Task<IResultList<IContentEntity>> QueryAsync(IAppEntity app, List<ISchemaEntity> schemas, Q q, SearchScope scope, CancellationToken ct = default);
Task<IResultList<IContentEntity>> QueryAsync(IAppEntity app, ISchemaEntity schema, Q q, SearchScope scope);
Task<IResultList<IContentEntity>> QueryAsync(IAppEntity app, ISchemaEntity schema, Q q, SearchScope scope, CancellationToken ct = default);
Task<IReadOnlyList<(DomainId SchemaId, DomainId Id, Status Status)>> QueryIdsAsync(DomainId appId, DomainId schemaId, FilterNode<ClrValue> filterNode);
Task<IReadOnlyList<(DomainId SchemaId, DomainId Id, Status Status)>> QueryIdsAsync(DomainId appId, DomainId schemaId, FilterNode<ClrValue> filterNode, CancellationToken ct = default);
Task<IReadOnlyList<(DomainId SchemaId, DomainId Id, Status Status)>> QueryIdsAsync(DomainId appId, HashSet<DomainId> ids, SearchScope scope);
Task<IReadOnlyList<(DomainId SchemaId, DomainId Id, Status Status)>> QueryIdsAsync(DomainId appId, HashSet<DomainId> ids, SearchScope scope, CancellationToken ct = default);
Task<IContentEntity?> FindContentAsync(IAppEntity app, ISchemaEntity schema, DomainId id, SearchScope scope);
Task<IContentEntity?> FindContentAsync(IAppEntity app, ISchemaEntity schema, DomainId id, SearchScope scope, CancellationToken ct = default);
Task<bool> HasReferrersAsync(DomainId appId, DomainId contentId, SearchScope scope);
Task<bool> HasReferrersAsync(DomainId appId, DomainId contentId, SearchScope scope, CancellationToken ct = default);
Task ResetScheduledAsync(DomainId documentId);
Task ResetScheduledAsync(DomainId documentId, CancellationToken ct = default);
Task QueryScheduledWithoutDataAsync(Instant now, Func<IContentEntity, Task> callback);
Task QueryScheduledWithoutDataAsync(Instant now, Func<IContentEntity, Task> callback, CancellationToken ct = default);
}
}

8
backend/src/Squidex.Domain.Apps.Entities/Contents/Validation/DependencyValidatorsFactory.cs

@ -42,7 +42,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Validation
{
var checkAssets = new CheckAssets(async ids =>
{
return await assetRepository.QueryAsync(context.AppId.Id, null, Q.Empty.WithIds(ids));
return await assetRepository.QueryAsync(context.AppId.Id, null, Q.Empty.WithIds(ids), default);
});
yield return new AssetsValidator(isRequired, assetsField.Properties, checkAssets);
@ -52,7 +52,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Validation
{
var checkReferences = new CheckContentsByIds(async ids =>
{
return await contentRepository.QueryIdsAsync(context.AppId.Id, ids, SearchScope.All);
return await contentRepository.QueryIdsAsync(context.AppId.Id, ids, SearchScope.All, default);
});
yield return new ReferencesValidator(isRequired, referencesField.Properties, checkReferences);
@ -62,7 +62,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Validation
{
var checkUniqueness = new CheckUniqueness(async filter =>
{
return await contentRepository.QueryIdsAsync(context.AppId.Id, context.SchemaId.Id, filter);
return await contentRepository.QueryIdsAsync(context.AppId.Id, context.SchemaId.Id, filter, default);
});
yield return new UniqueValidator(checkUniqueness);
@ -72,7 +72,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Validation
{
var checkUniqueness = new CheckUniqueness(async filter =>
{
return await contentRepository.QueryIdsAsync(context.AppId.Id, context.SchemaId.Id, filter);
return await contentRepository.QueryIdsAsync(context.AppId.Id, context.SchemaId.Id, filter, default);
});
yield return new UniqueValidator(checkUniqueness);

6
backend/src/Squidex.Domain.Apps.Entities/Rules/Repositories/IRuleEventRepository.cs

@ -48,10 +48,10 @@ namespace Squidex.Domain.Apps.Entities.Rules.Repositories
Task QueryPendingAsync(Instant now, Func<IRuleEventEntity, Task> callback, CancellationToken ct = default);
Task<IReadOnlyList<RuleStatistics>> QueryStatisticsByAppAsync(DomainId appId);
Task<IReadOnlyList<RuleStatistics>> QueryStatisticsByAppAsync(DomainId appId, CancellationToken ct = default);
Task<IResultList<IRuleEventEntity>> QueryByAppAsync(DomainId appId, DomainId? ruleId = null, int skip = 0, int take = 20);
Task<IResultList<IRuleEventEntity>> QueryByAppAsync(DomainId appId, DomainId? ruleId = null, int skip = 0, int take = 20, CancellationToken ct = default);
Task<IRuleEventEntity> FindAsync(DomainId id);
Task<IRuleEventEntity> FindAsync(DomainId id, CancellationToken ct = default);
}
}

4
backend/src/Squidex.Domain.Apps.Entities/Schemas/SchemasSearchSource.cs

@ -5,6 +5,7 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Threading;
using System.Threading.Tasks;
using Squidex.Domain.Apps.Core;
using Squidex.Domain.Apps.Core.Schemas;
@ -31,7 +32,8 @@ namespace Squidex.Domain.Apps.Entities.Schemas
this.urlGenerator = urlGenerator;
}
public async Task<SearchResults> SearchAsync(string query, Context context)
public async Task<SearchResults> SearchAsync(string query, Context context,
CancellationToken ct)
{
var result = new SearchResults();

3
backend/src/Squidex.Domain.Apps.Entities/Search/ISearchManager.cs

@ -5,12 +5,13 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Threading;
using System.Threading.Tasks;
namespace Squidex.Domain.Apps.Entities.Search
{
public interface ISearchManager
{
Task<SearchResults> SearchAsync(string? query, Context context);
Task<SearchResults> SearchAsync(string? query, Context context, CancellationToken ct = default);
}
}

3
backend/src/Squidex.Domain.Apps.Entities/Search/ISearchSource.cs

@ -5,12 +5,13 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Threading;
using System.Threading.Tasks;
namespace Squidex.Domain.Apps.Entities.Search
{
public interface ISearchSource
{
Task<SearchResults> SearchAsync(string query, Context context);
Task<SearchResults> SearchAsync(string query, Context context, CancellationToken ct);
}
}

11
backend/src/Squidex.Domain.Apps.Entities/Search/SearchManager.cs

@ -8,6 +8,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Squidex.Infrastructure;
using Squidex.Log;
@ -30,25 +31,27 @@ namespace Squidex.Domain.Apps.Entities.Search
this.log = log;
}
public async Task<SearchResults> SearchAsync(string? query, Context context)
public async Task<SearchResults> SearchAsync(string? query, Context context,
CancellationToken ct = default)
{
if (string.IsNullOrWhiteSpace(query) || query.Length < 3)
{
return new SearchResults();
}
var tasks = searchSources.Select(x => SearchAsync(x, query, context));
var tasks = searchSources.Select(x => SearchAsync(x, query, context, ct));
var results = await Task.WhenAll(tasks);
return new SearchResults(results.SelectMany(x => x));
}
private async Task<SearchResults> SearchAsync(ISearchSource source, string query, Context context)
private async Task<SearchResults> SearchAsync(ISearchSource source, string query, Context context,
CancellationToken ct)
{
try
{
return await source.SearchAsync(query, context);
return await source.SearchAsync(query, context, ct);
}
catch (Exception ex)
{

5
backend/src/Squidex.Domain.Users.MongoDb/MongoRoleStore.cs

@ -41,7 +41,8 @@ namespace Squidex.Domain.Users.MongoDb
return "Identity_Roles";
}
protected override Task SetupCollectionAsync(IMongoCollection<IdentityRole> collection, CancellationToken ct = default)
protected override Task SetupCollectionAsync(IMongoCollection<IdentityRole> collection,
CancellationToken ct)
{
return collection.Indexes.CreateOneAsync(
new CreateIndexModel<IdentityRole>(
@ -123,4 +124,4 @@ namespace Squidex.Domain.Users.MongoDb
return Task.CompletedTask;
}
}
}
}

5
backend/src/Squidex.Domain.Users.MongoDb/MongoUserStore.cs

@ -138,7 +138,8 @@ namespace Squidex.Domain.Users.MongoDb
return "Identity_Users";
}
protected override Task SetupCollectionAsync(IMongoCollection<MongoUser> collection, CancellationToken ct = default)
protected override Task SetupCollectionAsync(IMongoCollection<MongoUser> collection,
CancellationToken ct)
{
return collection.Indexes.CreateManyAsync(new[]
{
@ -601,4 +602,4 @@ namespace Squidex.Domain.Users.MongoDb
return Task.FromResult(false);
}
}
}
}

3
backend/src/Squidex.Infrastructure.MongoDb/EventSourcing/MongoEventStore.cs

@ -53,7 +53,8 @@ namespace Squidex.Infrastructure.EventSourcing
return new MongoCollectionSettings { WriteConcern = WriteConcern.WMajority };
}
protected override async Task SetupCollectionAsync(IMongoCollection<MongoEventCommit> collection, CancellationToken ct = default)
protected override async Task SetupCollectionAsync(IMongoCollection<MongoEventCommit> collection,
CancellationToken ct)
{
await collection.Indexes.CreateManyAsync(new[]
{

3
backend/src/Squidex.Infrastructure.MongoDb/Log/MongoRequestLogRepository.cs

@ -34,7 +34,8 @@ namespace Squidex.Infrastructure.Log
return "RequestLog";
}
protected override Task SetupCollectionAsync(IMongoCollection<MongoRequest> collection, CancellationToken ct = default)
protected override Task SetupCollectionAsync(IMongoCollection<MongoRequest> collection,
CancellationToken ct = default)
{
return collection.Indexes.CreateManyAsync(new[]
{

5
backend/src/Squidex.Infrastructure.MongoDb/MongoDb/MongoRepositoryBase.cs

@ -84,7 +84,8 @@ namespace Squidex.Infrastructure.MongoDb
return string.Format(CultureInfo.InvariantCulture, CollectionFormat, typeof(TEntity).Name);
}
protected virtual Task SetupCollectionAsync(IMongoCollection<TEntity> collection, CancellationToken ct = default)
protected virtual Task SetupCollectionAsync(IMongoCollection<TEntity> collection,
CancellationToken ct)
{
return Task.CompletedTask;
}
@ -131,4 +132,4 @@ namespace Squidex.Infrastructure.MongoDb
CollectionSettings() ?? new MongoCollectionSettings());
}
}
}
}

5
backend/src/Squidex.Infrastructure.MongoDb/UsageTracking/MongoUsageRepository.cs

@ -29,7 +29,8 @@ namespace Squidex.Infrastructure.UsageTracking
return "UsagesV2";
}
protected override Task SetupCollectionAsync(IMongoCollection<MongoUsage> collection, CancellationToken ct = default)
protected override Task SetupCollectionAsync(IMongoCollection<MongoUsage> collection,
CancellationToken ct = default)
{
return collection.Indexes.CreateOneAsync(
new CreateIndexModel<MongoUsage>(
@ -37,7 +38,7 @@ namespace Squidex.Infrastructure.UsageTracking
.Ascending(x => x.Key)
.Ascending(x => x.Category)
.Ascending(x => x.Date)),
cancellationToken: ct);
cancellationToken: ct = default);
}
public async Task TrackUsagesAsync(UsageUpdate update)

10
backend/src/Squidex/Areas/Api/Controllers/Assets/AssetContentController.cs

@ -76,11 +76,11 @@ namespace Squidex.Areas.Api.Controllers.Assets
{
var requestContext = Context.Clone(b => b.WithoutAssetEnrichment());
var asset = await assetQuery.FindAsync(requestContext, DomainId.Create(idOrSlug));
var asset = await assetQuery.FindAsync(requestContext, DomainId.Create(idOrSlug), ct: HttpContext.RequestAborted);
if (asset == null)
{
asset = await assetQuery.FindBySlugAsync(requestContext, idOrSlug);
asset = await assetQuery.FindBySlugAsync(requestContext, idOrSlug, HttpContext.RequestAborted);
}
return await DeliverAssetAsync(requestContext, asset, request);
@ -106,7 +106,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
{
var requestContext = Context.Clone(b => b.WithoutAssetEnrichment());
var asset = await assetQuery.FindGlobalAsync(requestContext, id);
var asset = await assetQuery.FindGlobalAsync(requestContext, id, HttpContext.RequestAborted);
return await DeliverAssetAsync(requestContext, asset, request);
}
@ -131,7 +131,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
{
if (context.App != null)
{
asset = await assetQuery.FindAsync(context, asset.Id, request.Version);
asset = await assetQuery.FindAsync(context, asset.Id, request.Version, HttpContext.RequestAborted);
}
else
{
@ -265,4 +265,4 @@ namespace Squidex.Areas.Api.Controllers.Assets
FileOptions.SequentialScan);
}
}
}
}

4
backend/src/Squidex/Areas/Api/Controllers/Assets/AssetFoldersController.cs

@ -54,8 +54,8 @@ namespace Squidex.Areas.Api.Controllers.Assets
public async Task<IActionResult> GetAssetFolders(string app, [FromQuery] DomainId parentId)
{
var (folders, path) = await AsyncHelper.WhenAll(
assetQuery.QueryAssetFoldersAsync(Context, parentId),
assetQuery.FindAssetFolderAsync(Context.App.Id, parentId));
assetQuery.QueryAssetFoldersAsync(Context, parentId, HttpContext.RequestAborted),
assetQuery.FindAssetFolderAsync(Context.App.Id, parentId, HttpContext.RequestAborted));
var response = Deferred.Response(() =>
{

6
backend/src/Squidex/Areas/Api/Controllers/Assets/AssetsController.cs

@ -98,7 +98,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
[ApiCosts(1)]
public async Task<IActionResult> GetAssets(string app, [FromQuery] DomainId? parentId, [FromQuery] string? ids = null, [FromQuery] string? q = null)
{
var assets = await assetQuery.QueryAsync(Context, parentId, CreateQuery(ids, q));
var assets = await assetQuery.QueryAsync(Context, parentId, CreateQuery(ids, q), HttpContext.RequestAborted);
var response = Deferred.Response(() =>
{
@ -127,7 +127,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
[ApiCosts(1)]
public async Task<IActionResult> GetAssetsPost(string app, [FromBody] QueryDto query)
{
var assets = await assetQuery.QueryAsync(Context, query?.ParentId, query?.ToQuery() ?? Q.Empty);
var assets = await assetQuery.QueryAsync(Context, query?.ParentId, query?.ToQuery() ?? Q.Empty, HttpContext.RequestAborted);
var response = Deferred.Response(() =>
{
@ -153,7 +153,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
[ApiCosts(1)]
public async Task<IActionResult> GetAsset(string app, DomainId id)
{
var asset = await assetQuery.FindAsync(Context, id);
var asset = await assetQuery.FindAsync(Context, id, ct: HttpContext.RequestAborted);
if (asset == null)
{

16
backend/src/Squidex/Areas/Api/Controllers/Contents/ContentsController.cs

@ -83,7 +83,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
[ApiCosts(1)]
public async Task<IActionResult> GetAllContents(string app, [FromQuery] string ids)
{
var contents = await contentQuery.QueryAsync(Context, Q.Empty.WithIds(ids));
var contents = await contentQuery.QueryAsync(Context, Q.Empty.WithIds(ids), HttpContext.RequestAborted);
var response = Deferred.AsyncResponse(() =>
{
@ -112,7 +112,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
[ApiCosts(1)]
public async Task<IActionResult> GetAllContentsPost(string app, [FromBody] ContentsIdsQueryDto query)
{
var contents = await contentQuery.QueryAsync(Context, Q.Empty.WithIds(query.Ids));
var contents = await contentQuery.QueryAsync(Context, Q.Empty.WithIds(query.Ids), HttpContext.RequestAborted);
var response = Deferred.AsyncResponse(() =>
{
@ -143,7 +143,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
[ApiCosts(1)]
public async Task<IActionResult> GetContents(string app, string schema, [FromQuery] string? ids = null, [FromQuery] string? q = null)
{
var contents = await contentQuery.QueryAsync(Context, schema, CreateQuery(ids, q));
var contents = await contentQuery.QueryAsync(Context, schema, CreateQuery(ids, q), HttpContext.RequestAborted);
var response = Deferred.AsyncResponse(() =>
{
@ -173,7 +173,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
[ApiCosts(1)]
public async Task<IActionResult> GetContentsPost(string app, string schema, [FromBody] QueryDto query)
{
var contents = await contentQuery.QueryAsync(Context, schema, query?.ToQuery() ?? Q.Empty);
var contents = await contentQuery.QueryAsync(Context, schema, query?.ToQuery() ?? Q.Empty, HttpContext.RequestAborted);
var response = Deferred.AsyncResponse(() =>
{
@ -203,7 +203,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
[ApiCosts(1)]
public async Task<IActionResult> GetContent(string app, string schema, DomainId id)
{
var content = await contentQuery.FindAsync(Context, schema, id);
var content = await contentQuery.FindAsync(Context, schema, id, ct: HttpContext.RequestAborted);
if (content == null)
{
@ -263,7 +263,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
[ApiCosts(1)]
public async Task<IActionResult> GetReferences(string app, string schema, DomainId id, [FromQuery] string? q = null)
{
var contents = await contentQuery.QueryAsync(Context, CreateQuery(null, q).WithReferencing(id));
var contents = await contentQuery.QueryAsync(Context, CreateQuery(null, q).WithReferencing(id), HttpContext.RequestAborted);
var response = Deferred.AsyncResponse(() =>
{
@ -294,7 +294,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
[ApiCosts(1)]
public async Task<IActionResult> GetReferencing(string app, string schema, DomainId id, [FromQuery] string? q = null)
{
var contents = await contentQuery.QueryAsync(Context, CreateQuery(null, q).WithReference(id));
var contents = await contentQuery.QueryAsync(Context, CreateQuery(null, q).WithReference(id), HttpContext.RequestAborted);
var response = Deferred.AsyncResponse(() =>
{
@ -324,7 +324,7 @@ namespace Squidex.Areas.Api.Controllers.Contents
[ApiCosts(1)]
public async Task<IActionResult> GetContentVersion(string app, string schema, DomainId id, int version)
{
var content = await contentQuery.FindAsync(Context, schema, id, version);
var content = await contentQuery.FindAsync(Context, schema, id, version, HttpContext.RequestAborted);
if (content == null)
{

2
backend/src/Squidex/Areas/Api/Controllers/Search/SearchController.cs

@ -47,7 +47,7 @@ namespace Squidex.Areas.Api.Controllers.Search
[ApiCosts(0)]
public async Task<IActionResult> GetSearchResults(string app, [FromQuery] string? query = null)
{
var result = await searchManager.SearchAsync(query, Context);
var result = await searchManager.SearchAsync(query, Context, HttpContext.RequestAborted);
var response = result.Select(SearchResultDto.FromSearchResult).ToArray();

50
backend/tests/Squidex.Domain.Apps.Entities.Tests/Apps/AppSettingsSearchSourceTests.cs

@ -35,7 +35,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
{
var ctx = ContextWithPermission();
var result = await sut.SearchAsync("xyz", ctx);
var result = await sut.SearchAsync("xyz", ctx, default);
Assert.Empty(result);
}
@ -50,7 +50,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
A.CallTo(() => urlGenerator.DashboardUI(appId))
.Returns("dashboard-url");
var result = await sut.SearchAsync("dashboard", ctx);
var result = await sut.SearchAsync("dashboard", ctx, default);
result.Should().BeEquivalentTo(
new SearchResults()
@ -62,7 +62,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
{
var ctx = ContextWithPermission();
var result = await sut.SearchAsync("assets", ctx);
var result = await sut.SearchAsync("assets", ctx, default);
Assert.Empty(result);
}
@ -77,7 +77,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
A.CallTo(() => urlGenerator.LanguagesUI(appId))
.Returns("languages-url");
var result = await sut.SearchAsync("languages", ctx);
var result = await sut.SearchAsync("languages", ctx, default);
result.Should().BeEquivalentTo(
new SearchResults()
@ -89,7 +89,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
{
var ctx = ContextWithPermission();
var result = await sut.SearchAsync("assets", ctx);
var result = await sut.SearchAsync("assets", ctx, default);
Assert.Empty(result);
}
@ -99,7 +99,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
{
var ctx = ContextWithPermission();
var result = await sut.SearchAsync("patterns", ctx);
var result = await sut.SearchAsync("patterns", ctx, default);
Assert.Empty(result);
}
@ -114,7 +114,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
A.CallTo(() => urlGenerator.SchemasUI(appId))
.Returns("schemas-url");
var result = await sut.SearchAsync("schemas", ctx);
var result = await sut.SearchAsync("schemas", ctx, default);
result.Should().BeEquivalentTo(
new SearchResults()
@ -126,7 +126,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
{
var ctx = ContextWithPermission();
var result = await sut.SearchAsync("schemas", ctx);
var result = await sut.SearchAsync("schemas", ctx, default);
Assert.Empty(result);
}
@ -141,7 +141,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
A.CallTo(() => urlGenerator.AssetsUI(appId, A<string?>._))
.Returns("assets-url");
var result = await sut.SearchAsync("assets", ctx);
var result = await sut.SearchAsync("assets", ctx, default);
result.Should().BeEquivalentTo(
new SearchResults()
@ -153,7 +153,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
{
var ctx = ContextWithPermission();
var result = await sut.SearchAsync("assets", ctx);
var result = await sut.SearchAsync("assets", ctx, default);
Assert.Empty(result);
}
@ -168,7 +168,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
A.CallTo(() => urlGenerator.BackupsUI(appId))
.Returns("backups-url");
var result = await sut.SearchAsync("backups", ctx);
var result = await sut.SearchAsync("backups", ctx, default);
result.Should().BeEquivalentTo(
new SearchResults()
@ -180,7 +180,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
{
var ctx = ContextWithPermission();
var result = await sut.SearchAsync("backups", ctx);
var result = await sut.SearchAsync("backups", ctx, default);
Assert.Empty(result);
}
@ -195,7 +195,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
A.CallTo(() => urlGenerator.ClientsUI(appId))
.Returns("clients-url");
var result = await sut.SearchAsync("clients", ctx);
var result = await sut.SearchAsync("clients", ctx, default);
result.Should().BeEquivalentTo(
new SearchResults()
@ -207,7 +207,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
{
var ctx = ContextWithPermission();
var result = await sut.SearchAsync("clients", ctx);
var result = await sut.SearchAsync("clients", ctx, default);
Assert.Empty(result);
}
@ -222,7 +222,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
A.CallTo(() => urlGenerator.ContributorsUI(appId))
.Returns("contributors-url");
var result = await sut.SearchAsync("contributors", ctx);
var result = await sut.SearchAsync("contributors", ctx, default);
result.Should().BeEquivalentTo(
new SearchResults()
@ -234,7 +234,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
{
var ctx = ContextWithPermission();
var result = await sut.SearchAsync("contributors", ctx);
var result = await sut.SearchAsync("contributors", ctx, default);
Assert.Empty(result);
}
@ -249,7 +249,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
A.CallTo(() => urlGenerator.PlansUI(appId))
.Returns("subscription-url");
var result = await sut.SearchAsync("subscription", ctx);
var result = await sut.SearchAsync("subscription", ctx, default);
result.Should().BeEquivalentTo(
new SearchResults()
@ -261,7 +261,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
{
var ctx = ContextWithPermission();
var result = await sut.SearchAsync("subscription", ctx);
var result = await sut.SearchAsync("subscription", ctx, default);
Assert.Empty(result);
}
@ -276,7 +276,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
A.CallTo(() => urlGenerator.RolesUI(appId))
.Returns("roles-url");
var result = await sut.SearchAsync("roles", ctx);
var result = await sut.SearchAsync("roles", ctx, default);
result.Should().BeEquivalentTo(
new SearchResults()
@ -288,7 +288,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
{
var ctx = ContextWithPermission();
var result = await sut.SearchAsync("roles", ctx);
var result = await sut.SearchAsync("roles", ctx, default);
Assert.Empty(result);
}
@ -303,7 +303,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
A.CallTo(() => urlGenerator.RulesUI(appId))
.Returns("rules-url");
var result = await sut.SearchAsync("rules", ctx);
var result = await sut.SearchAsync("rules", ctx, default);
result.Should().BeEquivalentTo(
new SearchResults()
@ -315,7 +315,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
{
var ctx = ContextWithPermission();
var result = await sut.SearchAsync("assets", ctx);
var result = await sut.SearchAsync("assets", ctx, default);
Assert.Empty(result);
}
@ -330,7 +330,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
A.CallTo(() => urlGenerator.WorkflowsUI(appId))
.Returns("workflows-url");
var result = await sut.SearchAsync("workflows", ctx);
var result = await sut.SearchAsync("workflows", ctx, default);
result.Should().BeEquivalentTo(
new SearchResults()
@ -342,7 +342,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
{
var ctx = ContextWithPermission();
var result = await sut.SearchAsync("workflows", ctx);
var result = await sut.SearchAsync("workflows", ctx, default);
Assert.Empty(result);
}
@ -360,4 +360,4 @@ namespace Squidex.Domain.Apps.Entities.Apps
return new Context(claimsPrincipal, Mocks.App(appId));
}
}
}
}

5
backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetsFluidExtensionTests.cs

@ -5,6 +5,7 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Threading;
using System.Threading.Tasks;
using FakeItEasy;
using Microsoft.Extensions.DependencyInjection;
@ -62,10 +63,10 @@ namespace Squidex.Domain.Apps.Entities.Assets
AppId = appId
};
A.CallTo(() => assetQuery.FindAsync(A<Context>._, assetId1, EtagVersion.Any))
A.CallTo(() => assetQuery.FindAsync(A<Context>._, assetId1, EtagVersion.Any, A<CancellationToken>._))
.Returns(asset1);
A.CallTo(() => assetQuery.FindAsync(A<Context>._, assetId2, EtagVersion.Any))
A.CallTo(() => assetQuery.FindAsync(A<Context>._, assetId2, EtagVersion.Any, A<CancellationToken>._))
.Returns(asset2);
var vars = new TemplateVars

5
backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetsJintExtensionTests.cs

@ -6,6 +6,7 @@
// ==========================================================================
using System.Security.Claims;
using System.Threading;
using System.Threading.Tasks;
using FakeItEasy;
using Microsoft.Extensions.Caching.Memory;
@ -62,7 +63,7 @@ namespace Squidex.Domain.Apps.Entities.Assets
.AddInvariant(JsonValue.Array(assetId1)));
A.CallTo(() => assetQuery.QueryAsync(
A<Context>.That.Matches(x => x.App.Id == appId.Id && x.User == user), null, A<Q>.That.HasIds(assetId1)))
A<Context>.That.Matches(x => x.App.Id == appId.Id && x.User == user), null, A<Q>.That.HasIds(assetId1), A<CancellationToken>._))
.Returns(ResultList.CreateFrom(1, asset1));
var vars = new ScriptVars { Data = data, AppId = appId.Id, User = user };
@ -100,7 +101,7 @@ namespace Squidex.Domain.Apps.Entities.Assets
.AddInvariant(JsonValue.Array(assetId1, assetId2)));
A.CallTo(() => assetQuery.QueryAsync(
A<Context>.That.Matches(x => x.App.Id == appId.Id && x.User == user), null, A<Q>.That.HasIds(assetId1, assetId2)))
A<Context>.That.Matches(x => x.App.Id == appId.Id && x.User == user), null, A<Q>.That.HasIds(assetId1, assetId2), A<CancellationToken>._))
.Returns(ResultList.CreateFrom(2, asset1, asset2));
var vars = new ScriptVars { Data = data, AppId = appId.Id, User = user };

9
backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/AssetsSearchSourceTests.cs

@ -6,6 +6,7 @@
// ==========================================================================
using System.Security.Claims;
using System.Threading;
using System.Threading.Tasks;
using FakeItEasy;
using FluentAssertions;
@ -36,11 +37,11 @@ namespace Squidex.Domain.Apps.Entities.Assets
{
var ctx = ContextWithPermission();
var result = await sut.SearchAsync("logo", ctx);
var result = await sut.SearchAsync("logo", ctx, default);
Assert.Empty(result);
A.CallTo(() => assetQuery.QueryAsync(A<Context>._, A<DomainId?>._, A<Q>._))
A.CallTo(() => assetQuery.QueryAsync(A<Context>._, A<DomainId?>._, A<Q>._, A<CancellationToken>._))
.MustNotHaveHappened();
}
@ -57,10 +58,10 @@ namespace Squidex.Domain.Apps.Entities.Assets
A.CallTo(() => urlGenerator.AssetsUI(appId, "logo"))
.Returns("assets-url");
A.CallTo(() => assetQuery.QueryAsync(ctx, null, A<Q>.That.HasQuery("Filter: contains(fileName, 'logo'); Take: 5")))
A.CallTo(() => assetQuery.QueryAsync(ctx, null, A<Q>.That.HasQuery("Filter: contains(fileName, 'logo'); Take: 5"), A<CancellationToken>._))
.Returns(ResultList.CreateFrom(2, asset1, asset2));
var result = await sut.SearchAsync("logo", ctx);
var result = await sut.SearchAsync("logo", ctx, default);
result.Should().BeEquivalentTo(
new SearchResults()

4
backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/BackupAssetsTests.cs

@ -229,7 +229,7 @@ namespace Squidex.Domain.Apps.Entities.Assets
var rebuildAssets = new HashSet<DomainId>();
A.CallTo(() => rebuilder.InsertManyAsync<AssetDomainObject, AssetDomainObject.State>(A<IEnumerable<DomainId>>._, A<int>._, A<CancellationToken>._))
.Invokes((IEnumerable<DomainId> source, CancellationToken _) => rebuildAssets.AddRange(source));
.Invokes((IEnumerable<DomainId> source, int _, CancellationToken _) => rebuildAssets.AddRange(source));
await sut.RestoreAsync(context);
@ -266,7 +266,7 @@ namespace Squidex.Domain.Apps.Entities.Assets
var rebuildAssetFolders = new HashSet<DomainId>();
A.CallTo(() => rebuilder.InsertManyAsync<AssetFolderDomainObject, AssetFolderDomainObject.State>(A<IEnumerable<DomainId>>._, A<int>._, A<CancellationToken>._))
.Invokes((IEnumerable<DomainId> source, CancellationToken _) => rebuildAssetFolders.AddRange(source));
.Invokes((IEnumerable<DomainId> source, int _, CancellationToken _) => rebuildAssetFolders.AddRange(source));
await sut.RestoreAsync(context);

10
backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/DomainObject/AssetCommandMiddlewareTests.cs

@ -50,7 +50,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
A.CallTo(() => contextProvider.Context)
.Returns(requestContext);
A.CallTo(() => assetQuery.FindByHashAsync(A<Context>._, A<string>._, A<string>._, A<long>._))
A.CallTo(() => assetQuery.FindByHashAsync(A<Context>._, A<string>._, A<string>._, A<long>._, A<CancellationToken>._))
.Returns(Task.FromResult<IEnrichedAssetEntity?>(null));
sut = new AssetCommandMiddleware(grainFactory,
@ -65,7 +65,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
{
await HandleAsync(new AnnotateAsset(), 12);
A.CallTo(() => assetEnricher.EnrichAsync(A<IEnrichedAssetEntity>._, requestContext))
A.CallTo(() => assetEnricher.EnrichAsync(A<IEnrichedAssetEntity>._, requestContext, A<CancellationToken>._))
.MustNotHaveHappened();
}
@ -78,7 +78,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
await HandleAsync(new AnnotateAsset(),
result);
A.CallTo(() => assetEnricher.EnrichAsync(A<IEnrichedAssetEntity>._, requestContext))
A.CallTo(() => assetEnricher.EnrichAsync(A<IEnrichedAssetEntity>._, requestContext, A<CancellationToken>._))
.MustNotHaveHappened();
}
@ -89,7 +89,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
var enriched = new AssetEntity();
A.CallTo(() => assetEnricher.EnrichAsync(result, requestContext))
A.CallTo(() => assetEnricher.EnrichAsync(result, requestContext, A<CancellationToken>._))
.Returns(enriched);
var context =
@ -206,7 +206,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
FileSize = fileSize
};
A.CallTo(() => assetQuery.FindByHashAsync(requestContext, A<string>._, fileName, fileSize))
A.CallTo(() => assetQuery.FindByHashAsync(requestContext, A<string>._, fileName, fileSize, A<CancellationToken>._))
.Returns(duplicate);
}

9
backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/DomainObject/AssetDomainObjectTests.cs

@ -7,6 +7,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using FakeItEasy;
using Squidex.Assets;
@ -40,7 +41,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
public AssetDomainObjectTests()
{
A.CallTo(() => assetQuery.FindAssetFolderAsync(AppId, parentId))
A.CallTo(() => assetQuery.FindAssetFolderAsync(AppId, parentId, A<CancellationToken>._))
.Returns(new List<IAssetFolderEntity> { A.Fake<IAssetFolderEntity>() });
A.CallTo(() => tagService.NormalizeTagsAsync(AppId, TagGroups.Assets, A<HashSet<string>>._, A<HashSet<string>>._))
@ -330,7 +331,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
await ExecuteCreateAsync();
A.CallTo(() => contentRepository.HasReferrersAsync(AppId, Id, SearchScope.All))
A.CallTo(() => contentRepository.HasReferrersAsync(AppId, Id, SearchScope.All, A<CancellationToken>._))
.Returns(true);
var result = await PublishAsync(command);
@ -348,7 +349,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
await ExecuteCreateAsync();
A.CallTo(() => contentRepository.HasReferrersAsync(AppId, Id, SearchScope.All))
A.CallTo(() => contentRepository.HasReferrersAsync(AppId, Id, SearchScope.All, A<CancellationToken>._))
.Returns(true);
await Assert.ThrowsAsync<DomainException>(() => PublishAsync(command));
@ -361,7 +362,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
await ExecuteCreateAsync();
A.CallTo(() => contentRepository.HasReferrersAsync(AppId, Id, SearchScope.All))
A.CallTo(() => contentRepository.HasReferrersAsync(AppId, Id, SearchScope.All, A<CancellationToken>._))
.Returns(true);
await PublishAsync(command);

3
backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/DomainObject/AssetFolderDomainObjectTests.cs

@ -6,6 +6,7 @@
// ==========================================================================
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using FakeItEasy;
using Squidex.Domain.Apps.Entities.Assets.Commands;
@ -31,7 +32,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject
public AssetFolderDomainObjectTests()
{
A.CallTo(() => assetQuery.FindAssetFolderAsync(AppId, parentId))
A.CallTo(() => assetQuery.FindAssetFolderAsync(AppId, parentId, A<CancellationToken>._))
.Returns(new List<IAssetFolderEntity> { A.Fake<IAssetFolderEntity>() });
sut = new AssetFolderDomainObject(PersistenceFactory, A.Dummy<ISemanticLog>(), assetQuery);

13
backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/DomainObject/Guards/GuardAssetFolderTests.cs

@ -6,6 +6,7 @@
// ==========================================================================
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using FakeItEasy;
using Squidex.Domain.Apps.Core.TestHelpers;
@ -27,7 +28,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject.Guards
{
var command = new CreateAssetFolder { AppId = appId };
A.CallTo(() => assetQuery.FindAssetFolderAsync(appId.Id, command.ParentId))
A.CallTo(() => assetQuery.FindAssetFolderAsync(appId.Id, command.ParentId, A<CancellationToken>._))
.Returns(new List<IAssetFolderEntity>());
await ValidationAssert.ThrowsAsync(() => GuardAssetFolder.CanCreate(command, assetQuery),
@ -39,7 +40,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject.Guards
{
var command = new CreateAssetFolder { AppId = appId, FolderName = "My Folder", ParentId = DomainId.NewGuid() };
A.CallTo(() => assetQuery.FindAssetFolderAsync(appId.Id, command.ParentId))
A.CallTo(() => assetQuery.FindAssetFolderAsync(appId.Id, command.ParentId, A<CancellationToken>._))
.Returns(new List<IAssetFolderEntity>());
await ValidationAssert.ThrowsAsync(() => GuardAssetFolder.CanCreate(command, assetQuery),
@ -51,7 +52,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject.Guards
{
var command = new CreateAssetFolder { AppId = appId, FolderName = "My Folder", ParentId = DomainId.NewGuid() };
A.CallTo(() => assetQuery.FindAssetFolderAsync(appId.Id, command.ParentId))
A.CallTo(() => assetQuery.FindAssetFolderAsync(appId.Id, command.ParentId, A<CancellationToken>._))
.Returns(new List<IAssetFolderEntity> { AssetFolder() });
await GuardAssetFolder.CanCreate(command, assetQuery);
@ -72,7 +73,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject.Guards
var command = new MoveAssetFolder { AppId = appId, ParentId = DomainId.NewGuid() };
A.CallTo(() => assetQuery.FindAssetFolderAsync(appId.Id, command.ParentId))
A.CallTo(() => assetQuery.FindAssetFolderAsync(appId.Id, command.ParentId, A<CancellationToken>._))
.Returns(new List<IAssetFolderEntity>
{
AssetFolder(id),
@ -88,7 +89,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject.Guards
{
var command = new MoveAssetFolder { AppId = appId, ParentId = DomainId.NewGuid() };
A.CallTo(() => assetQuery.FindAssetFolderAsync(appId.Id, command.ParentId))
A.CallTo(() => assetQuery.FindAssetFolderAsync(appId.Id, command.ParentId, A<CancellationToken>._))
.Returns(new List<IAssetFolderEntity>());
await ValidationAssert.ThrowsAsync(() => GuardAssetFolder.CanMove(command, AssetFolder(), assetQuery),
@ -100,7 +101,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject.Guards
{
var command = new MoveAssetFolder { AppId = appId, ParentId = DomainId.NewGuid() };
A.CallTo(() => assetQuery.FindAssetFolderAsync(appId.Id, command.ParentId))
A.CallTo(() => assetQuery.FindAssetFolderAsync(appId.Id, command.ParentId, A<CancellationToken>._))
.Returns(new List<IAssetFolderEntity> { AssetFolder() });
await GuardAssetFolder.CanMove(command, AssetFolder(), assetQuery);

8
backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/DomainObject/Guards/GuardAssetTests.cs

@ -32,7 +32,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject.Guards
var command = new MoveAsset { AppId = appId, ParentId = parentId };
A.CallTo(() => assetQuery.FindAssetFolderAsync(appId.Id, parentId))
A.CallTo(() => assetQuery.FindAssetFolderAsync(appId.Id, parentId, default))
.Returns(new List<IAssetFolderEntity>());
await ValidationAssert.ThrowsAsync(() => GuardAsset.CanMove(command, Asset(), assetQuery),
@ -46,7 +46,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject.Guards
var command = new MoveAsset { AppId = appId, ParentId = parentId, OptimizeValidation = true };
A.CallTo(() => assetQuery.FindAssetFolderAsync(appId.Id, command.ParentId))
A.CallTo(() => assetQuery.FindAssetFolderAsync(appId.Id, command.ParentId, default))
.Returns(new List<IAssetFolderEntity>());
await GuardAsset.CanMove(command, Asset(), assetQuery);
@ -59,7 +59,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject.Guards
var command = new MoveAsset { AppId = appId, ParentId = parentId };
A.CallTo(() => assetQuery.FindAssetFolderAsync(appId.Id, command.ParentId))
A.CallTo(() => assetQuery.FindAssetFolderAsync(appId.Id, command.ParentId, default))
.Returns(new List<IAssetFolderEntity> { AssetFolder() });
await GuardAsset.CanMove(command, Asset(), assetQuery);
@ -90,7 +90,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.DomainObject.Guards
var command = new DeleteAsset { AppId = appId, CheckReferrers = true };
A.CallTo(() => contentRepository.HasReferrersAsync(appId.Id, asset.Id, SearchScope.All))
A.CallTo(() => contentRepository.HasReferrersAsync(appId.Id, asset.Id, SearchScope.All, default))
.Returns(true);
await Assert.ThrowsAsync<DomainException>(() => GuardAsset.CanDelete(command, asset, contentRepository));

12
backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/Queries/AssetEnricherTests.cs

@ -45,7 +45,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
{
var source = new AssetEntity { AppId = appId };
var result = await sut.EnrichAsync(source, requestContext);
var result = await sut.EnrichAsync(source, requestContext, default);
Assert.Empty(result.TagNames);
}
@ -55,7 +55,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
{
var source = new AssetEntity { AppId = appId, Id = DomainId.NewGuid(), Version = 13 };
var result = await sut.EnrichAsync(source, requestContext);
var result = await sut.EnrichAsync(source, requestContext, default);
A.CallTo(() => requestCache.AddDependency(result.UniqueId, result.Version))
.MustHaveHappened();
@ -81,7 +81,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
["id2"] = "name2"
});
var result = await sut.EnrichAsync(source, requestContext);
var result = await sut.EnrichAsync(source, requestContext, default);
Assert.Equal(new HashSet<string> { "name1", "name2" }, result.TagNames);
}
@ -99,7 +99,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
AppId = appId
};
var result = await sut.EnrichAsync(source, requestContext.Clone(b => b.WithoutAssetEnrichment()));
var result = await sut.EnrichAsync(source, requestContext.Clone(b => b.WithoutAssetEnrichment()), default);
Assert.Null(result.TagNames);
}
@ -124,7 +124,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
A.CallTo(() => assetMetadataSource2.Format(A<IAssetEntity>._))
.Returns(new[] { "metadata2", "metadata3" });
var result = await sut.EnrichAsync(source, requestContext);
var result = await sut.EnrichAsync(source, requestContext, default);
Assert.Equal("metadata1, metadata2, metadata3, 2 kB", result.MetadataText);
}
@ -160,7 +160,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
["id3"] = "name3"
});
var result = await sut.EnrichAsync(new[] { source1, source2 }, requestContext);
var result = await sut.EnrichAsync(new[] { source1, source2 }, requestContext, default);
Assert.Equal(new HashSet<string> { "name1", "name2" }, result[0].TagNames);
Assert.Equal(new HashSet<string> { "name2", "name3" }, result[1].TagNames);

45
backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/Queries/AssetQueryServiceTests.cs

@ -7,6 +7,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using FakeItEasy;
using Squidex.Domain.Apps.Entities.Assets.Repositories;
@ -45,7 +46,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
{
var asset = CreateAsset(DomainId.NewGuid());
A.CallTo(() => assetRepository.FindAssetBySlugAsync(appId.Id, "slug"))
A.CallTo(() => assetRepository.FindAssetBySlugAsync(appId.Id, "slug", A<CancellationToken>._))
.Returns(asset);
var result = await sut.FindBySlugAsync(requestContext, "slug");
@ -58,7 +59,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
{
var asset = CreateAsset(DomainId.NewGuid());
A.CallTo(() => assetRepository.FindAssetBySlugAsync(appId.Id, "slug"))
A.CallTo(() => assetRepository.FindAssetBySlugAsync(appId.Id, "slug", A<CancellationToken>._))
.Returns(Task.FromResult<IAssetEntity?>(null));
var result = await sut.FindBySlugAsync(requestContext, "slug");
@ -71,7 +72,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
{
var asset = CreateAsset(DomainId.NewGuid());
A.CallTo(() => assetRepository.FindAssetAsync(appId.Id, asset.Id))
A.CallTo(() => assetRepository.FindAssetAsync(appId.Id, asset.Id, A<CancellationToken>._))
.Returns(asset);
var result = await sut.FindAsync(requestContext, asset.Id);
@ -84,7 +85,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
{
var asset = CreateAsset(DomainId.NewGuid());
A.CallTo(() => assetRepository.FindAssetAsync(appId.Id, asset.Id))
A.CallTo(() => assetRepository.FindAssetAsync(appId.Id, asset.Id, A<CancellationToken>._))
.Returns(Task.FromResult<IAssetEntity?>(null));
var result = await sut.FindAsync(requestContext, asset.Id);
@ -123,7 +124,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
{
var asset = CreateAsset(DomainId.NewGuid());
A.CallTo(() => assetRepository.FindAssetAsync(asset.Id))
A.CallTo(() => assetRepository.FindAssetAsync(asset.Id, A<CancellationToken>._))
.Returns(asset);
var result = await sut.FindGlobalAsync(requestContext, asset.Id);
@ -136,7 +137,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
{
var asset = CreateAsset(DomainId.NewGuid());
A.CallTo(() => assetRepository.FindAssetAsync(asset.Id))
A.CallTo(() => assetRepository.FindAssetAsync(asset.Id, A<CancellationToken>._))
.Returns(Task.FromResult<IAssetEntity?>(null));
var result = await sut.FindGlobalAsync(requestContext, asset.Id);
@ -149,7 +150,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
{
var asset = CreateAsset(DomainId.NewGuid());
A.CallTo(() => assetRepository.FindAssetByHashAsync(appId.Id, "hash", "name", 123))
A.CallTo(() => assetRepository.FindAssetByHashAsync(appId.Id, "hash", "name", 123, A<CancellationToken>._))
.Returns(asset);
var result = await sut.FindByHashAsync(requestContext, "hash", "name", 123);
@ -162,7 +163,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
{
var asset = CreateAsset(DomainId.NewGuid());
A.CallTo(() => assetRepository.FindAssetByHashAsync(appId.Id, "hash", "name", 123))
A.CallTo(() => assetRepository.FindAssetByHashAsync(appId.Id, "hash", "name", 123, A<CancellationToken>._))
.Returns(Task.FromResult<IAssetEntity?>(null));
var result = await sut.FindByHashAsync(requestContext, "hash", "name", 123);
@ -180,7 +181,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
var q = Q.Empty.WithODataQuery("fileName eq 'Name'");
A.CallTo(() => assetRepository.QueryAsync(appId.Id, parentId, q))
A.CallTo(() => assetRepository.QueryAsync(appId.Id, parentId, q, A<CancellationToken>._))
.Returns(ResultList.CreateFrom(8, asset1, asset2));
var result = await sut.QueryAsync(requestContext, parentId, q);
@ -198,7 +199,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
var assetFolders = ResultList.CreateFrom<IAssetFolderEntity>(10);
A.CallTo(() => assetFolderRepository.QueryAsync(appId.Id, parentId))
A.CallTo(() => assetFolderRepository.QueryAsync(appId.Id, parentId, A<CancellationToken>._))
.Returns(assetFolders);
var result = await sut.QueryAssetFoldersAsync(requestContext, parentId);
@ -213,7 +214,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
var assetFolders = ResultList.CreateFrom<IAssetFolderEntity>(10);
A.CallTo(() => assetFolderRepository.QueryAsync(appId.Id, parentId))
A.CallTo(() => assetFolderRepository.QueryAsync(appId.Id, parentId, A<CancellationToken>._))
.Returns(assetFolders);
var result = await sut.QueryAssetFoldersAsync(appId.Id, parentId);
@ -227,7 +228,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
var folderId1 = DomainId.NewGuid();
var folder1 = CreateFolder(folderId1);
A.CallTo(() => assetFolderRepository.FindAssetFolderAsync(appId.Id, folderId1))
A.CallTo(() => assetFolderRepository.FindAssetFolderAsync(appId.Id, folderId1, A<CancellationToken>._))
.Returns(folder1);
var result = await sut.FindAssetFolderAsync(appId.Id, folderId1);
@ -246,13 +247,13 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
var folder2 = CreateFolder(folderId2, folderId1);
var folder3 = CreateFolder(folderId3, folderId2);
A.CallTo(() => assetFolderRepository.FindAssetFolderAsync(appId.Id, folderId1))
A.CallTo(() => assetFolderRepository.FindAssetFolderAsync(appId.Id, folderId1, A<CancellationToken>._))
.Returns(folder1);
A.CallTo(() => assetFolderRepository.FindAssetFolderAsync(appId.Id, folderId2))
A.CallTo(() => assetFolderRepository.FindAssetFolderAsync(appId.Id, folderId2, A<CancellationToken>._))
.Returns(folder2);
A.CallTo(() => assetFolderRepository.FindAssetFolderAsync(appId.Id, folderId3))
A.CallTo(() => assetFolderRepository.FindAssetFolderAsync(appId.Id, folderId3, A<CancellationToken>._))
.Returns(folder3);
var result = await sut.FindAssetFolderAsync(appId.Id, folderId3);
@ -265,7 +266,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
{
var folderId1 = DomainId.NewGuid();
A.CallTo(() => assetFolderRepository.FindAssetFolderAsync(appId.Id, folderId1))
A.CallTo(() => assetFolderRepository.FindAssetFolderAsync(appId.Id, folderId1, A<CancellationToken>._))
.Returns(Task.FromResult<IAssetFolderEntity?>(null));
var result = await sut.FindAssetFolderAsync(appId.Id, folderId1);
@ -282,10 +283,10 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
var folder1 = CreateFolder(folderId1);
var folder2 = CreateFolder(folderId2, folderId1);
A.CallTo(() => assetFolderRepository.FindAssetFolderAsync(appId.Id, folderId1))
A.CallTo(() => assetFolderRepository.FindAssetFolderAsync(appId.Id, folderId1, A<CancellationToken>._))
.Returns(Task.FromResult<IAssetFolderEntity?>(null));
A.CallTo(() => assetFolderRepository.FindAssetFolderAsync(appId.Id, folderId2))
A.CallTo(() => assetFolderRepository.FindAssetFolderAsync(appId.Id, folderId2, A<CancellationToken>._))
.Returns(folder2);
var result = await sut.FindAssetFolderAsync(appId.Id, folderId2);
@ -302,10 +303,10 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
var folder1 = CreateFolder(folderId1, folderId2);
var folder2 = CreateFolder(folderId2, folderId1);
A.CallTo(() => assetFolderRepository.FindAssetFolderAsync(appId.Id, folderId1))
A.CallTo(() => assetFolderRepository.FindAssetFolderAsync(appId.Id, folderId1, A<CancellationToken>._))
.Returns(Task.FromResult<IAssetFolderEntity?>(null));
A.CallTo(() => assetFolderRepository.FindAssetFolderAsync(appId.Id, folderId2))
A.CallTo(() => assetFolderRepository.FindAssetFolderAsync(appId.Id, folderId2, A<CancellationToken>._))
.Returns(folder2);
var result = await sut.FindAssetFolderAsync(appId.Id, folderId2);
@ -337,7 +338,7 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
private void SetupEnricher()
{
A.CallTo(() => assetEnricher.EnrichAsync(A<IEnumerable<IAssetEntity>>._, A<Context>._))
A.CallTo(() => assetEnricher.EnrichAsync(A<IEnumerable<IAssetEntity>>._, A<Context>._, A<CancellationToken>._))
.ReturnsLazily(x =>
{
var input = x.GetArgument<IEnumerable<IAssetEntity>>(0)!;
@ -346,4 +347,4 @@ namespace Squidex.Domain.Apps.Entities.Assets.Queries
});
}
}
}
}

7
backend/tests/Squidex.Domain.Apps.Entities.Tests/Assets/RecursiveDeleterTests.cs

@ -7,6 +7,7 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using FakeItEasy;
using Squidex.Domain.Apps.Entities.Assets.Commands;
@ -80,7 +81,7 @@ namespace Squidex.Domain.Apps.Entities.Assets
var childFolderId1 = DomainId.NewGuid();
var childFolderId2 = DomainId.NewGuid();
A.CallTo(() => assetFolderRepository.QueryChildIdsAsync(appId.Id, @event.AssetFolderId))
A.CallTo(() => assetFolderRepository.QueryChildIdsAsync(appId.Id, @event.AssetFolderId, A<CancellationToken>._))
.Returns(new List<DomainId> { childFolderId1, childFolderId2 });
await sut.On(Envelope.Create(@event));
@ -100,7 +101,7 @@ namespace Squidex.Domain.Apps.Entities.Assets
var childId1 = DomainId.NewGuid();
var childId2 = DomainId.NewGuid();
A.CallTo(() => assetRepository.QueryChildIdsAsync(appId.Id, @event.AssetFolderId))
A.CallTo(() => assetRepository.QueryChildIdsAsync(appId.Id, @event.AssetFolderId, A<CancellationToken>._))
.Returns(new List<DomainId> { childId1, childId2 });
await sut.On(Envelope.Create(@event));
@ -123,7 +124,7 @@ namespace Squidex.Domain.Apps.Entities.Assets
A.CallTo(() => commandBus.PublishAsync(A<DeleteAsset>.That.Matches(x => x.AssetId == childId1)))
.Throws(new InvalidOperationException());
A.CallTo(() => assetRepository.QueryChildIdsAsync(appId.Id, @event.AssetFolderId))
A.CallTo(() => assetRepository.QueryChildIdsAsync(appId.Id, @event.AssetFolderId, A<CancellationToken>._))
.Returns(new List<DomainId> { childId1, childId2 });
await sut.On(Envelope.Create(@event));

2
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/BackupContentsTests.cs

@ -193,7 +193,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
var rebuildContents = new HashSet<DomainId>();
A.CallTo(() => rebuilder.InsertManyAsync<ContentDomainObject, ContentDomainObject.State>(A<IEnumerable<DomainId>>._, A<int>._, A<CancellationToken>._))
.Invokes((IEnumerable<DomainId> source, CancellationToken _) => rebuildContents.AddRange(source));
.Invokes((IEnumerable<DomainId> source, int _, CancellationToken _) => rebuildContents.AddRange(source));
await sut.RestoreAsync(context);

11
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/ContentsSearchSourceTests.cs

@ -7,6 +7,7 @@
using System.Collections.Generic;
using System.Security.Claims;
using System.Threading;
using System.Threading.Tasks;
using FakeItEasy;
using FluentAssertions;
@ -155,7 +156,7 @@ namespace Squidex.Domain.Apps.Entities.Contents
{
var ctx = ContextWithPermissions();
var result = await sut.SearchAsync("query", ctx);
var result = await sut.SearchAsync("query", ctx, default);
Assert.Empty(result);
@ -171,11 +172,11 @@ namespace Squidex.Domain.Apps.Entities.Contents
A.CallTo(() => contentIndex.SearchAsync(ctx.App, A<TextQuery>.That.Matches(x => x.Text == "query~"), ctx.Scope()))
.Returns(new List<DomainId>());
var result = await sut.SearchAsync("query", ctx);
var result = await sut.SearchAsync("query", ctx, default);
Assert.Empty(result);
A.CallTo(() => contentQuery.QueryAsync(ctx, A<Q>._))
A.CallTo(() => contentQuery.QueryAsync(ctx, A<Q>._, A<CancellationToken>._))
.MustNotHaveHappened();
}
@ -190,13 +191,13 @@ namespace Squidex.Domain.Apps.Entities.Contents
A.CallTo(() => contentIndex.SearchAsync(ctx.App, A<TextQuery>.That.Matches(x => x.Text == "query~" && x.Filter != null), ctx.Scope()))
.Returns(ids);
A.CallTo(() => contentQuery.QueryAsync(ctx, A<Q>.That.HasIds(ids)))
A.CallTo(() => contentQuery.QueryAsync(ctx, A<Q>.That.HasIds(ids), A<CancellationToken>._))
.Returns(ResultList.CreateFrom<IEnrichedContentEntity>(1, content));
A.CallTo(() => urlGenerator.ContentUI(appId, schemaId1, content.Id))
.Returns("content-url");
var result = await sut.SearchAsync("query", ctx);
var result = await sut.SearchAsync("query", ctx, default);
result.Should().BeEquivalentTo(
new SearchResults()

7
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DomainObject/ContentCommandMiddlewareTests.cs

@ -5,6 +5,7 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Threading;
using System.Threading.Tasks;
using FakeItEasy;
using Orleans;
@ -51,7 +52,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
{
await HandleAsync(new CreateContent(), 12);
A.CallTo(() => contentEnricher.EnrichAsync(A<IEnrichedContentEntity>._, A<bool>._, requestContext))
A.CallTo(() => contentEnricher.EnrichAsync(A<IEnrichedContentEntity>._, A<bool>._, requestContext, A<CancellationToken>._))
.MustNotHaveHappened();
}
@ -66,7 +67,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
Assert.Same(result, context.Result<IEnrichedContentEntity>());
A.CallTo(() => contentEnricher.EnrichAsync(A<IEnrichedContentEntity>._, A<bool>._, requestContext))
A.CallTo(() => contentEnricher.EnrichAsync(A<IEnrichedContentEntity>._, A<bool>._, requestContext, A<CancellationToken>._))
.MustNotHaveHappened();
}
@ -77,7 +78,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
var enriched = new ContentEntity();
A.CallTo(() => contentEnricher.EnrichAsync(result, true, requestContext))
A.CallTo(() => contentEnricher.EnrichAsync(result, true, requestContext, A<CancellationToken>._))
.Returns(enriched);
var context =

79
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DomainObject/ContentDomainObjectTests.cs

@ -5,6 +5,7 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Threading;
using System.Threading.Tasks;
using FakeItEasy;
using Microsoft.Extensions.DependencyInjection;
@ -100,7 +101,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
A.CallTo(() => appProvider.GetAppWithSchemaAsync(AppId, SchemaId, false))
.Returns((app, schema));
A.CallTo(() => scriptEngine.TransformAsync(A<ScriptVars>._, A<string>._, ScriptOptions()))
A.CallTo(() => scriptEngine.TransformAsync(A<ScriptVars>._, A<string>._, ScriptOptions(), default))
.ReturnsLazily(x => Task.FromResult(x.GetArgument<ScriptVars>(0)!.Data!));
patched = patch.MergeInto(data);
@ -148,9 +149,9 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
CreateContentEvent(new ContentCreated { Data = data, Status = Status.Draft })
);
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(data, null, Status.Draft), "<create-script>", ScriptOptions()))
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(data, null, Status.Draft), "<create-script>", ScriptOptions(), default))
.MustHaveHappened();
A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<change-script>", ScriptOptions()))
A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<change-script>", ScriptOptions(), default))
.MustNotHaveHappened();
}
@ -171,9 +172,9 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
CreateContentEvent(new ContentCreated { Data = data, Status = Status.Draft })
);
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(data, null, Status.Draft), "<create-script>", ScriptOptions()))
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(data, null, Status.Draft), "<create-script>", ScriptOptions(), default))
.MustHaveHappened();
A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<change-script>", ScriptOptions()))
A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<change-script>", ScriptOptions(), default))
.MustNotHaveHappened();
}
@ -195,9 +196,9 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
CreateContentEvent(new ContentStatusChanged { Status = Status.Archived })
);
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(data, null, Status.Draft), "<create-script>", ScriptOptions()))
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(data, null, Status.Draft), "<create-script>", ScriptOptions(), default))
.MustHaveHappened();
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(data, null, Status.Archived, Status.Draft), "<change-script>", ScriptOptions()))
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(data, null, Status.Archived, Status.Draft), "<change-script>", ScriptOptions(), default))
.MustHaveHappened();
}
@ -248,9 +249,9 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
CreateContentEvent(new ContentCreated { Data = data, Status = Status.Draft })
);
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(data, null, Status.Draft), "<create-script>", ScriptOptions()))
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(data, null, Status.Draft), "<create-script>", ScriptOptions(), default))
.MustHaveHappened();
A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<change-script>", ScriptOptions()))
A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<change-script>", ScriptOptions(), default))
.MustNotHaveHappened();
}
@ -271,9 +272,9 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
CreateContentEvent(new ContentCreated { Data = data, Status = Status.Draft })
);
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(data, null, Status.Draft), "<create-script>", ScriptOptions()))
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(data, null, Status.Draft), "<create-script>", ScriptOptions(), default))
.MustHaveHappened();
A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<change-script>", ScriptOptions()))
A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<change-script>", ScriptOptions(), default))
.MustNotHaveHappened();
}
@ -295,9 +296,9 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
CreateContentEvent(new ContentStatusChanged { Status = Status.Archived })
);
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(data, null, Status.Draft), "<create-script>", ScriptOptions()))
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(data, null, Status.Draft), "<create-script>", ScriptOptions(), default))
.MustHaveHappened();
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(data, null, Status.Archived, Status.Draft), "<change-script>", ScriptOptions()))
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(data, null, Status.Archived, Status.Draft), "<change-script>", ScriptOptions(), default))
.MustHaveHappened();
}
@ -319,7 +320,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
CreateContentEvent(new ContentUpdated { Data = otherData })
);
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(otherData, data, Status.Draft), "<update-script>", ScriptOptions()))
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(otherData, data, Status.Draft), "<update-script>", ScriptOptions(), default))
.MustHaveHappened();
}
@ -341,7 +342,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
CreateContentEvent(new ContentUpdated { Data = otherData })
);
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(otherData, data, Status.Draft), "<update-script>", ScriptOptions()))
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(otherData, data, Status.Draft), "<update-script>", ScriptOptions(), default))
.MustHaveHappened();
}
@ -365,9 +366,9 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
CreateContentEvent(new ContentStatusChanged { Status = Status.Archived })
);
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(otherData, data, Status.Draft), "<update-script>", ScriptOptions()))
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(otherData, data, Status.Draft), "<update-script>", ScriptOptions(), default))
.MustHaveHappened();
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(otherData, null, Status.Archived, Status.Draft), "<change-script>", ScriptOptions()))
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(otherData, null, Status.Archived, Status.Draft), "<change-script>", ScriptOptions(), default))
.MustHaveHappened();
}
@ -421,7 +422,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
CreateContentEvent(new ContentUpdated { Data = otherData })
);
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(otherData, data, Status.Draft), "<update-script>", ScriptOptions()))
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(otherData, data, Status.Draft), "<update-script>", ScriptOptions(), default))
.MustHaveHappened();
}
@ -445,7 +446,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
CreateContentEvent(new ContentUpdated { Data = otherData })
);
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(otherData, data, Status.Draft), "<update-script>", ScriptOptions()))
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(otherData, data, Status.Draft), "<update-script>", ScriptOptions(), default))
.MustHaveHappened();
}
@ -462,7 +463,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
Assert.Single(LastEvents);
A.CallTo(() => scriptEngine.TransformAsync(A<ScriptVars>._, "<update-script>", ScriptOptions()))
A.CallTo(() => scriptEngine.TransformAsync(A<ScriptVars>._, "<update-script>", ScriptOptions(), default))
.MustNotHaveHappened();
}
@ -494,7 +495,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
CreateContentEvent(new ContentUpdated { Data = patched })
);
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(patched, data, Status.Draft), "<update-script>", ScriptOptions()))
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(patched, data, Status.Draft), "<update-script>", ScriptOptions(), default))
.MustHaveHappened();
}
@ -518,7 +519,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
CreateContentEvent(new ContentUpdated { Data = patched })
);
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(patched, data, Status.Draft), "<update-script>", ScriptOptions()))
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(patched, data, Status.Draft), "<update-script>", ScriptOptions(), default))
.MustHaveHappened();
}
@ -535,7 +536,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
Assert.Single(LastEvents);
A.CallTo(() => scriptEngine.TransformAsync(A<ScriptVars>._, "<update-script>", ScriptOptions()))
A.CallTo(() => scriptEngine.TransformAsync(A<ScriptVars>._, "<update-script>", ScriptOptions(), default))
.MustNotHaveHappened();
}
@ -557,7 +558,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
CreateContentEvent(new ContentStatusChanged { Status = Status.Archived })
);
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(data, null, Status.Archived, Status.Draft), "<change-script>", ScriptOptions()))
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(data, null, Status.Archived, Status.Draft), "<change-script>", ScriptOptions(), default))
.MustHaveHappened();
}
@ -579,7 +580,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
CreateContentEvent(new ContentStatusChanged { Status = Status.Archived })
);
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(data, null, Status.Archived, Status.Draft), "<change-script>", ScriptOptions()))
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(data, null, Status.Archived, Status.Draft), "<change-script>", ScriptOptions(), default))
.MustHaveHappened();
}
@ -602,7 +603,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
CreateContentEvent(new ContentStatusChanged { Status = Status.Draft, Change = StatusChange.Unpublished })
);
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(data, null, Status.Draft, Status.Published), "<change-script>", ScriptOptions()))
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(data, null, Status.Draft, Status.Published), "<change-script>", ScriptOptions(), default))
.MustHaveHappened();
}
@ -611,7 +612,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
{
var command = new ChangeContentStatus { Status = Status.Draft };
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(data, null, Status.Draft, Status.Published), "<change-script>", ScriptOptions()))
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(data, null, Status.Draft, Status.Published), "<change-script>", ScriptOptions(), default))
.Returns(otherData);
await ExecuteCreateAsync();
@ -630,7 +631,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
CreateContentEvent(new ContentStatusChanged { Status = Status.Draft, Change = StatusChange.Unpublished })
);
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(data, null, Status.Draft, Status.Published), "<change-script>", ScriptOptions()))
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(data, null, Status.Draft, Status.Published), "<change-script>", ScriptOptions(), default))
.MustHaveHappened();
}
@ -654,7 +655,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
CreateContentEvent(new ContentStatusChanged { Change = StatusChange.Change, Status = Status.Archived })
);
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(data, null, Status.Archived, Status.Draft), "<change-script>", ScriptOptions()))
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(data, null, Status.Archived, Status.Draft), "<change-script>", ScriptOptions(), default))
.MustHaveHappened();
}
@ -678,7 +679,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
CreateContentEvent(new ContentStatusChanged { Change = StatusChange.Published, Status = Status.Published })
);
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(data, null, Status.Published, Status.Draft), "<change-script>", ScriptOptions()))
A.CallTo(() => scriptEngine.TransformAsync(ScriptVars(data, null, Status.Published, Status.Draft), "<change-script>", ScriptOptions(), default))
.MustHaveHappened();
}
@ -705,7 +706,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
CreateContentEvent(new ContentStatusScheduled { Status = Status.Published, DueTime = dueTime })
);
A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<change-script>", ScriptOptions()))
A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<change-script>", ScriptOptions(), default))
.MustNotHaveHappened();
}
@ -733,7 +734,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
CreateContentEvent(new ContentStatusChanged { Status = Status.Archived })
);
A.CallTo(() => scriptEngine.TransformAsync(A<ScriptVars>._, "<change-script>", ScriptOptions()))
A.CallTo(() => scriptEngine.TransformAsync(A<ScriptVars>._, "<change-script>", ScriptOptions(), default))
.MustHaveHappened();
}
@ -761,7 +762,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
CreateContentEvent(new ContentSchedulingCancelled())
);
A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<change-script>", ScriptOptions()))
A.CallTo(() => scriptEngine.ExecuteAsync(A<ScriptVars>._, "<change-script>", ScriptOptions(), default))
.MustNotHaveHappened();
}
@ -773,7 +774,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
await ExecuteCreateAsync();
await ExecuteChangeStatusAsync(Status.Published);
A.CallTo(() => contentRepository.HasReferrersAsync(AppId, contentId, SearchScope.All))
A.CallTo(() => contentRepository.HasReferrersAsync(AppId, contentId, SearchScope.All, A<CancellationToken>._))
.Returns(true);
await Assert.ThrowsAsync<DomainException>(() => PublishAsync(command));
@ -787,7 +788,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
await ExecuteCreateAsync();
await ExecuteChangeStatusAsync(Status.Published);
A.CallTo(() => contentRepository.HasReferrersAsync(AppId, contentId, SearchScope.Published))
A.CallTo(() => contentRepository.HasReferrersAsync(AppId, contentId, SearchScope.Published, A<CancellationToken>._))
.Returns(true);
await PublishAsync(command);
@ -823,7 +824,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
CreateContentEvent(new ContentDeleted())
);
A.CallTo(() => scriptEngine.ExecuteAsync(ScriptVars(data, null, Status.Draft), "<delete-script>", ScriptOptions()))
A.CallTo(() => scriptEngine.ExecuteAsync(ScriptVars(data, null, Status.Draft), "<delete-script>", ScriptOptions(), default))
.MustHaveHappened();
}
@ -841,7 +842,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
Assert.Equal(EtagVersion.Empty, sut.Snapshot.Version);
Assert.Empty(LastEvents);
A.CallTo(() => scriptEngine.ExecuteAsync(ScriptVars(data, null, Status.Draft), "<delete-script>", ScriptOptions()))
A.CallTo(() => scriptEngine.ExecuteAsync(ScriptVars(data, null, Status.Draft), "<delete-script>", ScriptOptions(), default))
.MustHaveHappened();
}
@ -852,7 +853,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
var command = new DeleteContent { CheckReferrers = true };
A.CallTo(() => contentRepository.HasReferrersAsync(AppId, contentId, SearchScope.All))
A.CallTo(() => contentRepository.HasReferrersAsync(AppId, contentId, SearchScope.All, A<CancellationToken>._))
.Returns(true);
await Assert.ThrowsAsync<DomainException>(() => PublishAsync(command));
@ -865,7 +866,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
await ExecuteCreateAsync();
A.CallTo(() => contentRepository.HasReferrersAsync(AppId, contentId, SearchScope.All))
A.CallTo(() => contentRepository.HasReferrersAsync(AppId, contentId, SearchScope.All, A<CancellationToken>._))
.Returns(true);
await PublishAsync(command);

7
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/DomainObject/ContentsBulkUpdateCommandMiddlewareTests.cs

@ -7,6 +7,7 @@
using System;
using System.Security.Claims;
using System.Threading;
using System.Threading.Tasks;
using FakeItEasy;
using NodaTime;
@ -88,7 +89,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
x.ShouldSkipCleanup() &&
x.ShouldSkipContentEnrichment() &&
x.ShouldSkipTotal()),
schemaId.Name, A<Q>.That.Matches(x => x.JsonQuery == query)))
schemaId.Name, A<Q>.That.Matches(x => x.JsonQuery == query), A<CancellationToken>._))
.Returns(ResultList.CreateFrom(2, CreateContent(id), CreateContent(id)));
var command = BulkCommand(BulkUpdateContentType.ChangeStatus, query);
@ -114,7 +115,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
x.ShouldSkipCleanup() &&
x.ShouldSkipContentEnrichment() &&
x.ShouldSkipTotal()),
schemaId.Name, A<Q>.That.Matches(x => x.JsonQuery == query)))
schemaId.Name, A<Q>.That.Matches(x => x.JsonQuery == query), A<CancellationToken>._))
.Returns(ResultList.CreateFrom(1, CreateContent(id)));
var command = BulkCommand(BulkUpdateContentType.Upsert, query: query, data: data);
@ -144,7 +145,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
x.ShouldSkipCleanup() &&
x.ShouldSkipContentEnrichment() &&
x.ShouldSkipTotal()),
schemaId.Name, A<Q>.That.Matches(x => x.JsonQuery == query)))
schemaId.Name, A<Q>.That.Matches(x => x.JsonQuery == query), A<CancellationToken>._))
.Returns(ResultList.CreateFrom(2,
CreateContent(id1),
CreateContent(id2)));

43
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/GraphQL/GraphQLQueriesTests.cs

@ -5,6 +5,7 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Threading;
using System.Threading.Tasks;
using FakeItEasy;
using GraphQL;
@ -60,7 +61,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
var asset = TestAsset.Create(appId, DomainId.NewGuid());
A.CallTo(() => assetQuery.QueryAsync(MatchsAssetContext(), null,
A<Q>.That.Matches(x => x.ODataQuery == "?$top=30&$skip=5&$filter=my-query" && x.NoTotal == true)))
A<Q>.That.Matches(x => x.ODataQuery == "?$top=30&$skip=5&$filter=my-query" && x.NoTotal == true), A<CancellationToken>._))
.Returns(ResultList.CreateFrom(0, asset));
var result = await ExecuteAsync(new ExecutionOptions { Query = query });
@ -95,7 +96,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
var asset = TestAsset.Create(appId, DomainId.NewGuid());
A.CallTo(() => assetQuery.QueryAsync(MatchsAssetContext(), null,
A<Q>.That.Matches(x => x.ODataQuery == "?$top=30&$skip=5&$filter=my-query" && x.NoTotal == false)))
A<Q>.That.Matches(x => x.ODataQuery == "?$top=30&$skip=5&$filter=my-query" && x.NoTotal == false), A<CancellationToken>._))
.Returns(ResultList.CreateFrom(10, asset));
var result = await ExecuteAsync(new ExecutionOptions { Query = query });
@ -130,7 +131,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
}
}", assetId);
A.CallTo(() => assetQuery.QueryAsync(MatchsAssetContext(), null, A<Q>.That.HasIdsWithoutTotal(assetId)))
A.CallTo(() => assetQuery.QueryAsync(MatchsAssetContext(), null, A<Q>.That.HasIdsWithoutTotal(assetId), A<CancellationToken>._))
.Returns(ResultList.CreateFrom<IEnrichedAssetEntity>(1));
var result = await ExecuteAsync(new ExecutionOptions { Query = query });
@ -159,7 +160,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
}
}", assetId);
A.CallTo(() => assetQuery.QueryAsync(MatchsAssetContext(), null, A<Q>.That.HasIdsWithoutTotal(assetId)))
A.CallTo(() => assetQuery.QueryAsync(MatchsAssetContext(), null, A<Q>.That.HasIdsWithoutTotal(assetId), A<CancellationToken>._))
.Returns(ResultList.CreateFrom(1, asset));
var result = await ExecuteAsync(new ExecutionOptions { Query = query });
@ -211,7 +212,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
var content = TestContent.Create(appId, schemaId, DomainId.NewGuid(), DomainId.Empty, DomainId.Empty);
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), schemaId.Id.ToString(),
A<Q>.That.Matches(x => x.ODataQuery == "?$top=30&$skip=5" && x.NoTotal == true)))
A<Q>.That.Matches(x => x.ODataQuery == "?$top=30&$skip=5" && x.NoTotal == true), A<CancellationToken>._))
.Returns(ResultList.CreateFrom(0, content));
var result = await ExecuteAsync(new ExecutionOptions { Query = query });
@ -290,7 +291,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
var content = TestContent.Create(appId, schemaId, DomainId.NewGuid(), DomainId.Empty, DomainId.Empty);
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), schemaId.Id.ToString(),
A<Q>.That.Matches(x => x.ODataQuery == "?$top=30&$skip=5" && x.NoTotal == true)))
A<Q>.That.Matches(x => x.ODataQuery == "?$top=30&$skip=5" && x.NoTotal == true), A<CancellationToken>._))
.Returns(ResultList.CreateFrom(0, content));
var result = await ExecuteAsync(new ExecutionOptions { Query = query });
@ -325,7 +326,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
var content = TestContent.Create(appId, schemaId, DomainId.NewGuid(), DomainId.Empty, DomainId.Empty);
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), schemaId.Id.ToString(),
A<Q>.That.Matches(x => x.ODataQuery == "?$top=30&$skip=5" && x.NoTotal == false)))
A<Q>.That.Matches(x => x.ODataQuery == "?$top=30&$skip=5" && x.NoTotal == false), A<CancellationToken>._))
.Returns(ResultList.CreateFrom(10, content));
var result = await ExecuteAsync(new ExecutionOptions { Query = query });
@ -360,7 +361,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
}
}", contentId);
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), A<Q>.That.HasIdsWithoutTotal(contentId)))
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), A<Q>.That.HasIdsWithoutTotal(contentId), A<CancellationToken>._))
.Returns(ResultList.CreateFrom<IEnrichedContentEntity>(1));
var result = await ExecuteAsync(new ExecutionOptions { Query = query });
@ -389,7 +390,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
}
}", contentId);
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), A<Q>.That.HasIdsWithoutTotal(contentId)))
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), A<Q>.That.HasIdsWithoutTotal(contentId), A<CancellationToken>._))
.Returns(ResultList.CreateFrom(1, content));
var result = await ExecuteAsync(new ExecutionOptions { Query = query });
@ -418,7 +419,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
}
}", contentId);
A.CallTo(() => contentQuery.FindAsync(MatchsContentContext(), schemaId.Id.ToString(), contentId, 3))
A.CallTo(() => contentQuery.FindAsync(MatchsContentContext(), schemaId.Id.ToString(), contentId, 3, A<CancellationToken>._))
.Returns(content);
var result = await ExecuteAsync(new ExecutionOptions { Query = query });
@ -462,10 +463,10 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
}
}", contentId);
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), A<Q>.That.HasIdsWithoutTotal(contentRefId)))
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), A<Q>.That.HasIdsWithoutTotal(contentRefId), A<CancellationToken>._))
.Returns(ResultList.CreateFrom(0, contentRef));
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), A<Q>.That.HasIdsWithoutTotal(contentId)))
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), A<Q>.That.HasIdsWithoutTotal(contentId), A<CancellationToken>._))
.Returns(ResultList.CreateFrom(1, content));
var result = await ExecuteAsync(new ExecutionOptions { Query = query });
@ -528,11 +529,11 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
}
}", contentRefId);
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), A<Q>.That.HasIdsWithoutTotal(contentRefId)))
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), A<Q>.That.HasIdsWithoutTotal(contentRefId), A<CancellationToken>._))
.Returns(ResultList.CreateFrom(1, contentRef));
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), content.SchemaId.Id.ToString(),
A<Q>.That.Matches(x => x.ODataQuery == "?$top=30&$skip=5" && x.Reference == contentRefId && x.NoTotal == true)))
A<Q>.That.Matches(x => x.ODataQuery == "?$top=30&$skip=5" && x.Reference == contentRefId && x.NoTotal == true), A<CancellationToken>._))
.Returns(ResultList.CreateFrom(1, content));
var result = await ExecuteAsync(new ExecutionOptions { Query = query });
@ -592,11 +593,11 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
}
}", contentRefId);
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), A<Q>.That.HasIdsWithoutTotal(contentRefId)))
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), A<Q>.That.HasIdsWithoutTotal(contentRefId), A<CancellationToken>._))
.Returns(ResultList.CreateFrom(1, contentRef));
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), content.SchemaId.Id.ToString(),
A<Q>.That.Matches(x => x.ODataQuery == "?$top=30&$skip=5" && x.Reference == contentRefId && x.NoTotal == false)))
A<Q>.That.Matches(x => x.ODataQuery == "?$top=30&$skip=5" && x.Reference == contentRefId && x.NoTotal == false), A<CancellationToken>._))
.Returns(ResultList.CreateFrom(1, content));
var result = await ExecuteAsync(new ExecutionOptions { Query = query });
@ -666,10 +667,10 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
}
}", contentId);
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), A<Q>.That.HasIdsWithoutTotal(contentRefId)))
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), A<Q>.That.HasIdsWithoutTotal(contentRefId), A<CancellationToken>._))
.Returns(ResultList.CreateFrom(0, contentRef));
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), A<Q>.That.HasIdsWithoutTotal(contentId)))
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), A<Q>.That.HasIdsWithoutTotal(contentId), A<CancellationToken>._))
.Returns(ResultList.CreateFrom(1, content));
var result = await ExecuteAsync(new ExecutionOptions { Query = query });
@ -732,10 +733,10 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
}
}", contentId);
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), A<Q>.That.HasIdsWithoutTotal(contentId)))
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), A<Q>.That.HasIdsWithoutTotal(contentId), A<CancellationToken>._))
.Returns(ResultList.CreateFrom(1, content));
A.CallTo(() => assetQuery.QueryAsync(MatchsAssetContext(), null, A<Q>.That.HasIdsWithoutTotal(assetRefId)))
A.CallTo(() => assetQuery.QueryAsync(MatchsAssetContext(), null, A<Q>.That.HasIdsWithoutTotal(assetRefId), A<CancellationToken>._))
.Returns(ResultList.CreateFrom(0, assetRef));
var result = await ExecuteAsync(new ExecutionOptions { Query = query });
@ -791,7 +792,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.GraphQL
}
}", contentId);
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), A<Q>.That.HasIdsWithoutTotal(contentId)))
A.CallTo(() => contentQuery.QueryAsync(MatchsContentContext(), A<Q>.That.HasIdsWithoutTotal(contentId), A<CancellationToken>._))
.Returns(ResultList.CreateFrom(1, content));
var result = await ExecuteAsync(new ExecutionOptions { Query = query });

30
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/ContentEnricherTests.cs

@ -8,6 +8,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using FakeItEasy;
using Squidex.Domain.Apps.Core.Contents;
@ -30,7 +31,8 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
{
public ISchemaEntity Schema { get; private set; }
public async Task EnrichAsync(Context context, IEnumerable<ContentEntity> contents, ProvideSchema schemas)
public async Task EnrichAsync(Context context, IEnumerable<ContentEntity> contents, ProvideSchema schemas,
CancellationToken ct)
{
foreach (var group in contents.GroupBy(x => x.SchemaId.Id))
{
@ -59,18 +61,18 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
var sut = new ContentEnricher(new[] { step1, step2 }, new Lazy<IContentQueryService>(() => contentQuery));
await sut.EnrichAsync(source, requestContext);
await sut.EnrichAsync(source, requestContext, default);
A.CallTo(() => step1.EnrichAsync(requestContext))
A.CallTo(() => step1.EnrichAsync(requestContext, A<CancellationToken>._))
.MustHaveHappened();
A.CallTo(() => step2.EnrichAsync(requestContext))
A.CallTo(() => step2.EnrichAsync(requestContext, A<CancellationToken>._))
.MustHaveHappened();
A.CallTo(() => step1.EnrichAsync(requestContext, A<IEnumerable<ContentEntity>>._, A<ProvideSchema>._))
A.CallTo(() => step1.EnrichAsync(requestContext, A<IEnumerable<ContentEntity>>._, A<ProvideSchema>._, A<CancellationToken>._))
.MustNotHaveHappened();
A.CallTo(() => step2.EnrichAsync(requestContext, A<IEnumerable<ContentEntity>>._, A<ProvideSchema>._))
A.CallTo(() => step2.EnrichAsync(requestContext, A<IEnumerable<ContentEntity>>._, A<ProvideSchema>._, A<CancellationToken>._))
.MustNotHaveHappened();
}
@ -84,18 +86,18 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
var sut = new ContentEnricher(new[] { step1, step2 }, new Lazy<IContentQueryService>(() => contentQuery));
await sut.EnrichAsync(source, false, requestContext);
await sut.EnrichAsync(source, false, requestContext, default);
A.CallTo(() => step1.EnrichAsync(requestContext))
A.CallTo(() => step1.EnrichAsync(requestContext, A<CancellationToken>._))
.MustHaveHappened();
A.CallTo(() => step2.EnrichAsync(requestContext))
A.CallTo(() => step2.EnrichAsync(requestContext, A<CancellationToken>._))
.MustHaveHappened();
A.CallTo(() => step1.EnrichAsync(requestContext, A<IEnumerable<ContentEntity>>._, A<ProvideSchema>._))
A.CallTo(() => step1.EnrichAsync(requestContext, A<IEnumerable<ContentEntity>>._, A<ProvideSchema>._, A<CancellationToken>._))
.MustHaveHappened();
A.CallTo(() => step2.EnrichAsync(requestContext, A<IEnumerable<ContentEntity>>._, A<ProvideSchema>._))
A.CallTo(() => step2.EnrichAsync(requestContext, A<IEnumerable<ContentEntity>>._, A<ProvideSchema>._, A<CancellationToken>._))
.MustHaveHappened();
}
@ -109,7 +111,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
var sut = new ContentEnricher(new[] { step1, step2 }, new Lazy<IContentQueryService>(() => contentQuery));
await sut.EnrichAsync(source, false, requestContext);
await sut.EnrichAsync(source, false, requestContext, default);
Assert.Same(schema, step1.Schema);
Assert.Same(schema, step1.Schema);
@ -125,7 +127,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
var sut = new ContentEnricher(Enumerable.Empty<IContentEnricherStep>(), new Lazy<IContentQueryService>(() => contentQuery));
var result = await sut.EnrichAsync(source, true, requestContext);
var result = await sut.EnrichAsync(source, true, requestContext, default);
Assert.NotSame(source.Data, result.Data);
}
@ -137,7 +139,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
var sut = new ContentEnricher(Enumerable.Empty<IContentEnricherStep>(), new Lazy<IContentQueryService>(() => contentQuery));
var result = await sut.EnrichAsync(source, false, requestContext);
var result = await sut.EnrichAsync(source, false, requestContext, default);
Assert.Same(source.Data, result.Data);
}

31
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/ContentQueryServiceTests.cs

@ -8,6 +8,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading;
using System.Threading.Tasks;
using FakeItEasy;
using Squidex.Domain.Apps.Core.Contents;
@ -113,7 +114,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
var content = CreateContent(DomainId.NewGuid());
A.CallTo(() => contentRepository.FindContentAsync(requestContext.App, schema, content.Id, A<SearchScope>._))
A.CallTo(() => contentRepository.FindContentAsync(requestContext.App, schema, content.Id, A<SearchScope>._, A<CancellationToken>._))
.Returns(CreateContent(DomainId.NewGuid()));
await Assert.ThrowsAsync<DomainForbiddenException>(() => sut.FindAsync(requestContext, schemaId.Name, content.Id));
@ -126,7 +127,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
var content = CreateContent(DomainId.NewGuid());
A.CallTo(() => contentRepository.FindContentAsync(requestContext.App, schema, content.Id, A<SearchScope>._))
A.CallTo(() => contentRepository.FindContentAsync(requestContext.App, schema, content.Id, A<SearchScope>._, A<CancellationToken>._))
.Returns<IContentEntity?>(null);
Assert.Null(await sut.FindAsync(requestContext, schemaId.Name, content.Id));
@ -143,7 +144,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
var content = CreateContent(DomainId.NewGuid());
A.CallTo(() => contentRepository.FindContentAsync(requestContext.App, schema, content.Id, scope))
A.CallTo(() => contentRepository.FindContentAsync(requestContext.App, schema, content.Id, scope, A<CancellationToken>._))
.Returns(content);
var result = await sut.FindAsync(requestContext, schemaId.Name, content.Id);
@ -171,7 +172,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
{
var requestContext = CreateContext(allowSchema: false);
await Assert.ThrowsAsync<DomainForbiddenException>(() => sut.QueryAsync(requestContext, schemaId.Name, Q.Empty));
await Assert.ThrowsAsync<DomainForbiddenException>(() => sut.QueryAsync(requestContext, schemaId.Name, Q.Empty, default));
}
[Theory]
@ -188,10 +189,10 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
var q = Q.Empty.WithReference(DomainId.NewGuid());
A.CallTo(() => contentRepository.QueryAsync(requestContext.App, schema, q, scope))
A.CallTo(() => contentRepository.QueryAsync(requestContext.App, schema, q, scope, A<CancellationToken>._))
.Returns(ResultList.CreateFrom(5, content1, content2));
var result = await sut.QueryAsync(requestContext, schemaId.Name, q);
var result = await sut.QueryAsync(requestContext, schemaId.Name, q, default);
Assert.Equal(5, result.Total);
@ -215,10 +216,10 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
var q = Q.Empty.WithIds(ids);
A.CallTo(() => contentRepository.QueryAsync(requestContext.App,
A<List<ISchemaEntity>>.That.Matches(x => x.Count == 1), q, scope))
A<List<ISchemaEntity>>.That.Matches(x => x.Count == 1), q, scope, A<CancellationToken>._))
.Returns(ResultList.Create(5, contents));
var result = await sut.QueryAsync(requestContext, q);
var result = await sut.QueryAsync(requestContext, q, default);
Assert.Equal(5, result.Total);
@ -238,10 +239,10 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
var q = Q.Empty.WithIds(ids);
A.CallTo(() => contentRepository.QueryAsync(requestContext.App,
A<List<ISchemaEntity>>.That.Matches(x => x.Count == 0), q, SearchScope.All))
A<List<ISchemaEntity>>.That.Matches(x => x.Count == 0), q, SearchScope.All, A<CancellationToken>._))
.Returns(ResultList.Create(0, ids.Select(CreateContent)));
var result = await sut.QueryAsync(requestContext, q);
var result = await sut.QueryAsync(requestContext, q, default);
Assert.Empty(result);
}
@ -251,10 +252,10 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
{
var requestContext = CreateContext(permissionId: Permissions.AppContentsReadOwn);
await sut.QueryAsync(requestContext, schemaId.Name, Q.Empty);
await sut.QueryAsync(requestContext, schemaId.Name, Q.Empty, default);
A.CallTo(() => contentRepository.QueryAsync(requestContext.App, schema,
A<Q>.That.Matches(x => Equals(x.CreatedBy, requestContext.User.Token())), SearchScope.Published))
A<Q>.That.Matches(x => Equals(x.CreatedBy, requestContext.User.Token())), SearchScope.Published, A<CancellationToken>._))
.MustHaveHappened();
}
@ -263,16 +264,16 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
{
var requestContext = CreateContext(permissionId: Permissions.AppContentsRead);
await sut.QueryAsync(requestContext, schemaId.Name, Q.Empty);
await sut.QueryAsync(requestContext, schemaId.Name, Q.Empty, default);
A.CallTo(() => contentRepository.QueryAsync(requestContext.App, schema,
A<Q>.That.Matches(x => x.CreatedBy == null), SearchScope.Published))
A<Q>.That.Matches(x => x.CreatedBy == null), SearchScope.Published, A<CancellationToken>._))
.MustHaveHappened();
}
private void SetupEnricher()
{
A.CallTo(() => contentEnricher.EnrichAsync(A<IEnumerable<IContentEntity>>._, A<Context>._))
A.CallTo(() => contentEnricher.EnrichAsync(A<IEnumerable<IContentEntity>>._, A<Context>._, A<CancellationToken>._))
.ReturnsLazily(x =>
{
var input = x.GetArgument<IEnumerable<IContentEntity>>(0)!;

15
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/ConvertDataTests.cs

@ -7,6 +7,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using FakeItEasy;
using Squidex.Domain.Apps.Core;
@ -58,7 +59,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
var ctx = new Context(Mocks.FrontendUser(), Mocks.App(appId));
await sut.EnrichAsync(ctx, Enumerable.Repeat(content, 1), schemaProvider);
await sut.EnrichAsync(ctx, Enumerable.Repeat(content, 1), schemaProvider, default);
Assert.NotNull(content.Data);
}
@ -88,15 +89,15 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
JsonValue.Object()
.Add("nested", JsonValue.Array(id2)))));
A.CallTo(() => assetRepository.QueryIdsAsync(appId.Id, A<HashSet<DomainId>>.That.Is(id1, id2)))
A.CallTo(() => assetRepository.QueryIdsAsync(appId.Id, A<HashSet<DomainId>>.That.Is(id1, id2), A<CancellationToken>._))
.Returns(new List<DomainId> { id2 });
A.CallTo(() => contentRepository.QueryIdsAsync(appId.Id, A<HashSet<DomainId>>.That.Is(id1, id2), SearchScope.All))
A.CallTo(() => contentRepository.QueryIdsAsync(appId.Id, A<HashSet<DomainId>>.That.Is(id1, id2), SearchScope.All, A<CancellationToken>._))
.Returns(new List<(DomainId, DomainId, Status)> { (id2, id2, Status.Published) });
var ctx = new Context(Mocks.FrontendUser(), Mocks.App(appId));
await sut.EnrichAsync(ctx, Enumerable.Repeat(content, 1), schemaProvider);
await sut.EnrichAsync(ctx, Enumerable.Repeat(content, 1), schemaProvider, default);
Assert.Equal(expected, content.Data);
}
@ -126,15 +127,15 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
JsonValue.Object()
.Add("nested", JsonValue.Array()))));
A.CallTo(() => assetRepository.QueryIdsAsync(appId.Id, A<HashSet<DomainId>>.That.Is(id1, id2)))
A.CallTo(() => assetRepository.QueryIdsAsync(appId.Id, A<HashSet<DomainId>>.That.Is(id1, id2), A<CancellationToken>._))
.Returns(new List<DomainId>());
A.CallTo(() => contentRepository.QueryIdsAsync(appId.Id, A<HashSet<DomainId>>.That.Is(id1, id2), SearchScope.All))
A.CallTo(() => contentRepository.QueryIdsAsync(appId.Id, A<HashSet<DomainId>>.That.Is(id1, id2), SearchScope.All, A<CancellationToken>._))
.Returns(new List<(DomainId, DomainId, Status)>());
var ctx = new Context(Mocks.FrontendUser(), Mocks.App(appId));
await sut.EnrichAsync(ctx, Enumerable.Repeat(content, 1), schemaProvider);
await sut.EnrichAsync(ctx, Enumerable.Repeat(content, 1), schemaProvider, default);
Assert.Equal(expected, content.Data);
}

4
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/EnrichForCachingTests.cs

@ -47,7 +47,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
A.CallTo(() => requestCache.AddHeader(A<string>._))
.Invokes(new Action<string>(header => headers.Add(header)));
await sut.EnrichAsync(requestContext);
await sut.EnrichAsync(requestContext, default);
Assert.Equal(new List<string>
{
@ -67,7 +67,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
{
var content = CreateContent();
await sut.EnrichAsync(requestContext, Enumerable.Repeat(content, 1), schemaProvider);
await sut.EnrichAsync(requestContext, Enumerable.Repeat(content, 1), schemaProvider, default);
A.CallTo(() => requestCache.AddDependency(content.UniqueId, content.Version))
.MustHaveHappened();

6
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/EnrichWithSchemaTests.cs

@ -38,7 +38,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
var content = CreateContent();
await sut.EnrichAsync(ctx, Enumerable.Repeat(content, 1), schemaProvider);
await sut.EnrichAsync(ctx, Enumerable.Repeat(content, 1), schemaProvider, default);
Assert.NotNull(content.ReferenceFields);
}
@ -50,7 +50,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
var source = CreateContent();
await sut.EnrichAsync(ctx, Enumerable.Repeat(source, 1), schemaProvider);
await sut.EnrichAsync(ctx, Enumerable.Repeat(source, 1), schemaProvider, default);
Assert.Null(source.ReferenceFields);
}
@ -62,7 +62,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
var content = CreateContent();
await sut.EnrichAsync(ctx, Enumerable.Repeat(content, 1), schemaProvider);
await sut.EnrichAsync(ctx, Enumerable.Repeat(content, 1), schemaProvider, default);
Assert.Equal("my-schema", content.SchemaName);
Assert.Equal("my-schema", content.SchemaDisplayName);

18
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/EnrichWithWorkflowsTests.cs

@ -45,7 +45,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
A.CallTo(() => workflow.GetNextAsync(content, content.Status, requestContext.User))
.Returns(nexts);
await sut.EnrichAsync(requestContext, new[] { content }, null!);
await sut.EnrichAsync(requestContext, new[] { content }, null!, default);
Assert.Equal(nexts, content.NextStatuses);
}
@ -55,7 +55,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
{
var content = new ContentEntity { SchemaId = schemaId, IsSingleton = true, Status = Status.Draft };
await sut.EnrichAsync(requestContext, new[] { content }, null!);
await sut.EnrichAsync(requestContext, new[] { content }, null!, default);
Assert.Equal(Status.Published, content.NextStatuses?.Single().Status);
@ -68,7 +68,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
{
var content = new ContentEntity { SchemaId = schemaId, IsSingleton = true, Status = Status.Published };
await sut.EnrichAsync(requestContext, new[] { content }, null!);
await sut.EnrichAsync(requestContext, new[] { content }, null!, default);
Assert.Empty(content.NextStatuses);
@ -84,7 +84,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
A.CallTo(() => workflow.GetInfoAsync(content, content.Status))
.Returns(new StatusInfo(Status.Published, StatusColors.Published));
await sut.EnrichAsync(requestContext, new[] { content }, null!);
await sut.EnrichAsync(requestContext, new[] { content }, null!, default);
Assert.Equal(StatusColors.Published, content.StatusColor);
}
@ -97,7 +97,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
A.CallTo(() => workflow.GetInfoAsync(content, content.NewStatus.Value))
.Returns(new StatusInfo(Status.Published, StatusColors.Archived));
await sut.EnrichAsync(requestContext, new[] { content }, null!);
await sut.EnrichAsync(requestContext, new[] { content }, null!, default);
Assert.Equal(StatusColors.Archived, content.NewStatusColor);
}
@ -110,7 +110,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
A.CallTo(() => workflow.GetInfoAsync(content, content.ScheduleJob.Status))
.Returns(new StatusInfo(Status.Published, StatusColors.Archived));
await sut.EnrichAsync(requestContext, new[] { content }, null!);
await sut.EnrichAsync(requestContext, new[] { content }, null!, default);
Assert.Equal(StatusColors.Archived, content.ScheduledStatusColor);
}
@ -125,7 +125,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
var ctx = requestContext.Clone(b => b.WithResolveFlow(false));
await sut.EnrichAsync(ctx, new[] { content }, null!);
await sut.EnrichAsync(ctx, new[] { content }, null!, default);
Assert.Equal(StatusColors.Draft, content.StatusColor);
}
@ -140,7 +140,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
var ctx = requestContext.Clone(b => b.WithResolveFlow(false));
await sut.EnrichAsync(ctx, new[] { content }, null!);
await sut.EnrichAsync(ctx, new[] { content }, null!, default);
Assert.True(content.CanUpdate);
}
@ -152,7 +152,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
var ctx = new Context(Mocks.ApiUser(), Mocks.App(appId)).Clone(b => b.WithResolveFlow(false));
await sut.EnrichAsync(ctx, new[] { content }, null!);
await sut.EnrichAsync(ctx, new[] { content }, null!, default);
Assert.False(content.CanUpdate);

25
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/ResolveAssetsTests.cs

@ -7,6 +7,7 @@
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using FakeItEasy;
using Squidex.Domain.Apps.Core;
@ -89,10 +90,10 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
};
A.CallTo(() => assetQuery.QueryAsync(
A<Context>.That.Matches(x => x.ShouldSkipAssetEnrichment() && x.ShouldSkipTotal()), null, A<Q>.That.HasIds(doc1.Id, doc2.Id)))
A<Context>.That.Matches(x => x.ShouldSkipAssetEnrichment() && x.ShouldSkipTotal()), null, A<Q>.That.HasIds(doc1.Id, doc2.Id), A<CancellationToken>._))
.Returns(ResultList.CreateFrom(4, doc1, doc2));
await sut.EnrichAsync(requestContext, contents, schemaProvider);
await sut.EnrichAsync(requestContext, contents, schemaProvider, default);
A.CallTo(() => requestCache.AddDependency(doc1.UniqueId, doc1.Version))
.MustHaveHappened();
@ -121,10 +122,10 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
};
A.CallTo(() => assetQuery.QueryAsync(
A<Context>.That.Matches(x => x.ShouldSkipAssetEnrichment() && x.ShouldSkipTotal()), null, A<Q>.That.HasIds(doc1.Id, doc2.Id, img1.Id, img2.Id)))
A<Context>.That.Matches(x => x.ShouldSkipAssetEnrichment() && x.ShouldSkipTotal()), null, A<Q>.That.HasIds(doc1.Id, doc2.Id, img1.Id, img2.Id), A<CancellationToken>._))
.Returns(ResultList.CreateFrom(4, img1, img2, doc1, doc2));
await sut.EnrichAsync(requestContext, contents, schemaProvider);
await sut.EnrichAsync(requestContext, contents, schemaProvider, default);
Assert.Equal(
new ContentData()
@ -157,11 +158,11 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
var ctx = new Context(Mocks.ApiUser(), Mocks.App(appId));
await sut.EnrichAsync(ctx, contents, schemaProvider);
await sut.EnrichAsync(ctx, contents, schemaProvider, default);
Assert.Null(contents[0].ReferenceData);
A.CallTo(() => assetQuery.QueryAsync(A<Context>._, null, A<Q>._))
A.CallTo(() => assetQuery.QueryAsync(A<Context>._, null, A<Q>._, A<CancellationToken>._))
.MustNotHaveHappened();
}
@ -175,11 +176,11 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
var ctx = new Context(Mocks.FrontendUser(), Mocks.App(appId)).Clone(b => b.WithoutContentEnrichment(true));
await sut.EnrichAsync(ctx, contents, schemaProvider);
await sut.EnrichAsync(ctx, contents, schemaProvider, default);
Assert.Null(contents[0].ReferenceData);
A.CallTo(() => assetQuery.QueryAsync(A<Context>._, null, A<Q>._))
A.CallTo(() => assetQuery.QueryAsync(A<Context>._, null, A<Q>._, A<CancellationToken>._))
.MustNotHaveHappened();
}
@ -191,11 +192,11 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
CreateContent(Array.Empty<DomainId>(), Array.Empty<DomainId>())
};
await sut.EnrichAsync(requestContext, contents, schemaProvider);
await sut.EnrichAsync(requestContext, contents, schemaProvider, default);
Assert.NotNull(contents[0].ReferenceData);
A.CallTo(() => assetQuery.QueryAsync(A<Context>._, null, A<Q>._))
A.CallTo(() => assetQuery.QueryAsync(A<Context>._, null, A<Q>._, A<CancellationToken>._))
.MustNotHaveHappened();
}
@ -210,12 +211,12 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
CreateContent(new[] { id1, id2 }, Array.Empty<DomainId>())
};
await sut.EnrichAsync(requestContext, contents, schemaProvider);
await sut.EnrichAsync(requestContext, contents, schemaProvider, default);
Assert.NotNull(contents[0].ReferenceData);
A.CallTo(() => assetQuery.QueryAsync(
A<Context>.That.Matches(x => x.ShouldSkipAssetEnrichment() && x.ShouldSkipTotal()), null, A<Q>.That.HasIds(id1)))
A<Context>.That.Matches(x => x.ShouldSkipAssetEnrichment() && x.ShouldSkipTotal()), null, A<Q>.That.HasIds(id1), A<CancellationToken>._))
.MustHaveHappened();
}

25
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/ResolveReferencesTests.cs

@ -7,6 +7,7 @@
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using FakeItEasy;
using Squidex.Domain.Apps.Core;
@ -102,10 +103,10 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
};
A.CallTo(() => contentQuery.QueryAsync(
A<Context>.That.Matches(x => x.ShouldSkipContentEnrichment() && x.ShouldSkipTotal()), A<Q>.That.HasIds(ref1_1.Id, ref1_2.Id, ref2_1.Id, ref2_2.Id)))
A<Context>.That.Matches(x => x.ShouldSkipContentEnrichment() && x.ShouldSkipTotal()), A<Q>.That.HasIds(ref1_1.Id, ref1_2.Id, ref2_1.Id, ref2_2.Id), A<CancellationToken>._))
.Returns(ResultList.CreateFrom(4, ref1_1, ref1_2, ref2_1, ref2_2));
await sut.EnrichAsync(requestContext, contents, schemaProvider);
await sut.EnrichAsync(requestContext, contents, schemaProvider, default);
A.CallTo(() => requestCache.AddDependency(DomainId.Combine(appId, refSchemaId1.Id), 0))
.MustHaveHappened();
@ -141,10 +142,10 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
};
A.CallTo(() => contentQuery.QueryAsync(
A<Context>.That.Matches(x => x.ShouldSkipContentEnrichment() && x.ShouldSkipTotal()), A<Q>.That.HasIds(ref1_1.Id, ref1_2.Id, ref2_1.Id, ref2_2.Id)))
A<Context>.That.Matches(x => x.ShouldSkipContentEnrichment() && x.ShouldSkipTotal()), A<Q>.That.HasIds(ref1_1.Id, ref1_2.Id, ref2_1.Id, ref2_2.Id), A<CancellationToken>._))
.Returns(ResultList.CreateFrom(4, ref1_1, ref1_2, ref2_1, ref2_2));
await sut.EnrichAsync(requestContext, contents, schemaProvider);
await sut.EnrichAsync(requestContext, contents, schemaProvider, default);
Assert.Equal(
new ContentData()
@ -194,10 +195,10 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
};
A.CallTo(() => contentQuery.QueryAsync(
A<Context>.That.Matches(x => x.ShouldSkipContentEnrichment() && x.ShouldSkipTotal()), A<Q>.That.HasIds(ref1_1.Id, ref1_2.Id, ref2_1.Id, ref2_2.Id)))
A<Context>.That.Matches(x => x.ShouldSkipContentEnrichment() && x.ShouldSkipTotal()), A<Q>.That.HasIds(ref1_1.Id, ref1_2.Id, ref2_1.Id, ref2_2.Id), A<CancellationToken>._))
.Returns(ResultList.CreateFrom(4, ref1_1, ref1_2, ref2_1, ref2_2));
await sut.EnrichAsync(requestContext, contents, schemaProvider);
await sut.EnrichAsync(requestContext, contents, schemaProvider, default);
Assert.Equal(
new ContentData()
@ -242,11 +243,11 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
var ctx = new Context(Mocks.ApiUser(), Mocks.App(appId));
await sut.EnrichAsync(ctx, contents, schemaProvider);
await sut.EnrichAsync(ctx, contents, schemaProvider, default);
Assert.Null(contents[0].ReferenceData);
A.CallTo(() => contentQuery.QueryAsync(A<Context>._, A<Q>._))
A.CallTo(() => contentQuery.QueryAsync(A<Context>._, A<Q>._, A<CancellationToken>._))
.MustNotHaveHappened();
}
@ -260,11 +261,11 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
var ctx = new Context(Mocks.FrontendUser(), Mocks.App(appId)).Clone(b => b.WithoutContentEnrichment(true));
await sut.EnrichAsync(ctx, contents, schemaProvider);
await sut.EnrichAsync(ctx, contents, schemaProvider, default);
Assert.Null(contents[0].ReferenceData);
A.CallTo(() => contentQuery.QueryAsync(A<Context>._, A<Q>._))
A.CallTo(() => contentQuery.QueryAsync(A<Context>._, A<Q>._, A<CancellationToken>._))
.MustNotHaveHappened();
}
@ -276,11 +277,11 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
CreateContent(Array.Empty<DomainId>(), Array.Empty<DomainId>())
};
await sut.EnrichAsync(requestContext, contents, schemaProvider);
await sut.EnrichAsync(requestContext, contents, schemaProvider, default);
Assert.NotNull(contents[0].ReferenceData);
A.CallTo(() => contentQuery.QueryAsync(A<Context>._, A<Q>._))
A.CallTo(() => contentQuery.QueryAsync(A<Context>._, A<Q>._, A<CancellationToken>._))
.MustNotHaveHappened();
}

15
backend/tests/Squidex.Domain.Apps.Entities.Tests/Contents/Queries/ScriptContentTests.cs

@ -5,6 +5,7 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Threading;
using System.Threading.Tasks;
using FakeItEasy;
using Squidex.Domain.Apps.Core.Contents;
@ -63,9 +64,9 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
var content = new ContentEntity { SchemaId = schemaId };
await sut.EnrichAsync(ctx, new[] { content }, schemaProvider);
await sut.EnrichAsync(ctx, new[] { content }, schemaProvider, default);
A.CallTo(() => scriptEngine.TransformAsync(A<ScriptVars>._, A<string>._, ScriptOptions()))
A.CallTo(() => scriptEngine.TransformAsync(A<ScriptVars>._, A<string>._, ScriptOptions(), A<CancellationToken>._))
.MustNotHaveHappened();
}
@ -76,9 +77,9 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
var content = new ContentEntity { SchemaId = schemaWithScriptId };
await sut.EnrichAsync(ctx, new[] { content }, schemaProvider);
await sut.EnrichAsync(ctx, new[] { content }, schemaProvider, default);
A.CallTo(() => scriptEngine.TransformAsync(A<ScriptVars>._, A<string>._, ScriptOptions()))
A.CallTo(() => scriptEngine.TransformAsync(A<ScriptVars>._, A<string>._, ScriptOptions(), A<CancellationToken>._))
.MustNotHaveHappened();
}
@ -91,10 +92,10 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
var content = new ContentEntity { SchemaId = schemaWithScriptId, Data = oldData };
A.CallTo(() => scriptEngine.TransformAsync(A<ScriptVars>._, "my-query", ScriptOptions()))
A.CallTo(() => scriptEngine.TransformAsync(A<ScriptVars>._, "my-query", ScriptOptions(), A<CancellationToken>._))
.Returns(new ContentData());
await sut.EnrichAsync(ctx, new[] { content }, schemaProvider);
await sut.EnrichAsync(ctx, new[] { content }, schemaProvider, default);
Assert.NotSame(oldData, content.Data);
@ -104,7 +105,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.Queries
ReferenceEquals(x.Data, oldData) &&
x.ContentId == content.Id),
"my-query",
ScriptOptions()))
ScriptOptions(), A<CancellationToken>._))
.MustHaveHappened();
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save