Skip to content

Commit

Permalink
asyncify serialization
Browse files Browse the repository at this point in the history
  • Loading branch information
adamhathcock committed Sep 26, 2024
1 parent 8ede2a4 commit 4454513
Show file tree
Hide file tree
Showing 13 changed files with 82 additions and 82 deletions.
2 changes: 1 addition & 1 deletion src/Speckle.Sdk/Api/Operations/Operations.Send.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ internal static async Task<string> SerializerSend(
CancellationToken cancellationToken = default
)
{
string obj = serializer.Serialize(value);
string obj = await serializer.Serialize(value).ConfigureAwait(false);
Task[] transportAwaits = serializer.WriteTransports.Select(t => t.WriteComplete()).ToArray();

cancellationToken.ThrowIfCancellationRequested();
Expand Down
4 changes: 2 additions & 2 deletions src/Speckle.Sdk/Api/Operations/Operations.Serialize.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ public partial class Operations
/// <param name="value">The object to serialise</param>
/// <param name="cancellationToken"></param>
/// <returns>A json string representation of the object.</returns>
public string Serialize(Base value, CancellationToken cancellationToken = default)
public async Task<string> Serialize(Base value, CancellationToken cancellationToken = default)
{
var serializer = new SpeckleObjectSerializer { CancellationToken = cancellationToken };
return serializer.Serialize(value);
return await serializer.Serialize(value).ConfigureAwait(false);
}

/// <remarks>
Expand Down
6 changes: 3 additions & 3 deletions src/Speckle.Sdk/Models/Base.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public class Base : DynamicBase, ISpeckleObject
private string _type;

/// <summary>
/// A speckle object's id is an unique hash based on its properties. <b>NOTE: this field will be null unless the object was deserialised from a source. Use the <see cref="GetId"/> function to get it.</b>
/// A speckle object's id is an unique hash based on its properties. <b>NOTE: this field will be null unless the object was deserialised from a source. Use the <see cref="GetIdAsync"/> function to get it.</b>
/// </summary>
[SchemaIgnore]
public virtual string id { get; set; }
Expand Down Expand Up @@ -70,13 +70,13 @@ public virtual string speckle_type
/// </remarks>
/// <param name="decompose">If <see langword="true"/>, will decompose the object in the process of hashing.</param>
/// <returns>the resulting id (hash)</returns>
public string GetId(bool decompose = false)
public async Task<string> GetIdAsync(bool decompose = false)
{
//TODO remove me
var transports = decompose ? [new MemoryTransport()] : Array.Empty<IWritableTransport>();
var serializer = new SpeckleObjectSerializer(transports);

string obj = serializer.Serialize(this);
string obj = await serializer.Serialize(this).ConfigureAwait(false);
return JObject.Parse(obj).GetValue(nameof(id))?.ToString() ?? string.Empty;
}

Expand Down
46 changes: 23 additions & 23 deletions src/Speckle.Sdk/Serialisation/SpeckleObjectSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public SpeckleObjectSerializer(
/// <exception cref="TransportException">Failed to save object in one or more <see cref="WriteTransports"/></exception>
/// <exception cref="SpeckleSerializeException">Failed to extract (pre-serialize) properties from the <paramref name="baseObj"/></exception>
/// <exception cref="OperationCanceledException">One or more <see cref="WriteTransports"/>'s cancellation token requested cancel</exception>
public string Serialize(Base baseObj)
public async ValueTask<string> Serialize(Base baseObj)
{
if (_isBusy)
{
Expand All @@ -84,8 +84,8 @@ public string Serialize(Base baseObj)
_isBusy = true;
try
{
var result = SerializeBase(baseObj, true).NotNull();
StoreObject(result.Id.NotNull(), result.Json);
var result = await SerializeBase(baseObj, true).NotNull().ConfigureAwait(false);
await StoreObject(result.Id.NotNull(), result.Json).ConfigureAwait(false);
return result.Json;
}
catch (Exception ex) when (!ex.IsFatal() && ex is not OperationCanceledException)
Expand All @@ -104,7 +104,7 @@ public string Serialize(Base baseObj)

// `Preserialize` means transforming all objects into the final form that will appear in json, with basic .net objects
// (primitives, lists and dictionaries with string keys)
private void SerializeProperty(
private async ValueTask SerializeProperty(
object? obj,
JsonWriter writer,
bool computeClosures = false,
Expand Down Expand Up @@ -146,10 +146,10 @@ private void SerializeProperty(
}
}
UpdateParentClosures(r.referencedId);
SerializeProperty(ret, writer);
await SerializeProperty(ret, writer).ConfigureAwait(false);
break;
case Base b:
var result = SerializeBase(b, computeClosures, inheritedDetachInfo);
var result = await SerializeBase(b, computeClosures, inheritedDetachInfo).ConfigureAwait(false);
if (result is not null)
{
writer.WriteRawValue(result.Json);
Expand All @@ -174,7 +174,7 @@ private void SerializeProperty(
}

writer.WritePropertyName(key);
SerializeProperty(kvp.Value, writer, inheritedDetachInfo: inheritedDetachInfo);
await SerializeProperty(kvp.Value, writer, inheritedDetachInfo: inheritedDetachInfo).ConfigureAwait(false);
}
writer.WriteEndObject();
}
Expand All @@ -184,7 +184,7 @@ private void SerializeProperty(
writer.WriteStartArray();
foreach (object? element in e)
{
SerializeProperty(element, writer, inheritedDetachInfo: inheritedDetachInfo);
await SerializeProperty(element, writer, inheritedDetachInfo: inheritedDetachInfo).ConfigureAwait(false);
}
writer.WriteEndArray();
}
Expand Down Expand Up @@ -231,7 +231,7 @@ private void SerializeProperty(
}
}

internal SerializationResult? SerializeBase(
internal async ValueTask<SerializationResult?> SerializeBase(
Base baseObj,
bool computeClosures = false,
PropertyAttributeInfo inheritedDetachInfo = default
Expand All @@ -252,7 +252,7 @@ private void SerializeProperty(

using var writer = new StringWriter();
using var jsonWriter = new JsonTextWriter(writer);
string id = SerializeBaseObject(baseObj, jsonWriter, closure);
string id = await SerializeBaseObject(baseObj, jsonWriter, closure).ConfigureAwait(false);
var json = writer.ToString();

if (computeClosures || inheritedDetachInfo.IsDetachable || baseObj is Blob)
Expand All @@ -264,19 +264,19 @@ private void SerializeProperty(

if (baseObj is Blob myBlob)
{
StoreBlob(myBlob);
await StoreBlob(myBlob).ConfigureAwait(false);
UpdateParentClosures($"blob:{id}");
return new(json, id);
}

if (inheritedDetachInfo.IsDetachable && WriteTransports.Count > 0)
{
StoreObject(id, json);
await StoreObject(id, json).ConfigureAwait(false);

ObjectReference objRef = new() { referencedId = id };
using var writer2 = new StringWriter();
using var jsonWriter2 = new JsonTextWriter(writer2);
SerializeProperty(objRef, jsonWriter2);
await SerializeProperty(objRef, jsonWriter2).ConfigureAwait(false);
var json2 = writer2.ToString();
UpdateParentClosures(id);

Expand Down Expand Up @@ -341,7 +341,7 @@ private void SerializeProperty(
return allProperties;
}

private string SerializeBaseObject(Base baseObj, JsonWriter writer, IReadOnlyDictionary<string, int> closure)
private async ValueTask<string> SerializeBaseObject(Base baseObj, JsonWriter writer, IReadOnlyDictionary<string, int> closure)
{
var allProperties = ExtractAllProperties(baseObj);

Expand All @@ -360,7 +360,7 @@ private string SerializeBaseObject(Base baseObj, JsonWriter writer, IReadOnlyDic
}

writer.WritePropertyName(prop.Key);
SerializeProperty(prop.Value.value, writer, prop.Value.info);
await SerializeProperty(prop.Value.value, writer, prop.Value.info).ConfigureAwait(false);
}

string id;
Expand Down Expand Up @@ -393,12 +393,12 @@ private string SerializeBaseObject(Base baseObj, JsonWriter writer, IReadOnlyDic
return id;
}

private void SerializeProperty(object? baseValue, JsonWriter jsonWriter, PropertyAttributeInfo detachInfo)
private async ValueTask SerializeProperty(object? baseValue, JsonWriter jsonWriter, PropertyAttributeInfo detachInfo)
{
// If there are no WriteTransports, keep everything attached.
if (WriteTransports.Count == 0)
{
SerializeProperty(baseValue, jsonWriter, inheritedDetachInfo: detachInfo);
await SerializeProperty(baseValue, jsonWriter, inheritedDetachInfo: detachInfo).ConfigureAwait(false);
return;
}

Expand All @@ -421,11 +421,11 @@ private void SerializeProperty(object? baseValue, JsonWriter jsonWriter, Propert
{
chunks.Add(crtChunk);
}
SerializeProperty(chunks, jsonWriter, inheritedDetachInfo: new PropertyAttributeInfo(true, false, 0, null));
await SerializeProperty(chunks, jsonWriter, inheritedDetachInfo: new PropertyAttributeInfo(true, false, 0, null)).ConfigureAwait(false);
return;
}

SerializeProperty(baseValue, jsonWriter, inheritedDetachInfo: detachInfo);
await SerializeProperty(baseValue, jsonWriter, inheritedDetachInfo: detachInfo).ConfigureAwait(false);
}

private void UpdateParentClosures(string objectId)
Expand Down Expand Up @@ -453,18 +453,18 @@ private static string ComputeId(string serialized)
return hash;
}

private void StoreObject(string objectId, string objectJson)
private async ValueTask StoreObject(string objectId, string objectJson)
{
_stopwatch.Stop();
foreach (var transport in WriteTransports)
{
transport.SaveObject(objectId, objectJson);
await transport.SaveObject(objectId, objectJson).ConfigureAwait(false);
}

_stopwatch.Start();
}

private void StoreBlob(Blob obj)
private async ValueTask StoreBlob(Blob obj)
{
bool hasBlobTransport = false;

Expand All @@ -475,7 +475,7 @@ private void StoreBlob(Blob obj)
if (transport is IBlobCapableTransport blobTransport)
{
hasBlobTransport = true;
blobTransport.SaveBlob(obj);
await blobTransport.SaveBlob(obj).ConfigureAwait(false);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ await dataSource
}

[Benchmark]
public string RunTest()
public async Task<string> RunTest()
{
var remote = new NullTransport();
SpeckleObjectSerializer sut = new([remote]);
var x = sut.Serialize(_testData);
var x = await sut.Serialize(_testData);
return x;
}
}
Expand Down
22 changes: 11 additions & 11 deletions tests/Speckle.Sdk.Tests.Unit/Api/Operations/ClosureTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,27 +56,27 @@ public async Task CorrectDecompositionTracking()
var test = await _operations.Receive(sendResult.rootObjId, localTransport: transport);

test.id.NotNull();
Assert.That(d1.GetId(true), Is.EqualTo(test.id));
Assert.That(await d1.GetIdAsync(true), Is.EqualTo(test.id));

var d1_ = NotNullExtensions.NotNull(JsonConvert.DeserializeObject<dynamic>(transport.Objects[d1.GetId(true)]));
var d2_ = NotNullExtensions.NotNull(JsonConvert.DeserializeObject<dynamic>(transport.Objects[d2.GetId(true)]));
var d3_ = NotNullExtensions.NotNull(JsonConvert.DeserializeObject<dynamic>(transport.Objects[d3.GetId(true)]));
var d4_ = JsonConvert.DeserializeObject<dynamic>(transport.Objects[d4.GetId(true)]);
var d5_ = JsonConvert.DeserializeObject<dynamic>(transport.Objects[d5.GetId(true)]);
var d1_ = NotNullExtensions.NotNull(JsonConvert.DeserializeObject<dynamic>(transport.Objects[await d1.GetIdAsync(true)]));
var d2_ = NotNullExtensions.NotNull(JsonConvert.DeserializeObject<dynamic>(transport.Objects[await d2.GetIdAsync(true)]));
var d3_ = NotNullExtensions.NotNull(JsonConvert.DeserializeObject<dynamic>(transport.Objects[await d3.GetIdAsync(true)]));
var d4_ = JsonConvert.DeserializeObject<dynamic>(transport.Objects[await d4.GetIdAsync(true)]);
var d5_ = JsonConvert.DeserializeObject<dynamic>(transport.Objects[await d5.GetIdAsync(true)]);

var depthOf_d5_in_d1 = int.Parse((string)d1_.__closure[d5.GetId(true)]);
var depthOf_d5_in_d1 = int.Parse((string)d1_.__closure[await d5.GetIdAsync(true)]);
Assert.That(depthOf_d5_in_d1, Is.EqualTo(1));

var depthOf_d4_in_d1 = int.Parse((string)d1_.__closure[d4.GetId(true)]);
var depthOf_d4_in_d1 = int.Parse((string)d1_.__closure[await d4.GetIdAsync(true)]);
Assert.That(depthOf_d4_in_d1, Is.EqualTo(3));

var depthOf_d5_in_d3 = int.Parse((string)d3_.__closure[d5.GetId(true)]);
var depthOf_d5_in_d3 = int.Parse((string)d3_.__closure[await d5.GetIdAsync(true)]);
Assert.That(depthOf_d5_in_d3, Is.EqualTo(2));

var depthOf_d4_in_d3 = int.Parse((string)d3_.__closure[d4.GetId(true)]);
var depthOf_d4_in_d3 = int.Parse((string)d3_.__closure[await d4.GetIdAsync(true)]);
Assert.That(depthOf_d4_in_d3, Is.EqualTo(1));

var depthOf_d5_in_d2 = int.Parse((string)d2_.__closure[d5.GetId(true)]);
var depthOf_d5_in_d2 = int.Parse((string)d2_.__closure[await d5.GetIdAsync(true)]);
Assert.That(depthOf_d5_in_d2, Is.EqualTo(1));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ static OperationsReceiveTests()
];
}

public static IEnumerable<string> TestCases()
public static async Task<IEnumerable<string>> TestCases()
{
List<string> ret = new();
foreach (var s in s_testObjects)
{
ret.Add(s.GetId(true));
ret.Add(await s.GetIdAsync(true));
}

return ret;
Expand Down
Loading

0 comments on commit 4454513

Please sign in to comment.