Skip to content

Commit 65920aa

Browse files
committed
EffectLoopingWorks: dump flag/status/effects/messages on wait timeout
1 parent 17bcbb0 commit 65920aa

1 file changed

Lines changed: 67 additions & 9 deletions

File tree

  • Core/Cleipnir.ResilientFunctions.Tests/TestTemplates/FunctionTests

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

Lines changed: 67 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,23 +1018,81 @@ await elms.CaptureEach(
10181018
var cp = await registration.ControlPanel(id.Instance).ShouldNotBeNullAsync();
10191019
var messageWriter = registration.MessageWriters.For(id.Instance);
10201020
var effectStore = store.EffectsStore;
1021+
var storedId = registration.MapToStoredId(id.Instance);
1022+
1023+
async Task<string> DumpAsync(string phase)
1024+
{
1025+
string status;
1026+
try { await cp.Refresh(); status = cp.Status.ToString(); }
1027+
catch (Exception ex) { status = $"<refresh failed: {ex.GetType().Name}: {ex.Message}>"; }
1028+
1029+
string effectsDump;
1030+
try
1031+
{
1032+
var effects = await effectStore.GetEffectResults(storedId);
1033+
effectsDump = string.Join(", ", effects.Select(e => $"{e.Alias ?? "<null>"}:{e.EffectId}:{e.WorkStatus}"));
1034+
}
1035+
catch (Exception ex) { effectsDump = $"<effects fetch failed: {ex.GetType().Name}: {ex.Message}>"; }
1036+
1037+
string messagesDump;
1038+
try
1039+
{
1040+
var msgs = await store.MessageStore.GetMessages(storedId);
1041+
messagesDump = string.Join(", ", msgs.Select(m =>
1042+
{
1043+
try { return $"[{m.Position}]{System.Text.Encoding.UTF8.GetString(m.MessageContent)}"; }
1044+
catch { return $"[{m.Position}]<{m.MessageContent.Length} bytes>"; }
1045+
}));
1046+
}
1047+
catch (Exception ex) { messagesDump = $"<messages fetch failed: {ex.GetType().Name}: {ex.Message}>"; }
1048+
1049+
int[] iterationsSnapshot;
1050+
try { iterationsSnapshot = iterations.ToArray(); }
1051+
catch { iterationsSnapshot = Array.Empty<int>(); }
1052+
1053+
return $"phase={phase}; flag.Value={flag.Value}; status={status}; iterations=[{string.Join(",", iterationsSnapshot)}]; effects=[{effectsDump}]; messages=[{messagesDump}]";
1054+
}
1055+
1056+
async Task WaitAsync(string label, Func<Task<bool>> predicate)
1057+
{
1058+
try
1059+
{
1060+
await BusyWait.Until(predicate, maxWait: TimeSpan.FromSeconds(30));
1061+
}
1062+
catch (TimeoutException)
1063+
{
1064+
throw new TimeoutException($"Wait '{label}' timed out after 30s. {await DumpAsync(label)}");
1065+
}
1066+
}
10211067

10221068
for (var i = 0; i < 6; i++)
10231069
{
1024-
await BusyWait.Until(() => flag.Value == i, maxWait: TimeSpan.FromSeconds(30));
1025-
await cp.BusyWaitUntil(c => c.Status == Status.Suspended, maxWait: TimeSpan.FromSeconds(30));
1026-
var storedEffects = await effectStore.GetEffectResults(registration.MapToStoredId(id.Instance));
1027-
storedEffects.Any(e => e.Alias == "Before").ShouldBeTrue();
1028-
storedEffects.Any(e => e.Alias == "Loop").ShouldBeTrue();
1029-
storedEffects.Single(e => e.Alias == i.ToString()).EffectId.ShouldBe(new EffectId([1,i,0]));
1030-
storedEffects.Count(e => e.Alias != null).ShouldBe(3);
1070+
await WaitAsync($"flag.Value == {i}", () => Task.FromResult(flag.Value == i));
1071+
await WaitAsync($"Status == Suspended (i={i})", async () => { await cp.Refresh(); return cp.Status == Status.Suspended; });
1072+
1073+
var storedEffects = await effectStore.GetEffectResults(storedId);
1074+
try
1075+
{
1076+
storedEffects.Any(e => e.Alias == "Before").ShouldBeTrue();
1077+
storedEffects.Any(e => e.Alias == "Loop").ShouldBeTrue();
1078+
storedEffects.Single(e => e.Alias == i.ToString()).EffectId.ShouldBe(new EffectId([1, i, 0]));
1079+
storedEffects.Count(e => e.Alias != null).ShouldBe(3);
1080+
}
1081+
catch (Exception ex)
1082+
{
1083+
throw new Exception($"Effect assertion failed at i={i}. {await DumpAsync($"effect-assertions i={i}")}", ex);
1084+
}
10311085

10321086
await messageWriter.AppendMessage(i.ToString());
10331087
}
10341088

1035-
await cp.BusyWaitUntil(c => c.Status == Status.Succeeded, maxWait: TimeSpan.FromSeconds(30));
1089+
await WaitAsync("Status == Succeeded (final)", async () => { await cp.Refresh(); return cp.Status == Status.Succeeded; });
10361090

1037-
iterations.SequenceEqual([0, 1, 2, 3, 4, 5]).ShouldBeTrue();
1091+
try { iterations.SequenceEqual([0, 1, 2, 3, 4, 5]).ShouldBeTrue(); }
1092+
catch (Exception ex)
1093+
{
1094+
throw new Exception($"Final iterations check failed. {await DumpAsync("final-iterations")}", ex);
1095+
}
10381096
}
10391097

10401098
public abstract Task ChildEffectsAreClearedWhenParentEffectWithResultCompletes();

0 commit comments

Comments
 (0)