Browse Source

Optimize memory usage by copying same field values to new data and fix parsing error with geojson.

pull/786/head
Sebastian 4 years ago
parent
commit
acb2ca2779
  1. 67
      backend/src/Squidex.Domain.Apps.Core.Model/Contents/ContentData.cs
  2. 4
      backend/src/Squidex.Domain.Apps.Core.Model/Contents/GeoJsonValue.cs
  3. 29
      backend/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/ContentConverter.cs
  4. 16
      backend/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/FieldConverters.cs
  5. 10
      backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/ContentDomainObject.State.cs
  6. 50
      backend/tests/Squidex.Domain.Apps.Core.Tests/Model/Contents/ContentDataTests.cs

67
backend/src/Squidex.Domain.Apps.Core.Model/Contents/ContentData.cs

@ -38,6 +38,49 @@ namespace Squidex.Domain.Apps.Core.Contents
return this; return this;
} }
public ContentData UseSameFields(ContentData? other)
{
if (other == null || other.Count == 0)
{
return this;
}
foreach (var (fieldName, fieldData) in this.ToList())
{
if (fieldData == null)
{
continue;
}
if (!other.TryGetValue(fieldName, out var otherField) || otherField == null)
{
continue;
}
if (otherField.Equals(fieldData))
{
this[fieldName] = otherField;
}
else
{
foreach (var (language, value) in fieldData.ToList())
{
if (!otherField.TryGetValue(language, out var otherValue) || otherValue == null)
{
continue;
}
if (otherValue.Equals(value))
{
fieldData[language] = otherValue;
}
}
}
}
return this;
}
private static ContentData MergeTo(ContentData target, params ContentData[] sources) private static ContentData MergeTo(ContentData target, params ContentData[] sources)
{ {
Guard.NotEmpty(sources, nameof(sources)); Guard.NotEmpty(sources, nameof(sources));
@ -49,19 +92,23 @@ namespace Squidex.Domain.Apps.Core.Contents
foreach (var source in sources) foreach (var source in sources)
{ {
foreach (var (key, contentFieldData) in source) foreach (var (fieldName, sourceFieldData) in source)
{ {
if (contentFieldData != null) if (sourceFieldData == null)
{ {
var fieldValue = target.GetOrAdd(key, _ => new ContentFieldData()); continue;
}
if (fieldValue != null) var targetFieldData = target.GetOrAdd(fieldName, _ => new ContentFieldData());
{
foreach (var (fieldName, value) in contentFieldData) if (targetFieldData == null)
{ {
fieldValue[fieldName] = value; continue;
} }
}
foreach (var (partition, value) in sourceFieldData)
{
targetFieldData[partition] = value;
} }
} }
} }

4
backend/src/Squidex.Domain.Apps.Core.Model/Contents/GeoJsonValue.cs

@ -22,7 +22,7 @@ namespace Squidex.Domain.Apps.Core.Contents
Guard.NotNull(serializer, nameof(serializer)); Guard.NotNull(serializer, nameof(serializer));
Guard.NotNull(value, nameof(value)); Guard.NotNull(value, nameof(value));
geoJSON = null!; geoJSON = null;
if (value is JsonObject obj) if (value is JsonObject obj)
{ {
@ -42,6 +42,8 @@ namespace Squidex.Domain.Apps.Core.Contents
} }
geoJSON = new Point(new Position(lat.Value, lon.Value)); geoJSON = new Point(new Position(lat.Value, lon.Value));
return GeoJsonParseResult.Success;
} }
return GeoJsonParseResult.InvalidValue; return GeoJsonParseResult.InvalidValue;

29
backend/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/ContentConverter.cs

@ -19,14 +19,19 @@ namespace Squidex.Domain.Apps.Core.ConvertContent
var result = new ContentData(content.Count); var result = new ContentData(content.Count);
foreach (var (fieldName, data) in content) if (converters == null || converters.Length == 0)
{ {
if (data == null || !schema.FieldsByName.TryGetValue(fieldName, out var field)) return result;
}
foreach (var (fieldName, fieldData) in content)
{
if (fieldData == null || !schema.FieldsByName.TryGetValue(fieldName, out var field))
{ {
continue; continue;
} }
ContentFieldData? newData = data; ContentFieldData? newData = fieldData;
if (newData != null) if (newData != null)
{ {
@ -44,16 +49,18 @@ namespace Squidex.Domain.Apps.Core.ConvertContent
private static ContentFieldData? ConvertData(IRootField field, ContentFieldData data, FieldConverter[] converters) private static ContentFieldData? ConvertData(IRootField field, ContentFieldData data, FieldConverter[] converters)
{ {
if (converters != null) if (converters == null || converters.Length == 0)
{ {
for (var i = 0; i < converters.Length; i++) return data;
{ }
data = converters[i](data!, field)!;
for (var i = 0; i < converters.Length; i++)
{
data = converters[i](data!, field)!;
if (data == null) if (data == null)
{ {
break; break;
}
} }
} }

16
backend/src/Squidex.Domain.Apps.Core.Operations/ConvertContent/FieldConverters.cs

@ -119,15 +119,17 @@ namespace Squidex.Domain.Apps.Core.ConvertContent
{ {
foreach (var languageCode in languages.AllKeys) foreach (var languageCode in languages.AllKeys)
{ {
if (!data.TryGetNonNull(languageCode, out _)) if (data.TryGetNonNull(languageCode, out _))
{ {
foreach (var fallback in languages.GetPriorities(languageCode)) continue;
}
foreach (var fallback in languages.GetPriorities(languageCode))
{
if (data.TryGetNonNull(fallback, out var value))
{ {
if (data.TryGetNonNull(fallback, out var value)) data[languageCode] = value;
{ break;
data[languageCode] = value;
break;
}
} }
} }
} }

10
backend/src/Squidex.Domain.Apps.Entities/Contents/DomainObject/ContentDomainObject.State.cs

@ -71,7 +71,9 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
case ContentDraftCreated e: case ContentDraftCreated e:
{ {
NewVersion = new ContentVersion(e.Status, e.MigratedData ?? CurrentVersion.Data); var newData = e.MigratedData?.UseSameFields(Data) ?? CurrentVersion.Data;
NewVersion = new ContentVersion(e.Status, newData);
ScheduleJob = null; ScheduleJob = null;
@ -95,7 +97,7 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
{ {
if (e.Status == Status.Published) if (e.Status == Status.Published)
{ {
CurrentVersion = new ContentVersion(e.Status, NewVersion.Data); CurrentVersion = new ContentVersion(e.Status, NewVersion.Data.UseSameFields(Data));
NewVersion = null; NewVersion = null;
} }
@ -130,11 +132,11 @@ namespace Squidex.Domain.Apps.Entities.Contents.DomainObject
{ {
if (NewVersion != null) if (NewVersion != null)
{ {
NewVersion = NewVersion.WithData(e.Data); NewVersion = NewVersion.WithData(e.Data.UseSameFields(Data));
} }
else else
{ {
CurrentVersion = CurrentVersion.WithData(e.Data); CurrentVersion = CurrentVersion.WithData(e.Data.UseSameFields(Data));
} }
break; break;

50
backend/tests/Squidex.Domain.Apps.Core.Tests/Model/Contents/ContentDataTests.cs

@ -159,5 +159,55 @@ namespace Squidex.Domain.Apps.Core.Model.Contents
Assert.NotSame(value, source[key]); Assert.NotSame(value, source[key]);
} }
} }
[Fact]
public void Should_copy_fields_from_other_data_if_they_are_equal()
{
var oldData =
new ContentData()
.AddField("field1",
new ContentFieldData()
.AddInvariant(1))
.AddField("field2",
new ContentFieldData()
.AddInvariant(2));
var newData =
new ContentData()
.AddField("field1",
new ContentFieldData()
.AddInvariant(1))
.AddField("field2",
new ContentFieldData()
.AddInvariant(3));
newData.UseSameFields(oldData);
Assert.Same(newData["field1"], oldData["field1"]);
Assert.NotSame(newData["field2"], oldData["field2"]);
}
[Fact]
public void Should_copy_field_values_from_other_data_if_they_are_equal()
{
var oldData =
new ContentData()
.AddField("field1",
new ContentFieldData()
.AddLocalized("en", 1)
.AddLocalized("de", 2));
var newData =
new ContentData()
.AddField("field1",
new ContentFieldData()
.AddLocalized("en", 1)
.AddLocalized("de", 3));
newData.UseSameFields(oldData);
Assert.Same(newData["field1"]!["en"], oldData["field1"]!["en"]);
Assert.NotSame(newData["field1"]!["de"], oldData["field1"]!["de"]);
Assert.NotSame(newData["field1"], oldData["field1"]);
}
} }
} }

Loading…
Cancel
Save