Browse Source

Performance improvements.

pull/492/head
Sebastian 6 years ago
parent
commit
976fbf87d4
  1. 9
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentCollectionAll.cs
  2. 9
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentCollectionPublished.cs
  3. 9
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentEntity.cs
  4. 9
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository.cs
  5. 6
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/MongoContentRepository_SnapshotStore.cs
  6. 32
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Operations/DataConverter.cs
  7. 9
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Operations/QueryContent.cs
  8. 9
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Operations/QueryContentsByIds.cs
  9. 9
      backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Operations/QueryContentsByQuery.cs
  10. 58
      backend/src/Squidex.Domain.Apps.Entities/Contents/Text/Extensions.cs
  11. 17
      backend/src/Squidex.Infrastructure.Azure/EventSourcing/StreamPosition.cs
  12. 2
      backend/src/Squidex.Infrastructure.MongoDb/EventSourcing/StreamPosition.cs
  13. 4
      backend/src/Squidex.Infrastructure/Json/Newtonsoft/NamedGuidIdConverter.cs
  14. 4
      backend/src/Squidex.Infrastructure/Json/Newtonsoft/NamedLongIdConverter.cs
  15. 4
      backend/src/Squidex.Infrastructure/Json/Newtonsoft/NamedStringIdConverter.cs

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

@ -18,7 +18,6 @@ using Squidex.Domain.Apps.Entities.Contents.Text;
using Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations;
using Squidex.Domain.Apps.Entities.Schemas;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Json;
using Squidex.Infrastructure.Log;
using Squidex.Infrastructure.MongoDb;
using Squidex.Infrastructure.Queries;
@ -33,12 +32,12 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
private readonly QueryIdsAsync queryIdsAsync;
private readonly QueryScheduledContents queryScheduledItems;
public MongoContentCollectionAll(IMongoDatabase database, IAppProvider appProvider, ITextIndex indexer, IJsonSerializer serializer)
public MongoContentCollectionAll(IMongoDatabase database, IAppProvider appProvider, ITextIndex indexer, DataConverter converter)
: base(database)
{
queryContentAsync = new QueryContent(serializer);
queryContentsById = new QueryContentsByIds(serializer, appProvider);
queryContentsByQuery = new QueryContentsByQuery(serializer, indexer);
queryContentAsync = new QueryContent(converter);
queryContentsById = new QueryContentsByIds(converter, appProvider);
queryContentsByQuery = new QueryContentsByQuery(converter, indexer);
queryIdsAsync = new QueryIdsAsync(appProvider);
queryScheduledItems = new QueryScheduledContents();
}

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

@ -17,7 +17,6 @@ using Squidex.Domain.Apps.Entities.Contents.Text;
using Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations;
using Squidex.Domain.Apps.Entities.Schemas;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Json;
using Squidex.Infrastructure.Log;
using Squidex.Infrastructure.MongoDb;
using Squidex.Infrastructure.Queries;
@ -31,12 +30,12 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
private readonly QueryContentsByQuery queryContentsByQuery;
private readonly QueryIdsAsync queryIdsAsync;
public MongoContentCollectionPublished(IMongoDatabase database, IAppProvider appProvider, ITextIndex indexer, IJsonSerializer serializer)
public MongoContentCollectionPublished(IMongoDatabase database, IAppProvider appProvider, ITextIndex indexer, DataConverter converter)
: base(database)
{
queryContentAsync = new QueryContent(serializer);
queryContentsById = new QueryContentsByIds(serializer, appProvider);
queryContentsByQuery = new QueryContentsByQuery(serializer, indexer);
queryContentAsync = new QueryContent(converter);
queryContentsById = new QueryContentsByIds(converter, appProvider);
queryContentsByQuery = new QueryContentsByQuery(converter, indexer);
queryIdsAsync = new QueryIdsAsync(appProvider);
}

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

@ -16,7 +16,6 @@ using Squidex.Domain.Apps.Core.Schemas;
using Squidex.Domain.Apps.Entities.Contents;
using Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Json;
using Squidex.Infrastructure.MongoDb;
namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
@ -105,16 +104,16 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
get { return data; }
}
public void LoadData(NamedContentData data, Schema schema, IJsonSerializer serializer)
public void LoadData(NamedContentData data, Schema schema, DataConverter converter)
{
ReferencedIds = data.GetReferencedIds(schema);
DataByIds = data.ToMongoModel(schema, serializer);
DataByIds = converter.ToMongoModel(data, schema);
}
public void ParseData(Schema schema, IJsonSerializer serializer)
public void ParseData(Schema schema, DataConverter converter)
{
data = DataByIds.FromMongoModel(schema, serializer);
data = converter.FromMongoModel(DataByIds, schema);
}
}
}

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

@ -15,6 +15,7 @@ using Squidex.Domain.Apps.Entities.Apps;
using Squidex.Domain.Apps.Entities.Contents;
using Squidex.Domain.Apps.Entities.Contents.Repositories;
using Squidex.Domain.Apps.Entities.Contents.Text;
using Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations;
using Squidex.Domain.Apps.Entities.Schemas;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Json;
@ -25,7 +26,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
public partial class MongoContentRepository : IContentRepository, IInitializable
{
private readonly IAppProvider appProvider;
private readonly IJsonSerializer serializer;
private readonly DataConverter converter;
private readonly MongoContentCollectionAll collectionAll;
private readonly MongoContentCollectionPublished collectionPublished;
@ -41,10 +42,10 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
this.appProvider = appProvider;
this.serializer = serializer;
converter = new DataConverter(serializer);
collectionAll = new MongoContentCollectionAll(database, appProvider, indexer, serializer);
collectionPublished = new MongoContentCollectionPublished(database, appProvider, indexer, serializer);
collectionAll = new MongoContentCollectionAll(database, appProvider, indexer, converter);
collectionPublished = new MongoContentCollectionPublished(database, appProvider, indexer, converter);
}
public async Task InitializeAsync(CancellationToken ct = default)

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

@ -53,7 +53,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
{
var schema = await GetSchemaAsync(contentEntity.IndexedAppId, contentEntity.IndexedSchemaId);
contentEntity.ParseData(schema.SchemaDef, serializer);
contentEntity.ParseData(schema.SchemaDef, converter);
return (SimpleMapper.Map(contentEntity, new ContentState()), contentEntity.Version);
}
@ -109,7 +109,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
content.ScheduleJob = value.ScheduleJob;
content.NewStatus = value.NewStatus;
content.LoadData(value.Data, schema.SchemaDef, serializer);
content.LoadData(value.Data, schema.SchemaDef, converter);
await collectionAll.UpsertVersionedAsync(content.Id, oldVersion, content);
}
@ -127,7 +127,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents
content.ScheduleJob = null;
content.NewStatus = null;
content.LoadData(value.CurrentVersion.Data, schema.SchemaDef, serializer);
content.LoadData(value.CurrentVersion.Data, schema.SchemaDef, converter);
await collectionPublished.UpsertVersionedAsync(content.Id, oldVersion, content);
}

32
backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Operations/Extensions.cs → backend/src/Squidex.Domain.Apps.Entities.MongoDb/Contents/Operations/DataConverter.cs

@ -12,24 +12,38 @@ using Squidex.Infrastructure.Json;
namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
{
public static class Extensions
public sealed class DataConverter
{
public static NamedContentData FromMongoModel(this IdContentData result, Schema schema, IJsonSerializer serializer)
private readonly FieldConverter[] decodeJsonConverters;
private readonly FieldConverter[] encodeJsonConverters;
public DataConverter(IJsonSerializer serializer)
{
return result.ConvertId2Name(schema,
decodeJsonConverters = new[]
{
FieldConverters.ForValues(
ValueConverters.DecodeJson(serializer)),
FieldConverters.ForNestedId2Name(
ValueConverters.DecodeJson(serializer)));
}
ValueConverters.DecodeJson(serializer))
};
public static IdContentData ToMongoModel(this NamedContentData result, Schema schema, IJsonSerializer serializer)
{
return result.ConvertName2Id(schema,
encodeJsonConverters = new[]
{
FieldConverters.ForValues(
ValueConverters.EncodeJson(serializer)),
FieldConverters.ForNestedName2Id(
ValueConverters.EncodeJson(serializer)));
ValueConverters.EncodeJson(serializer))
};
}
public NamedContentData FromMongoModel(IdContentData result, Schema schema)
{
return result.ConvertId2Name(schema, decodeJsonConverters);
}
public IdContentData ToMongoModel(NamedContentData result, Schema schema)
{
return result.ConvertName2Id(schema, encodeJsonConverters);
}
}
}

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

@ -11,17 +11,16 @@ using MongoDB.Driver;
using Squidex.Domain.Apps.Entities.Contents;
using Squidex.Domain.Apps.Entities.Schemas;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Json;
namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
{
internal sealed class QueryContent : OperationBase
{
private readonly IJsonSerializer serializer;
private readonly DataConverter converter;
public QueryContent(IJsonSerializer serializer)
public QueryContent(DataConverter converter)
{
this.serializer = serializer;
this.converter = converter;
}
public async Task<IContentEntity?> DoAsync(ISchemaEntity schema, Guid id)
@ -39,7 +38,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
return null;
}
contentEntity?.ParseData(schema.SchemaDef, serializer);
contentEntity?.ParseData(schema.SchemaDef, converter);
}
return contentEntity;

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

@ -13,18 +13,17 @@ using MongoDB.Driver;
using Squidex.Domain.Apps.Entities.Contents;
using Squidex.Domain.Apps.Entities.Schemas;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Json;
namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
{
internal sealed class QueryContentsByIds : OperationBase
{
private readonly IJsonSerializer serializer;
private readonly DataConverter converter;
private readonly IAppProvider appProvider;
public QueryContentsByIds(IJsonSerializer serializer, IAppProvider appProvider)
public QueryContentsByIds(DataConverter converter, IAppProvider appProvider)
{
this.serializer = serializer;
this.converter = converter;
this.appProvider = appProvider;
}
@ -44,7 +43,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
{
if (contentSchemas.TryGetValue(contentEntity.IndexedSchemaId, out var contentSchema))
{
contentEntity.ParseData(contentSchema.SchemaDef, serializer);
contentEntity.ParseData(contentSchema.SchemaDef, converter);
result.Add((contentEntity, contentSchema));
}

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

@ -15,7 +15,6 @@ using Squidex.Domain.Apps.Entities.Contents;
using Squidex.Domain.Apps.Entities.Contents.Text;
using Squidex.Domain.Apps.Entities.Schemas;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Json;
using Squidex.Infrastructure.MongoDb.Queries;
using Squidex.Infrastructure.Queries;
@ -23,12 +22,12 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
{
internal sealed class QueryContentsByQuery : OperationBase
{
private readonly IJsonSerializer serializer;
private readonly DataConverter converter;
private readonly ITextIndex indexer;
public QueryContentsByQuery(IJsonSerializer serializer, ITextIndex indexer)
public QueryContentsByQuery(DataConverter converter, ITextIndex indexer)
{
this.serializer = serializer;
this.converter = converter;
this.indexer = indexer;
}
@ -83,7 +82,7 @@ namespace Squidex.Domain.Apps.Entities.MongoDb.Contents.Operations
foreach (var entity in contentItems.Result)
{
entity.ParseData(schema.SchemaDef, serializer);
entity.ParseData(schema.SchemaDef, converter);
}
return ResultList.Create<IContentEntity>(contentCount.Result, contentItems.Result);

58
backend/src/Squidex.Domain.Apps.Entities/Contents/Text/Extensions.cs

@ -5,17 +5,18 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Extensions.ObjectPool;
using Squidex.Domain.Apps.Core.Contents;
using Squidex.Infrastructure;
using Squidex.Infrastructure.Json.Objects;
namespace Squidex.Domain.Apps.Entities.Contents.Text
{
public static class Extensions
{
private static readonly ObjectPool<StringBuilder> Pool = new DefaultObjectPool<StringBuilder>(new StringBuilderPooledObjectPolicy());
public static Dictionary<string, string> ToTexts(this NamedContentData data)
{
var result = new Dictionary<string, string>();
@ -24,63 +25,68 @@ namespace Squidex.Domain.Apps.Entities.Contents.Text
{
var languages = new Dictionary<string, StringBuilder>();
void AppendText(string language, string text)
{
if (!string.IsNullOrWhiteSpace(text))
{
var sb = languages.GetOrAddNew(language);
if (sb.Length > 0)
{
sb.Append(" ");
}
sb.Append(text);
}
}
foreach (var value in data.Values)
{
if (value != null)
{
foreach (var (key, jsonValue) in value)
{
var appendText = new Action<string>(text => AppendText(key, text));
AppendJsonText(jsonValue, appendText);
AppendJsonText(languages, key, jsonValue);
}
}
}
foreach (var (key, value) in languages)
foreach (var (key, stringBuilder) in languages)
{
result[key] = value.ToString();
result[key] = stringBuilder.ToString();
Pool.Return(stringBuilder);
}
}
return result;
}
private static void AppendJsonText(IJsonValue value, Action<string> appendText)
private static void AppendJsonText(Dictionary<string, StringBuilder> languages, string language, IJsonValue value)
{
if (value.Type == JsonValueType.String)
{
appendText(value.ToString());
AppendText(languages, language, value.ToString());
}
else if (value is JsonArray array)
{
foreach (var item in array)
{
AppendJsonText(item, appendText);
AppendJsonText(languages, language, item);
}
}
else if (value is JsonObject obj)
{
foreach (var item in obj.Values)
{
AppendJsonText(item, appendText);
AppendJsonText(languages, language, item);
}
}
}
private static void AppendText(Dictionary<string, StringBuilder> languages, string language, string text)
{
if (!string.IsNullOrWhiteSpace(text))
{
if (!languages.TryGetValue(language, out var stringBuilder))
{
stringBuilder = Pool.Get();
languages[language] = stringBuilder;
}
if (stringBuilder.Length > 0)
{
stringBuilder.Append(" ");
}
stringBuilder.Append(text);
}
}
}
}

17
backend/src/Squidex.Infrastructure.Azure/EventSourcing/StreamPosition.cs

@ -5,6 +5,8 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System.Text;
namespace Squidex.Infrastructure.EventSourcing
{
internal sealed class StreamPosition
@ -30,14 +32,15 @@ namespace Squidex.Infrastructure.EventSourcing
public static implicit operator string(StreamPosition position)
{
var parts = new object[]
{
position.Timestamp,
position.CommitOffset,
position.CommitSize
};
var sb = new StringBuilder(20);
sb.Append(position.Timestamp);
sb.Append("-");
sb.Append(position.CommitOffset);
sb.Append("-");
sb.Append(position.CommitSize);
return string.Join("-", parts);
return sb.ToString();
}
public static implicit operator StreamPosition(string? position)

2
backend/src/Squidex.Infrastructure.MongoDb/EventSourcing/StreamPosition.cs

@ -35,7 +35,7 @@ namespace Squidex.Infrastructure.EventSourcing
public static implicit operator string(StreamPosition position)
{
var sb = new StringBuilder();
var sb = new StringBuilder(20);
sb.Append(position.Timestamp.Timestamp);
sb.Append("-");

4
backend/src/Squidex.Infrastructure/Json/Newtonsoft/NamedGuidIdConverter.cs

@ -12,6 +12,8 @@ namespace Squidex.Infrastructure.Json.Newtonsoft
{
public sealed class NamedGuidIdConverter : JsonClassConverter<NamedId<Guid>>
{
private static readonly Parser<Guid> Parser = Guid.TryParse;
protected override void WriteValue(JsonWriter writer, NamedId<Guid> value, JsonSerializer serializer)
{
writer.WriteValue(value.ToString());
@ -21,7 +23,7 @@ namespace Squidex.Infrastructure.Json.Newtonsoft
{
var value = serializer.Deserialize<string>(reader)!;
if (!NamedId<Guid>.TryParse(value, Guid.TryParse, out var result))
if (!NamedId<Guid>.TryParse(value, Parser, out var result))
{
throw new JsonException("Named id must have more than 2 parts divided by commata.");
}

4
backend/src/Squidex.Infrastructure/Json/Newtonsoft/NamedLongIdConverter.cs

@ -12,6 +12,8 @@ namespace Squidex.Infrastructure.Json.Newtonsoft
{
public sealed class NamedLongIdConverter : JsonClassConverter<NamedId<long>>
{
private static readonly Parser<long> Parser = long.TryParse;
protected override void WriteValue(JsonWriter writer, NamedId<long> value, JsonSerializer serializer)
{
writer.WriteValue(value.ToString());
@ -21,7 +23,7 @@ namespace Squidex.Infrastructure.Json.Newtonsoft
{
var value = serializer.Deserialize<string>(reader)!;
if (!NamedId<long>.TryParse(value, long.TryParse, out var result))
if (!NamedId<long>.TryParse(value, Parser, out var result))
{
throw new JsonException("Named id must have at least 2 parts divided by commata.");
}

4
backend/src/Squidex.Infrastructure/Json/Newtonsoft/NamedStringIdConverter.cs

@ -12,6 +12,8 @@ namespace Squidex.Infrastructure.Json.Newtonsoft
{
public sealed class NamedStringIdConverter : JsonClassConverter<NamedId<string>>
{
private static readonly Parser<string> Parser = ParseString;
protected override void WriteValue(JsonWriter writer, NamedId<string> value, JsonSerializer serializer)
{
writer.WriteValue(value.ToString());
@ -21,7 +23,7 @@ namespace Squidex.Infrastructure.Json.Newtonsoft
{
var value = serializer.Deserialize<string>(reader)!;
if (!NamedId<string>.TryParse(value, ParseString, out var result))
if (!NamedId<string>.TryParse(value, Parser, out var result))
{
throw new JsonException("Named id must have at least 2 parts divided by commata.");
}

Loading…
Cancel
Save