Skip to content

Commit 7e3d468

Browse files
committed
Added custom serializable functionality
1 parent 2847595 commit 7e3d468

File tree

8 files changed

+83
-44
lines changed

8 files changed

+83
-44
lines changed

Core/Cleipnir.ResilientFunctions.Tests/InMemoryTests/RFunctionTests/EffectTests.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,8 @@ public override Task ExceptionThrownInsideEffectBecomesFatalWorkflowException()
6161
[TestMethod]
6262
public override Task ExceptionThrownInsideEffectStaysFatalWorkflowException()
6363
=> ExceptionThrownInsideEffectStaysFatalWorkflowException(FunctionStoreFactory.Create());
64+
65+
[TestMethod]
66+
public override Task EffectCanReturnOption()
67+
=> EffectCanReturnOption(FunctionStoreFactory.Create());
6468
}

Core/Cleipnir.ResilientFunctions.Tests/TestTemplates/RFunctionTests/EffectTests.cs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
using Cleipnir.ResilientFunctions.CoreRuntime.Invocation;
66
using Cleipnir.ResilientFunctions.CoreRuntime.Serialization;
77
using Cleipnir.ResilientFunctions.Domain;
8-
using Cleipnir.ResilientFunctions.Domain.Exceptions;
98
using Cleipnir.ResilientFunctions.Helpers;
9+
using Cleipnir.ResilientFunctions.Reactive.Utilities;
1010
using Cleipnir.ResilientFunctions.Storage;
1111
using Cleipnir.ResilientFunctions.Tests.Utils;
1212
using Microsoft.VisualStudio.TestTools.UnitTesting;
@@ -541,4 +541,39 @@ public async Task ExceptionThrownInsideEffectStaysFatalWorkflowException(Task<IF
541541
}
542542
Assert.Fail("Expected FatalWorkflowException<InvalidOperationException>");
543543
}
544+
545+
public abstract Task EffectCanReturnOption();
546+
public async Task EffectCanReturnOption(Task<IFunctionStore> storeTask)
547+
{
548+
var store = await storeTask;
549+
using var functionsRegistry = new FunctionsRegistry(store);
550+
var flowId = TestFlowId.Create();
551+
var (flowType, flowInstance) = flowId;
552+
var rAction = functionsRegistry.RegisterFunc(
553+
flowType,
554+
async Task<Option<string>> (string message, Workflow workflow) =>
555+
{
556+
var (effect, _, _) = workflow;
557+
return await effect.Capture(
558+
id: "Test",
559+
work: () => Option.Create(message)
560+
);
561+
});
562+
563+
var result = await rAction.Invoke(flowInstance.ToString(), "Hello!");
564+
result.HasValue.ShouldBeTrue();
565+
result.Value.ShouldBe("Hello!");
566+
567+
var controlPanel = await rAction.ControlPanel(flowId.Instance);
568+
controlPanel.ShouldNotBeNull();
569+
570+
var effectValue = await controlPanel.Effects.GetValue<Option<string>>("Test");
571+
effectValue.ShouldNotBeNull();
572+
effectValue.HasValue.ShouldBeTrue();
573+
effectValue.Value.ShouldBe("Hello!");
574+
575+
result = await controlPanel.Restart();
576+
result.HasValue.ShouldBeTrue();
577+
result.Value.ShouldBe("Hello!");
578+
}
544579
}

Core/Cleipnir.ResilientFunctions/CoreRuntime/Invocation/InvocationHelper.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public InvocationHelper(FlowType flowType, StoredType storedType, bool isParamle
3232
_isParamlessFunction = isParamlessFunction;
3333
_settings = settings;
3434

35-
Serializer = new ErrorHandlingDecorator(settings.Serializer);
35+
Serializer = new ErrorHandlingDecorator(new CustomSerializableDecorator(settings.Serializer));
3636
_shutdownCoordinator = shutdownCoordinator;
3737
_leaseUpdaters = leaseUpdaters;
3838
_storedType = storedType;

Core/Cleipnir.ResilientFunctions/CoreRuntime/Serialization/CustomSerializableDecorator.cs

Lines changed: 8 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,10 @@
33
using System.Reflection;
44
using System.Threading;
55
using Cleipnir.ResilientFunctions.Domain;
6-
using Cleipnir.ResilientFunctions.Helpers;
76
using Cleipnir.ResilientFunctions.Storage;
87

98
namespace Cleipnir.ResilientFunctions.CoreRuntime.Serialization;
10-
/*
9+
1110
public class CustomSerializableDecorator : ISerializer
1211
{
1312
private readonly ISerializer _inner;
@@ -16,65 +15,32 @@ public class CustomSerializableDecorator : ISerializer
1615

1716
public CustomSerializableDecorator(ISerializer inner) => _inner = inner;
1817

19-
public byte[] SerializeParameter<TParam>(TParam parameter)
18+
public byte[] Serialize<T>(T parameter)
2019
=> parameter is ICustomSerializable customSerializable
2120
? customSerializable.Serialize(this)
22-
: _inner.SerializeParameter(parameter);
21+
: _inner.Serialize(parameter);
2322

24-
public TParam DeserializeParameter<TParam>(byte[] json)
25-
{
26-
return typeof(TParam).IsAssignableTo(typeof(ICustomSerializable))
27-
? CustomDeserialize<TParam>(json)
28-
: _inner.DeserializeParameter<TParam>(json);
29-
}
23+
public T Deserialize<T>(byte[] json)
24+
=> typeof(T).IsAssignableTo(typeof(ICustomSerializable))
25+
? CustomDeserialize<T>(json)
26+
: _inner.Deserialize<T>(json);
3027

3128
public StoredException SerializeException(FatalWorkflowException exception)
3229
=> _inner.SerializeException(exception);
3330

3431
public FatalWorkflowException DeserializeException(FlowId flowId, StoredException storedException)
3532
=> _inner.DeserializeException(flowId, storedException);
3633

37-
public byte[] SerializeResult<TResult>(TResult result)
38-
=> result is ICustomSerializable customSerializable
39-
? customSerializable.Serialize(this)
40-
: _inner.SerializeResult(result);
41-
42-
public TResult DeserializeResult<TResult>(byte[] json)
43-
{
44-
return typeof(TResult).IsAssignableTo(typeof(ICustomSerializable))
45-
? CustomDeserialize<TResult>(json)
46-
: _inner.DeserializeParameter<TResult>(json);
47-
}
48-
4934
public SerializedMessage SerializeMessage<TEvent>(TEvent message) where TEvent : notnull
5035
=> _inner.SerializeMessage(message); //todo allow custom serializer
5136
public object DeserializeMessage(byte[] json, byte[] type) => _inner.DeserializeMessage(json, type);
52-
53-
public byte[] SerializeEffectResult<TResult>(TResult result)
54-
=> result is ICustomSerializable customSerializable
55-
? customSerializable.Serialize(this)
56-
: _inner.SerializeEffectResult(result);
57-
58-
public TResult DeserializeEffectResult<TResult>(byte[] json)
59-
{
60-
return typeof(TResult).IsAssignableTo(typeof(ICustomSerializable))
61-
? CustomDeserialize<TResult>(json)
62-
: _inner.DeserializeEffectResult<TResult>(json);
63-
}
64-
65-
public byte[] SerializeState<TState>(TState state) where TState : FlowState, new()
66-
=> _inner.SerializeState(state);
67-
public TState DeserializeState<TState>(byte[] json) where TState : FlowState, new()
68-
=> _inner.DeserializeState<TState>(json);
6937

7038
private T CustomDeserialize<T>(byte[] bytes)
7139
{
7240
lock (_lock)
7341
{
7442
if (!_deserializers.ContainsKey(typeof(T)))
7543
{
76-
//var serializeMethodInfo = typeof(T).GetMethod(nameof(ICustomSerializable.Serialize), BindingFlags.Public | BindingFlags.Static);
77-
//var serializeFunc = (Func<ISerializer, byte[]>) Delegate.CreateDelegate(typeof(Func<ISerializer, byte[]>), serializeMethodInfo!);
7844
var deserializeMethodInfo = typeof(T).GetMethod(nameof(ICustomSerializable.Deserialize), BindingFlags.Public | BindingFlags.Static);
7945
var deserializeFunc = (Func<byte[], ISerializer, object>) Delegate.CreateDelegate(typeof(Func<byte[], ISerializer, object>), deserializeMethodInfo!);
8046
_deserializers[typeof(T)] = deserializeFunc;
@@ -83,4 +49,4 @@ private T CustomDeserialize<T>(byte[] bytes)
8349
return (T) _deserializers[typeof(T)](bytes, this);
8450
}
8551
}
86-
}*/
52+
}

Core/Cleipnir.ResilientFunctions/Reactive/Utilities/Option.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Text.Json.Serialization;
33
using System.Threading.Tasks;
4+
using Cleipnir.ResilientFunctions.CoreRuntime.Serialization;
45

56
namespace Cleipnir.ResilientFunctions.Reactive.Utilities;
67

@@ -28,6 +29,27 @@ public override bool Equals(object? obj)
2829
return Value!.Equals(option.Value);
2930
}
3031
public override int GetHashCode() => !HasValue ? 0 : Value!.GetHashCode();
32+
33+
public byte[] Serialize(ISerializer serializer)
34+
{
35+
if (!HasValue)
36+
return [];
37+
38+
var valueBytes = serializer.Serialize(Value);
39+
var bytes = new byte[valueBytes.Length + 1];
40+
bytes[0] = 1;
41+
valueBytes.CopyTo(bytes, index: 1);
42+
return bytes;
43+
}
44+
45+
public static object Deserialize(byte[] bytes, ISerializer serializer)
46+
{
47+
if (bytes[0] == 0)
48+
return NoValue;
49+
50+
var value = (T) serializer.Deserialize<T>(bytes[1..])!;
51+
return new Option<T>(value, hasValue: true);
52+
}
3153
}
3254

3355
public static class Option

Stores/MariaDB/Cleipnir.ResilientFunctions.MariaDB.Tests/RFunctionTests/EffectTests.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,8 @@ public override Task ExceptionThrownInsideEffectBecomesFatalWorkflowException()
6060
[TestMethod]
6161
public override Task ExceptionThrownInsideEffectStaysFatalWorkflowException()
6262
=> ExceptionThrownInsideEffectStaysFatalWorkflowException(FunctionStoreFactory.Create());
63+
64+
[TestMethod]
65+
public override Task EffectCanReturnOption()
66+
=> EffectCanReturnOption(FunctionStoreFactory.Create());
6367
}

Stores/PostgreSQL/Cleipnir.ResilientFunctions.PostgreSQL.Tests/RFunctionTests/EffectTests.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,8 @@ public override Task ExceptionThrownInsideEffectBecomesFatalWorkflowException()
6161
[TestMethod]
6262
public override Task ExceptionThrownInsideEffectStaysFatalWorkflowException()
6363
=> ExceptionThrownInsideEffectStaysFatalWorkflowException(FunctionStoreFactory.Create());
64+
65+
[TestMethod]
66+
public override Task EffectCanReturnOption()
67+
=> EffectCanReturnOption(FunctionStoreFactory.Create());
6468
}

Stores/SqlServer/Cleipnir.ResilientFunctions.SqlServer.Tests/EffectTests.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,8 @@ public override Task ExceptionThrownInsideEffectBecomesFatalWorkflowException()
6161
[TestMethod]
6262
public override Task ExceptionThrownInsideEffectStaysFatalWorkflowException()
6363
=> ExceptionThrownInsideEffectStaysFatalWorkflowException(FunctionStoreFactory.Create());
64+
65+
[TestMethod]
66+
public override Task EffectCanReturnOption()
67+
=> EffectCanReturnOption(FunctionStoreFactory.Create());
6468
}

0 commit comments

Comments
 (0)