Skip to content

Commit cf25de9

Browse files
authored
Update ResilientFunctions to CreateAndStart lifecycle and adapt the Flows wrapper (#13)
The submodule moves to latest main (PR #221), where FunctionsRegistry's constructor is private and the static CreateAndStart factories are the only public construction path - guaranteeing background processing never starts before construction completes. FlowsContainer follows the same shape: private constructor plus async CreateAndStart factories (the Create helper is renamed accordingly). The DI registration resolves the container through a factory that blocks once during host start-up, mirroring the old constructor's synchronous replica-watchdog initialization. Adaptations to the intervening core changes: - Flows<...> now registers through the public Register* overloads with plain Task-returning inners. The previous internal-overload registration bypassed the core's WithSuspension wrapper, and since the central-suspension redesign (core #204) removed exception-based suspension, wrapper flows awaiting a message were stuck Executing forever instead of suspending. The wrapper's own exception-to-result catch blocks are deleted - the core adapter owns that conversion now. - SuspendInvocationException catches removed (type deleted; suspension no longer surfaces as an exception). - FlowOptions/FlowsContainer no longer reference the removed EnableWatchdogs and DelayStartup settings; MapToLocalSettings matches the new LocalSettings shape. - Flows.Interrupt removed, mirroring the interrupt API deletion in the core. - OptionsTests appends its message via the registration MessageWriter instead of the control panel - control-panel appends against a live flow race the owner's effect-version guard.
1 parent 78bf200 commit cf25de9

27 files changed

Lines changed: 95 additions & 159 deletions

File tree

‎Cleipnir.ResilientFunctions‎

‎Cleipnir.Tests.AspNet/BulkPublishTests.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public Task MultipleMessageCanBePublishedUsingSqlServer()
2525

2626
private async Task MultipleMessageCanBePublished(Task<IFunctionStore> storeTask)
2727
{
28-
using var container = FlowsContainer.Create(functionStore: await storeTask);
28+
using var container = await FlowsContainer.CreateAndStart(functionStore: await storeTask);
2929
var flows = container.RegisterAnonymousFlow(() => new TestFlow(), flowName: $"TestFlow#{Guid.NewGuid()}");
3030

3131
var instances = Enumerable.Range(0, 100)

‎Cleipnir.Tests/Flows/FlowFactoryTests.cs‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ public class FlowFactoryTests
99
[TestMethod]
1010
public async Task FlowFactoryForTestFlowWithResultIsUsedWhenProvided()
1111
{
12-
var flowsContainer = FlowsContainer.Create();
12+
var flowsContainer = await FlowsContainer.CreateAndStart();
1313
var flows = flowsContainer.RegisterAnonymousFlow<TestFlowWithResult, string, string>(flowFactory: () => new TestFlowWithResult());
1414
var result = await flows.Run("SomeInstance", "hallo world");
1515
result.ShouldBe("HALLO WORLD");
@@ -30,7 +30,7 @@ public override Task<string> Run(string param)
3030
[TestMethod]
3131
public async Task FlowFactoryForTestFlowWithParamIsUsedWhenProvided()
3232
{
33-
var flowsContainer = FlowsContainer.Create();
33+
var flowsContainer = await FlowsContainer.CreateAndStart();
3434
var flows = flowsContainer.RegisterAnonymousFlow<TestFlowWithParam, string>(flowFactory: () => new TestFlowWithParam());
3535
await flows.Run("SomeInstance", "hallo world");
3636

@@ -55,7 +55,7 @@ public override Task Run(string param)
5555
[TestMethod]
5656
public async Task FlowFactoryForTestFlowWithoutParamIsUsedWhenProvided()
5757
{
58-
var flowsContainer = FlowsContainer.Create();
58+
var flowsContainer = await FlowsContainer.CreateAndStart();
5959
var flows = flowsContainer.RegisterAnonymousFlow(flowFactory: () => new TestFlowWithoutParam());
6060
await flows.Run("SomeInstance");
6161

‎Cleipnir.Tests/Flows/FlowsWithResultTests.cs‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public async Task SimpleFlowCompletesSuccessfully()
1717
serviceCollection.AddTransient<SimpleFuncFlow>();
1818

1919
var flowStore = new InMemoryFunctionStore();
20-
var flowsContainer = new FlowsContainer(
20+
var flowsContainer = await FlowsContainer.CreateAndStart(
2121
flowStore,
2222
serviceCollection.BuildServiceProvider()
2323
);
@@ -63,7 +63,7 @@ public async Task CompletionOfScheduledFlowCanBeAwaited()
6363
serviceCollection.AddTransient<SimpledDelayedFlow>();
6464

6565
var flowStore = new InMemoryFunctionStore();
66-
var flowsContainer = new FlowsContainer(
66+
var flowsContainer = await FlowsContainer.CreateAndStart(
6767
flowStore,
6868
serviceCollection.BuildServiceProvider(),
6969
new Settings(watchdogCheckFrequency: TimeSpan.FromMilliseconds(100))
@@ -100,7 +100,7 @@ public async Task EventDrivenFlowCompletesSuccessfully()
100100
serviceCollection.AddTransient<MessageDrivenFuncFlow>();
101101

102102
var flowStore = new InMemoryFunctionStore();
103-
var flowsContainer = new FlowsContainer(
103+
var flowsContainer = await FlowsContainer.CreateAndStart(
104104
flowStore,
105105
serviceCollection.BuildServiceProvider(),
106106
new Settings(watchdogCheckFrequency: TimeSpan.FromMilliseconds(100))
@@ -148,7 +148,7 @@ public async Task FailingFlowCompletesWithError()
148148
serviceCollection.AddTransient<FailingFuncFlow>();
149149

150150
var flowStore = new InMemoryFunctionStore();
151-
var flowsContainer = new FlowsContainer(
151+
var flowsContainer = await FlowsContainer.CreateAndStart(
152152
flowStore,
153153
serviceCollection.BuildServiceProvider()
154154
);

‎Cleipnir.Tests/Flows/FunctionRegistrationTests.cs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public class FunctionRegistrationTests
1111
[TestMethod]
1212
public async Task FunctionCanBeRegisteredAndInvoked()
1313
{
14-
using var container = FlowsContainer.Create();
14+
using var container = await FlowsContainer.CreateAndStart();
1515
var registration = container.Functions.RegisterFunc(
1616
"TestFlow",
1717
inner: Task<string> (string param) => param.ToUpper().ToTask()
@@ -24,7 +24,7 @@ public async Task FunctionCanBeRegisteredAndInvoked()
2424
[TestMethod]
2525
public async Task FlowCanBeCreatedWithInitialState()
2626
{
27-
var flowsContainer = FlowsContainer.Create();
27+
var flowsContainer = await FlowsContainer.CreateAndStart();
2828
var flow = new InitialStateFlow();
2929
var flows = flowsContainer.RegisterAnonymousFlow<InitialStateFlow, string, string>(
3030
flowFactory: () => flow

‎Cleipnir.Tests/Flows/MultipleRegistrationTests.cs‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using Cleipnir.ResilientFunctions.Storage;
2+
using System.Threading.Tasks;
23
using Cleipnir.ResilientFunctions.Domain;
34
using Microsoft.Extensions.DependencyInjection;
45
using Shouldly;
@@ -9,21 +10,21 @@ namespace Cleipnir.Flows.Tests.Flows;
910
public class MultipleRegistrationTests
1011
{
1112
[TestMethod]
12-
public void SameFlowTypeWithSameNameCanBeRegisteredSeveralTimes()
13+
public async Task SameFlowTypeWithSameNameCanBeRegisteredSeveralTimes()
1314
{
1415
var serviceCollection = new ServiceCollection();
1516
var store = new InMemoryFunctionStore();
16-
var flowsContainer = new FlowsContainer(store, serviceCollection.BuildServiceProvider());
17+
var flowsContainer = await FlowsContainer.CreateAndStart(store, serviceCollection.BuildServiceProvider());
1718
_ = new TestFlowType1s(flowsContainer);
1819
_ = new TestFlowType1s(flowsContainer);
1920
}
2021

2122
[TestMethod]
22-
public void DifferentFlowTypesWithSameNameCannotBeRegisteredSeveralTimes()
23+
public async Task DifferentFlowTypesWithSameNameCannotBeRegisteredSeveralTimes()
2324
{
2425
var serviceCollection = new ServiceCollection();
2526
var store = new InMemoryFunctionStore();
26-
var flowsContainer = new FlowsContainer(store, serviceCollection.BuildServiceProvider());
27+
var flowsContainer = await FlowsContainer.CreateAndStart(store, serviceCollection.BuildServiceProvider());
2728
_ = new TestFlowType1s(flowsContainer);
2829
Should.Throw<InvalidOperationException>(() =>
2930
new TestFlowType2s(flowsContainer)

‎Cleipnir.Tests/Flows/OptionsTests.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ await Should.ThrowAsync<InvocationSuspendedException>(
4747
// Flow may be Executing (waiting for message) or Suspended depending on timing
4848
controlPanel.Status.ShouldBeOneOf(Status.Executing, Status.Suspended);
4949

50-
await controlPanel.Messages.Append(new StringWrapper("Hello"));
50+
await flowsWithDefaultProvidedOptions.MessageWriter("Id").AppendMessage(new StringWrapper("Hello"));
5151

5252
await controlPanel.WaitForCompletion(allowPostponeAndSuspended: true);
5353
}

‎Cleipnir.Tests/Flows/ParamlessFlowsTests.cs‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public async Task SimpleFlowCompletesSuccessfully()
1717
serviceCollection.AddTransient<SimpleParamlessFlow>();
1818

1919
var flowStore = new InMemoryFunctionStore();
20-
var flowsContainer = new FlowsContainer(
20+
var flowsContainer = await FlowsContainer.CreateAndStart(
2121
flowStore,
2222
serviceCollection.BuildServiceProvider()
2323
);
@@ -56,7 +56,7 @@ public async Task EventDrivenFlowCompletesSuccessfully()
5656
serviceCollection.AddTransient<EventDrivenParamlessFlow>();
5757

5858
var flowStore = new InMemoryFunctionStore();
59-
var flowsContainer = new FlowsContainer(
59+
var flowsContainer = await FlowsContainer.CreateAndStart(
6060
flowStore,
6161
serviceCollection.BuildServiceProvider(),
6262
new Settings(watchdogCheckFrequency: TimeSpan.FromMilliseconds(100))
@@ -102,7 +102,7 @@ public async Task FailingFlowCompletesWithError()
102102
serviceCollection.AddTransient<FailingParamlessFlow>();
103103

104104
var flowStore = new InMemoryFunctionStore();
105-
var flowsContainer = new FlowsContainer(
105+
var flowsContainer = await FlowsContainer.CreateAndStart(
106106
flowStore,
107107
serviceCollection.BuildServiceProvider()
108108
);
@@ -146,7 +146,7 @@ public override Task Run()
146146
[TestMethod]
147147
public async Task FlowCanBeCreatedWithInitialState()
148148
{
149-
var flowsContainer = FlowsContainer.Create();
149+
var flowsContainer = await FlowsContainer.CreateAndStart();
150150
var flow = new InitialStateFlow();
151151
var flows = flowsContainer.RegisterAnonymousFlow(
152152
flowFactory: () => flow

‎Cleipnir.Tests/Flows/UnitFlowsTests.cs‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public async Task SimpleFlowCompletesSuccessfully()
1818
serviceCollection.AddTransient<SimpleUnitFlow>();
1919

2020
var flowStore = new InMemoryFunctionStore();
21-
var flowsContainer = new FlowsContainer(
21+
var flowsContainer = await FlowsContainer.CreateAndStart(
2222
flowStore,
2323
serviceCollection.BuildServiceProvider()
2424
);
@@ -60,7 +60,7 @@ public async Task EventDrivenFlowCompletesSuccessfully()
6060
serviceCollection.AddTransient<EventDrivenUnitFlow>();
6161

6262
var flowStore = new InMemoryFunctionStore();
63-
var flowsContainer = new FlowsContainer(
63+
var flowsContainer = await FlowsContainer.CreateAndStart(
6464
flowStore,
6565
serviceCollection.BuildServiceProvider(),
6666
new Settings(watchdogCheckFrequency: TimeSpan.FromMilliseconds(100))
@@ -107,7 +107,7 @@ public async Task FailingActionFlowCompletesWithError()
107107
serviceCollection.AddTransient<FailingUnitActionFlow>();
108108

109109
var flowStore = new InMemoryFunctionStore();
110-
var flowsContainer = new FlowsContainer(
110+
var flowsContainer = await FlowsContainer.CreateAndStart(
111111
flowStore,
112112
serviceCollection.BuildServiceProvider()
113113
);
@@ -156,7 +156,7 @@ public async Task FailingFuncFlowCompletesWithError()
156156
serviceCollection.AddTransient<FailingUnitFuncFlow>();
157157

158158
var flowStore = new InMemoryFunctionStore();
159-
var flowsContainer = new FlowsContainer(
159+
var flowsContainer = await FlowsContainer.CreateAndStart(
160160
flowStore,
161161
serviceCollection.BuildServiceProvider()
162162
);
@@ -205,7 +205,7 @@ public async Task FailingParamlessFlowCompletesWithError()
205205
serviceCollection.AddTransient<FailingUnitParamlessFlow>();
206206

207207
var flowStore = new InMemoryFunctionStore();
208-
var flowsContainer = new FlowsContainer(
208+
var flowsContainer = await FlowsContainer.CreateAndStart(
209209
flowStore,
210210
serviceCollection.BuildServiceProvider()
211211
);
@@ -250,7 +250,7 @@ public override Task Run()
250250
[TestMethod]
251251
public async Task FlowCanBeCreatedWithInitialState()
252252
{
253-
var flowsContainer = FlowsContainer.Create();
253+
var flowsContainer = await FlowsContainer.CreateAndStart();
254254
var flow = new InitialStateFlow();
255255
var flows = flowsContainer.RegisterAnonymousFlow<InitialStateFlow, string>(
256256
flowFactory: () => flow

‎Cleipnir.Tests/Flows/UtcNowTests.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public async Task ProvidedUtcNowDelegateIsUsed()
1515

1616
var serviceCollection = new ServiceCollection();
1717
serviceCollection.AddSingleton<UtcNowTestFlow>();
18-
var flowsContainer = new FlowsContainer(
18+
var flowsContainer = await FlowsContainer.CreateAndStart(
1919
new InMemoryFunctionStore(),
2020
serviceCollection.BuildServiceProvider(),
2121
new Settings(utcNow: () => now, watchdogCheckFrequency: TimeSpan.FromMilliseconds(100))

0 commit comments

Comments
 (0)