Skip to content

Commit

Permalink
#813 add State validation on getting mem delta
Browse files Browse the repository at this point in the history
  • Loading branch information
zhabis committed Feb 2, 2023
1 parent 0a23487 commit 5d37944
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 9 deletions.
25 changes: 22 additions & 3 deletions src/Azos.Sky.Server/Fabric/Server/FiberMemory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -162,10 +162,12 @@ public void Crash(Exception error)
/// Creates s snapshot of data changes which can be commited back into <see cref="IFiberStoreShard"/>
/// using <see cref="IFiberStoreShard.CheckInAsync(FiberMemoryDelta)"/>.
/// This only succeeds if the <see cref="Status"/> is <see cref="MemoryStatus.LockedForCaller"/>
/// otherwise Delta can not be obtained
/// otherwise Delta can not be obtained.
/// Performs validation and throws if slots are in invalid state
/// </summary>
public FiberMemoryDelta MakeDeltaSnapshot(FiberStep? nextStep, FiberState currentState)
public FiberMemoryDelta MakeDeltaSnapshot(IApplication app, FiberStep? nextStep, FiberState currentState)
{
app.NonNull(nameof(app));
(m_Status == MemoryStatus.LockedForCaller).IsTrue("Delta obtained for LockedForCaller memory");

var result = new FiberMemoryDelta
Expand All @@ -188,7 +190,24 @@ public FiberMemoryDelta MakeDeltaSnapshot(FiberStep? nextStep, FiberState curren
result.NextSliceInterval = nxt.NextSliceInterval;
result.ExitCode = nxt.ExitCode;
result.Result = nxt.Result;
result.Changes = currentState.SlotChanges.ToArray();

var changes = currentState.SlotChanges.ToArray();
foreach(var change in changes)
{
app.InjectInto(change.Value);

var error = change.Value.Validate();
if (error != null)
{
throw new FabricStateValidationException(
"Validation error for state slot `{0}.{1}` validation failed: {2}".Args(
currentState.GetType().DisplayNameWithExpandedGenericArgs(),
change.Value.GetType().DisplayNameWithExpandedGenericArgs(),
error.ToMessageWithType()), error);
}
}

result.Changes = changes;
}

return result;
Expand Down
2 changes: 1 addition & 1 deletion src/Azos.Sky.Server/Fabric/Server/FiberProcessorDaemon.cs
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ private async Task processFiberQuantumUnsafe(ShardMapping shard, Guid logRel)
var (wasHandled, nextStep, fiberState) = await processFiberQuantumCore(memory).ConfigureAwait(false);//<===================== FIBER SLICE gets called
if (!wasHandled) return;//get out asap

var delta = memory.MakeDeltaSnapshot(nextStep, fiberState);
var delta = memory.MakeDeltaSnapshot(App, nextStep, fiberState);//this can throw on invalid state

var saveErrorCount = 0;
while(true)
Expand Down
12 changes: 12 additions & 0 deletions src/Azos.Sky/Fabric/Exceptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,18 @@ public FabricProcessorException(string message, Exception inner) : base(message,
protected FabricProcessorException(SerializationInfo info, StreamingContext context) : base(info, context) { }
}

/// <summary>
/// Thrown to indicate state validation error
/// </summary>
[Serializable]
public class FabricStateValidationException : FabricProcessorException
{
public FabricStateValidationException() : base() { }
public FabricStateValidationException(string message) : base(message) { }
public FabricStateValidationException(string message, Exception inner) : base(message, inner) { }
protected FabricStateValidationException(SerializationInfo info, StreamingContext context) : base(info, context) { }
}

/// <summary>
/// Thrown to indicate errors when fibers are not derived from <see cref="Fiber{TParameters, TState}"/>
/// </summary>
Expand Down
3 changes: 3 additions & 0 deletions src/Azos.Sky/Fabric/FiberStep.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ public struct FiberStep
{
public const string CONVENTION_STEP_METHOD_NAME_PREFIX = "Step_";

public static readonly Atom START = Atom.Encode("Start");


public static readonly FiberStep ZERO = new FiberStep();

private static readonly FiniteSetLookup<(Type t, Atom s), MethodInfo> STEP_MI_CACHE =
Expand Down
10 changes: 5 additions & 5 deletions src/testing/Azos.Tests.Unit/Fabric/MemoryDeltaFormatTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Azos.Apps;
using Azos.Data;
using Azos.Scripting;
using Azos.Serialization.Bix;
Expand Down Expand Up @@ -73,7 +73,7 @@ public void Test01_Roundtrip_NextStep_NoResult()
gotState.AccountNumber = 223322;//mutate state <====================
Aver.IsTrue(got.HasDelta(gotState));

var delta = got.MakeDeltaSnapshot(FiberStep.ContinueImmediately(Atom.Encode("step2")), gotState);
var delta = got.MakeDeltaSnapshot(NOPApplication.Instance, FiberStep.ContinueImmediately(Atom.Encode("step2")), gotState);

Aver.AreEqual("step2", delta.NextStep.Value);
Aver.AreEqual(new TimeSpan(0), delta.NextSliceInterval);
Expand Down Expand Up @@ -156,7 +156,7 @@ public void Test02_Roundtrip_FinalStep_WithResult()
String1 = "Dallas"
};

var delta = got.MakeDeltaSnapshot(FiberStep.FinishWithResult(123, result), gotState);
var delta = got.MakeDeltaSnapshot(NOPApplication.Instance, FiberStep.FinishWithResult(123, result), gotState);

Aver.IsTrue(delta.NextStep.IsZero);
Aver.AreEqual(new TimeSpan(0), delta.NextSliceInterval);
Expand Down Expand Up @@ -241,7 +241,7 @@ public void Test03_Roundtrip_FinalStep_NoResult()
Aver.IsTrue(got.HasDelta(gotState));


var delta = got.MakeDeltaSnapshot(FiberStep.Finish(321), gotState);
var delta = got.MakeDeltaSnapshot(NOPApplication.Instance, FiberStep.Finish(321), gotState);

Aver.IsTrue(delta.NextStep.IsZero);
Aver.AreEqual(new TimeSpan(0), delta.NextSliceInterval);
Expand Down Expand Up @@ -323,7 +323,7 @@ public void Test04_Roundtrip_Crash()
Aver.IsFalse(got.HasDelta(gotState));
got.Crash(new FabricException("Problem X"));//crash memory

var delta = got.MakeDeltaSnapshot(FiberStep.Finish(321), gotState);
var delta = got.MakeDeltaSnapshot(NOPApplication.Instance, FiberStep.Finish(321), gotState);

Aver.IsTrue(delta.NextStep.IsZero);
Aver.AreEqual(new TimeSpan(0), delta.NextSliceInterval);
Expand Down

0 comments on commit 5d37944

Please sign in to comment.