Skip to content

Commit

Permalink
remove ParallelBranch
Browse files Browse the repository at this point in the history
  • Loading branch information
mihainradu committed May 9, 2024
1 parent 99d13ee commit 0bf097f
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 102 deletions.
109 changes: 42 additions & 67 deletions src/Test/TestCases.Runtime/ParallelBranchTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,157 +26,132 @@ protected override void Execute(CodeActivityContext context)
}

protected virtual IWorkflowSerializer Serializer => new DataContractWorkflowSerializer();
ParallelBranch parentLevel = default;
ParallelBranch noBranch = default;
string _parentLevel = default;
readonly string _noBranch = default;

private void Run(params Action<CodeActivityContext>[] onExecute)
{
new WorkflowApplication(new SuspendingWrapper(onExecute.Select(c => new TestCodeActivity(c))))
{
InstanceStore = new MemoryInstanceStore(Serializer)
}
.RunUntilCompletion();

}.RunUntilCompletion();
}

private void RunWithParent(params Action<CodeActivityContext>[] onExecute)
{
Run([new(SetParent), .. onExecute]);
void SetParent(CodeActivityContext context)
{

var parent = context.CurrentInstance.Parent;
noBranch = parent.GetCurrentParallelBranch();
parent.GetCurrentParallelBranchId().ShouldBe(_noBranch);
parent.MarkNewParallelBranch();
parentLevel = parent.GetCurrentParallelBranch();
_parentLevel = parent.GetCurrentParallelBranchId();
}
}

[Fact]
public void Push()
{
var level1 = new ParallelBranch().Push();
var level2 = level1.Push();
var level3 = level2.Push();
level2.BranchesStackString.ShouldStartWith(level1.BranchesStackString);
level3.BranchesStackString.ShouldStartWith(level2.BranchesStackString);
var l3Splits = level3.BranchesStackString.Split('.');
var level1 = default(string).PushNewBranch();
var level2 = level1.PushNewBranch();
var level3 = level2.PushNewBranch();
level2.ShouldStartWith(level1);
level3.ShouldStartWith(level2);
var l3Splits = level3.Split('.');
l3Splits.Length.ShouldBe(3);
l3Splits.First().ShouldBe(level1.BranchesStackString);
l3Splits.First().ShouldBe(level1);
}

[Fact]
public void RestoreToNullWhenNull() => Run(
public void SetToNullWhenNull() => Run(
context =>
{
var noBranch = context.CurrentInstance.GetCurrentParallelBranch();
context.CurrentInstance.SetCurrentParallelBranch(noBranch);
context.CurrentInstance.SetCurrentParallelBranch(noBranch);
context.CurrentInstance.SetCurrentParallelBranchId(_noBranch);
context.CurrentInstance.SetCurrentParallelBranchId(_noBranch);
context.CurrentInstance.GetCurrentParallelBranchId().ShouldBeNull();
});

[Fact]
public void SetToNullWhenNotNull() => Run(
context =>
{
var noBranch = context.CurrentInstance.GetCurrentParallelBranch();
context.CurrentInstance.SetCurrentParallelBranch(noBranch);
context.CurrentInstance.SetCurrentParallelBranch(noBranch.Push());
context.CurrentInstance.SetCurrentParallelBranch(noBranch);
context.CurrentInstance.SetCurrentParallelBranchId(_noBranch);
context.CurrentInstance.SetCurrentParallelBranchId(_noBranch.PushNewBranch());
context.CurrentInstance.SetCurrentParallelBranchId(_noBranch);
context.CurrentInstance.GetCurrentParallelBranchId().ShouldBeNull();
});


[Fact]
public void ParallelBranchPersistence() => RunWithParent(
context =>
{
PersistParallelBranch();
void PersistParallelBranch()
{
new ExecutionProperties(null, context.CurrentInstance.Parent, context.CurrentInstance.Parent.PropertyManager)
.Add("localParallelBranch", parentLevel, skipValidations: true, onlyVisibleToPublicChildren: false);
}
},
context =>
{
var persistedParent = GetPersistedParallelBranch();
var branchId = context.GetCurrentParallelBranchId();
persistedParent.BranchesStackString.ShouldBe(parentLevel.BranchesStackString);
branchId.ShouldBe(persistedParent.BranchesStackString);
ParallelBranch GetPersistedParallelBranch()
{
return (ParallelBranch)new ExecutionProperties(null, context.CurrentInstance.Parent, context.CurrentInstance.Parent.PropertyManager)
.Find("localParallelBranch");
}
});

[Fact]
public void GetCurrentParallelBranch_InheritsFromParent() => RunWithParent(
context =>
{
var branchId = context.GetCurrentParallelBranchId();
var currentBranch = context.CurrentInstance.GetCurrentParallelBranch();
currentBranch.BranchesStackString.ShouldBe(branchId);
currentBranch.BranchesStackString.ShouldBe(parentLevel.BranchesStackString);
var currentBranch = context.CurrentInstance.GetCurrentParallelBranchId();
currentBranch.ShouldBe(branchId);
currentBranch.ShouldBe(_parentLevel);
});

[Fact]
public void PushAndSetParallelBranch() => RunWithParent(
context =>
{
var pushLevelOnSchedule = parentLevel.Push();
var pushLevelOnSchedule = _parentLevel.PushNewBranch();
var scheduledInstance = context.CurrentInstance;
scheduledInstance.SetCurrentParallelBranch(pushLevelOnSchedule);
var getPushedLevel = scheduledInstance.GetCurrentParallelBranch();
getPushedLevel.BranchesStackString.ShouldBe(pushLevelOnSchedule.BranchesStackString);
scheduledInstance.GetCurrentParallelBranchId().ShouldBe(pushLevelOnSchedule.BranchesStackString);
scheduledInstance.SetCurrentParallelBranchId(pushLevelOnSchedule);
var getPushedLevel = scheduledInstance.GetCurrentParallelBranchId();
getPushedLevel.ShouldBe(pushLevelOnSchedule);
scheduledInstance.GetCurrentParallelBranchId().ShouldBe(pushLevelOnSchedule);
});

[Fact]
public void UnparentedPushFails() => RunWithParent(
context =>
{
var instance = context.CurrentInstance;
instance.SetCurrentParallelBranch(parentLevel.Push());
Should.Throw<ArgumentException>(() => instance.SetCurrentParallelBranch(parentLevel.Push().Push()));
instance.SetCurrentParallelBranchId(_parentLevel.PushNewBranch());
Should.Throw<ArgumentException>(() => instance.SetCurrentParallelBranchId(_parentLevel.PushNewBranch().PushNewBranch()));
});

[Fact]
public void DoublePush() => RunWithParent(
context =>
{
var instance = context.CurrentInstance;
instance.SetCurrentParallelBranch(parentLevel.Push().Push());
instance.SetCurrentParallelBranchId(_parentLevel.PushNewBranch().PushNewBranch());
});

[Fact]
public void DoublePop() => RunWithParent(
context =>
{
var instance = context.CurrentInstance;
instance.SetCurrentParallelBranch(parentLevel.Push().Push());
instance.SetCurrentParallelBranch(parentLevel);
instance.SetCurrentParallelBranchId(_parentLevel.PushNewBranch().PushNewBranch());
instance.SetCurrentParallelBranchId(_parentLevel);
});

[Fact]
public void UnparentedPopFails() => RunWithParent(
context =>
{
var scheduledInstance = context.CurrentInstance;
scheduledInstance.SetCurrentParallelBranch(parentLevel.Push().Push());
Should.Throw<ArgumentException>(() => scheduledInstance.SetCurrentParallelBranch(parentLevel.Push()));
scheduledInstance.SetCurrentParallelBranchId(_parentLevel.PushNewBranch().PushNewBranch());
Should.Throw<ArgumentException>(() => scheduledInstance.SetCurrentParallelBranchId(_parentLevel.PushNewBranch()));
});

[Fact]
public void ParallelBranchDoesNotLeakToSiblings() => RunWithParent(
context =>
{
var readLevel = context.CurrentInstance.GetCurrentParallelBranch();
context.CurrentInstance.SetCurrentParallelBranchId(context.CurrentInstance.GetCurrentParallelBranchId().PushNewBranch());
context.CurrentInstance.GetCurrentParallelBranchId().ShouldNotBe(_parentLevel);
context.CurrentInstance.GetCurrentParallelBranchId().ShouldStartWith(_parentLevel);
},
context =>
{
var readLevel = context.CurrentInstance.GetCurrentParallelBranchId();
var branchId = context.GetCurrentParallelBranchId();
readLevel.BranchesStackString.ShouldBe(parentLevel.BranchesStackString);
branchId.ShouldBe(parentLevel.BranchesStackString);
readLevel.ShouldBe(_parentLevel);
branchId.ShouldBe(_parentLevel);
});
}
39 changes: 4 additions & 35 deletions src/UiPath.Workflow.Runtime/ParallelTrackingExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,21 +1,5 @@
namespace System.Activities.ParallelTracking;

[DataContract]
public readonly record struct ParallelBranch
{
[DataMember]
internal string BranchesStackString { get; init; }
[DataMember]
internal string InstanceId { get; init; }

public readonly ParallelBranch Push() =>
new()
{
BranchesStackString = ParallelTrackingExtensions.PushNewBranch(BranchesStackString),
InstanceId = InstanceId
};
}

/// <summary>
/// This feature introduces a context.GetCurrentParallelId() queryable from an activity,
/// which should identify a "parallelism" branch on which the activity executes.
Expand All @@ -25,9 +9,7 @@
/// </summary>
public static class ParallelTrackingExtensions
{
public const string BranchIdPropertyName = "__ParallelBranchId";
private const char StackDelimiter = '.';

private const string BranchIdPropertyName = "__ParallelBranchId";

public static ActivityInstance MarkNewParallelBranch(this ActivityInstance instance)
{
Expand All @@ -42,24 +24,12 @@ public static ActivityInstance MarkNewParallelBranch(this ActivityInstance insta
public static string GetCurrentParallelBranchId(this ActivityContext context) =>
context.CurrentInstance?.GetCurrentParallelBranchId();

public static ParallelBranch GetCurrentParallelBranch(this ActivityInstance instance) =>
new() { BranchesStackString = instance.GetCurrentParallelBranchId(), InstanceId = instance.Id };

public static void SetCurrentParallelBranch(this ActivityInstance currentOrChildInstance, ParallelBranch parallelBranch)
{
if (parallelBranch.InstanceId != currentOrChildInstance.Id
&& parallelBranch.InstanceId != currentOrChildInstance.Parent?.Id)
throw new ArgumentException($"{nameof(parallelBranch)} must be a pop or a push.", nameof(currentOrChildInstance));

currentOrChildInstance.SetCurrentParallelBranchId(parallelBranch.BranchesStackString);
}

/// <summary>
/// Sets the parallelBranchId for the current activity instance
/// </summary>
/// <param name="branchId">null or empty removes the branch setting from current instance</param>
/// <exception cref="ArgumentException">when not a pop or a push</exception>
private static void SetCurrentParallelBranchId(this ActivityInstance instance, string branchId)
public static void SetCurrentParallelBranchId(this ActivityInstance instance, string branchId)
{
var currentBranchId = instance.GetCurrentParallelBranchId();

Expand All @@ -74,14 +44,13 @@ private static void SetCurrentParallelBranchId(this ActivityInstance instance, s

props.Add(BranchIdPropertyName, branchId, skipValidations: true, onlyVisibleToPublicChildren: false);
}
public static string PushNewBranch(this string thisStack) =>
$"{thisStack}.{Guid.NewGuid():N}".Trim('.');

private static ExecutionProperties GetExecutionProperties(ActivityInstance instance) =>
new(null, instance, instance.PropertyManager);

private static bool IsAncestorOf(string thisStack, string descendantStack) =>
(thisStack ?? string.Empty)
.StartsWith(descendantStack ?? string.Empty, StringComparison.Ordinal);

internal static string PushNewBranch(string thisStack) =>
$"{thisStack}.{Guid.NewGuid():N}".Trim(StackDelimiter);
}

0 comments on commit 0bf097f

Please sign in to comment.