Browse Source

Improve counter performance. (#1021)

pull/1023/head
Sebastian Stehle 3 years ago
committed by GitHub
parent
commit
37c046c989
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 10
      backend/src/Migrations/MigrationPath.cs
  2. 66
      backend/src/Migrations/Migrations/MongoDb/CopyRuleStatistics.cs
  3. 12
      backend/src/Squidex.Domain.Apps.Entities/Billing/UsageGate.Rules.cs
  4. 7
      backend/src/Squidex.Infrastructure/UsageTracking/BackgroundUsageTracker.cs
  5. 9
      backend/src/Squidex.Infrastructure/UsageTracking/Counters.cs
  6. 3
      backend/src/Squidex/Config/Domain/StoreServices.cs
  7. 2
      frontend/src/app/framework/angular/forms/editors/code-editor.component.ts

10
backend/src/Migrations/MigrationPath.cs

@ -15,7 +15,7 @@ namespace Migrations;
public sealed class MigrationPath : IMigrationPath
{
private const int CurrentVersion = 25;
private const int CurrentVersion = 26;
private readonly IServiceProvider serviceProvider;
public MigrationPath(IServiceProvider serviceProvider)
@ -114,10 +114,16 @@ public sealed class MigrationPath : IMigrationPath
}
}
// Version 13: Json refactoring
// Version 13: Json refactoring.
if (version < 13)
{
yield return serviceProvider.GetRequiredService<ConvertRuleEventsJson>();
}
// Version 27: New rule statistics using normal usage collection.
if (version < 26)
{
yield return serviceProvider.GetRequiredService<CopyRuleStatistics>();
}
}
}

66
backend/src/Migrations/Migrations/MongoDb/CopyRuleStatistics.cs

@ -0,0 +1,66 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Driver;
using Squidex.Domain.Apps.Entities.Rules;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Migrations;
using Squidex.Infrastructure.MongoDb;
namespace Migrations.Migrations.MongoDb;
public sealed class CopyRuleStatistics : IMigration
{
private readonly IMongoDatabase database;
private readonly IRuleUsageTracker ruleUsageTracker;
[BsonIgnoreExtraElements]
public class Document
{
public DomainId AppId { get; private set; }
public DomainId RuleId { get; private set; }
public int NumFailed { get; private set; }
public int NumSucceeded { get; private set; }
}
public CopyRuleStatistics(IMongoDatabase database, IRuleUsageTracker ruleUsageTracker)
{
this.database = database;
this.ruleUsageTracker = ruleUsageTracker;
}
public async Task UpdateAsync(
CancellationToken ct)
{
var collectionName = "RuleStatistics";
// Do not create the collection if not needed.
if (!await database.CollectionExistsAsync(collectionName, ct))
{
return;
}
var collection = database.GetCollection<Document>(collectionName);
await foreach (var document in collection.Find(new BsonDocument()).ToAsyncEnumerable(ct))
{
await ruleUsageTracker.TrackAsync(
document.AppId,
document.RuleId,
default,
0,
document.NumSucceeded,
document.NumFailed,
ct);
}
}
}

12
backend/src/Squidex.Domain.Apps.Entities/Billing/UsageGate.Rules.cs

@ -103,18 +103,26 @@ public sealed partial class UsageGate : IRuleUsageTracker
var tasks = new List<Task>
{
usageTracker.TrackAsync(date, appKey, ruleId.ToString(), counters, ct),
usageTracker.TrackAsync(SummaryDate, appKey, ruleId.ToString(), counters, ct)
};
if (date != default)
{
tasks.Add(usageTracker.TrackAsync(date, appKey, ruleId.ToString(), counters, ct));
}
var (_, _, teamId) = await GetPlanForAppAsync(appId, true, ct);
if (teamId != null)
{
var teamKey = TeamRulesKey(teamId.Value);
tasks.Add(usageTracker.TrackAsync(date, teamKey, appId.ToString(), counters, ct));
tasks.Add(usageTracker.TrackAsync(SummaryDate, teamKey, appId.ToString(), counters, ct));
if (date != default)
{
tasks.Add(usageTracker.TrackAsync(date, teamKey, appId.ToString(), counters, ct));
}
}
await Task.WhenAll(tasks);

7
backend/src/Squidex.Infrastructure/UsageTracking/BackgroundUsageTracker.cs

@ -116,9 +116,8 @@ public sealed class BackgroundUsageTracker : DisposableObjectBase, IUsageTracker
category = GetCategory(category);
#pragma warning disable MA0105 // Use the lambda parameters instead of using a closure
jobs.AddOrUpdate((key, category, date), counters, (k, p) => p.SumpUpCloned(counters));
#pragma warning restore MA0105 // Use the lambda parameters instead of using a closure
// Create a copy of the counters on add, so that we do not share it.
jobs.AddOrUpdate((key, category, date), (_, args) => new Counters(args), (_, v, args) => v.Merge(args), counters);
return Task.CompletedTask;
}
@ -191,7 +190,7 @@ public sealed class BackgroundUsageTracker : DisposableObjectBase, IUsageTracker
foreach (var usage in queried)
{
result.SumpUp(usage.Counters);
result.Merge(usage.Counters);
}
return result;

9
backend/src/Squidex.Infrastructure/UsageTracking/Counters.cs

@ -42,14 +42,7 @@ public sealed class Counters : Dictionary<string, double>
return (long)value;
}
public Counters SumpUpCloned(Counters counters)
{
var result = new Counters(this);
return result.SumpUp(counters);
}
public Counters SumpUp(Counters source)
public Counters Merge(Counters source)
{
foreach (var (key, value) in source)
{

3
backend/src/Squidex/Config/Domain/StoreServices.cs

@ -80,6 +80,9 @@ public static class StoreServices
services.AddTransientAs<ConvertOldSnapshotStores>()
.As<IMigration>();
services.AddTransientAs<CopyRuleStatistics>()
.As<IMigration>();
services.AddTransientAs(c => new DeleteContentCollections(GetDatabase(c, mongoContentDatabaseName)))
.As<IMigration>();

2
frontend/src/app/framework/angular/forms/editors/code-editor.component.ts

@ -294,6 +294,8 @@ export class CodeEditorComponent extends StatefulControlComponent<{}, any> imple
printMargin: !this.singleLine,
showGutter: !this.singleLine,
});
this.aceEditor.commands.bindKey('Enter|Shift-Enter', this.singleLine ? 'null' : undefined);
}
private setValue(value: string) {

Loading…
Cancel
Save