public void StopAndInitiateDurableTaskOrReplay_ContinuesToNextTimer_IfTimersHaveIdenticalFireAt() { var history = DurableTestUtilities.MergeHistories( CreateOrchestratorStartedHistory(date: _startTime, isProcessed: true), CreateDurableTimerHistory(timerCreated: true, timerFired: true, fireAt: _fireAt, restartTime: _restartTime, orchestratorStartedIsProcessed: false), CreateDurableTimerHistory(timerCreated: true, timerFired: true, fireAt: _fireAt, restartTime: _restartTime, orchestratorStartedIsProcessed: false), CreateDurableTimerHistory(timerCreated: true, timerFired: true, fireAt: _fireAt, restartTime: _shouldNotHitTime, orchestratorStartedIsProcessed: false) ); var context = new OrchestrationContext { History = history }; var durableTaskHandler = new DurableTaskHandler(); for (int i = 0; i < 2; i++) { durableTaskHandler.StopAndInitiateDurableTaskOrReplay( task: new DurableTimerTask(_fireAt), context: context, noWait: false, output: _ => { Assert.True(false, "Unexpected output"); }, onFailure: _ => { }); Assert.Equal(_restartTime, context.CurrentUtcDateTime); } durableTaskHandler.StopAndInitiateDurableTaskOrReplay( task: new DurableTimerTask(_fireAt), context: context, noWait: false, output: _ => { Assert.True(false, "Unexpected output"); }, onFailure: _ => { }); Assert.Equal(_shouldNotHitTime, context.CurrentUtcDateTime); }
public void WaitAll_OutputsNothing_WhenAnyTaskIsNotCompleted( bool scheduled, bool completed) { var history = DurableTestUtilities.MergeHistories( CreateActivityHistory("FunctionA", scheduled: true, completed: true, output: "\"Result1\""), // completed CreateActivityHistory("FunctionA", scheduled: true, completed: true, output: "\"Result2\""), CreateDurableTimerHistory(timerCreated: scheduled, timerFired: completed, fireAt: _fireAt, _restartTime, orchestratorStartedIsProcessed: false), CreateActivityHistory("FunctionB", scheduled: true, completed: true, output: "\"Result3\"") // completed ); var orchestrationContext = new OrchestrationContext { History = history }; var tasksToWaitFor = new ReadOnlyCollection <DurableTask>( new DurableTask[] { new ActivityInvocationTask("FunctionA", FunctionInput), new ActivityInvocationTask("FunctionA", FunctionInput), new DurableTimerTask(_fireAt), new ActivityInvocationTask("FunctionB", FunctionInput) }); var durableTaskHandler = new DurableTaskHandler(); DurableTestUtilities.EmulateStop(durableTaskHandler); durableTaskHandler.WaitAll(tasksToWaitFor, orchestrationContext, _ => { Assert.True(false, "Unexpected output"); }); VerifyNoOrchestrationActionAdded(orchestrationContext); }
public void WaitAll_WaitsForStop_WhenAnyTaskIsNotCompleted(bool scheduledAndCompleted, bool expectedWaitForStop) { var history = DurableTestUtilities.MergeHistories( CreateActivityHistory("FunctionA", scheduled: true, completed: true, output: "\"Result1\""), CreateActivityHistory("FunctionA", scheduled: scheduledAndCompleted, completed: scheduledAndCompleted, output: "\"Result2\""), CreateDurableTimerHistory(timerCreated: scheduledAndCompleted, timerFired: scheduledAndCompleted, fireAt: _fireAt, _restartTime, orchestratorStartedIsProcessed: false), CreateActivityHistory("FunctionB", scheduled: true, completed: true, output: "\"Result3\"") ); var durableTaskHandler = new DurableTaskHandler(); var orchestrationContext = new OrchestrationContext { History = history }; var tasksToWaitFor = new ReadOnlyCollection <DurableTask>( new DurableTask[] { new ActivityInvocationTask("FunctionA", FunctionInput), new ActivityInvocationTask("FunctionA", FunctionInput), new DurableTimerTask(_fireAt), new ActivityInvocationTask("FunctionB", FunctionInput) }); DurableTestUtilities.VerifyWaitForDurableTasks( durableTaskHandler, _delayBeforeStopping, expectedWaitForStop, () => { durableTaskHandler.WaitAll(tasksToWaitFor, orchestrationContext, _ => { }); }); }
public static void VerifyWaitForDurableTasks( DurableTaskHandler durableTaskHandler, TimeSpan delayBeforeStopping, bool expectedWaitForStop, Action action ) { // action() call may block until Stop is invoked from another thread. var thread = new Thread(() => { Thread.Sleep(delayBeforeStopping); durableTaskHandler.Stop(); }); thread.Start(); try { var elapsedMilliseconds = MeasureExecutionTimeInMilliseconds(action); if (expectedWaitForStop) { Assert.True(elapsedMilliseconds > delayBeforeStopping.TotalMilliseconds * 0.8); } else { Assert.True(elapsedMilliseconds < delayBeforeStopping.TotalMilliseconds * 0.2); } } finally { thread.Join(); } }
public void ValidateTask_Throws_WhenActivityFunctionHasNoProperBinding( string bindingType, BindingInfo.Types.Direction bindingDirection) { var history = CreateHistory(scheduled: false, completed: false, output: InvocationResultJson); var orchestrationContext = new OrchestrationContext { History = history }; var loadedFunctions = new[] { DurableTestUtilities.CreateFakeAzFunctionInfo(FunctionName, "fakeTriggerBindingName", bindingType, bindingDirection) }; var durableTaskHandler = new DurableTaskHandler(); var exception = Assert.Throws <InvalidOperationException>( () => ActivityInvocationTask.ValidateTask( new ActivityInvocationTask(FunctionName, FunctionInput), loadedFunctions)); Assert.Contains(FunctionName, exception.Message); Assert.Contains(ActivityTriggerBindingType, exception.Message); DurableTestUtilities.VerifyNoActionAdded(orchestrationContext); }
public void StopAndInitiateDurableTaskOrReplay_ReplaysMultipleActivitiesWithTheSameName() { var loadedFunctions = new[] { DurableTestUtilities.CreateFakeActivityTriggerAzFunctionInfo("FunctionA"), DurableTestUtilities.CreateFakeActivityTriggerAzFunctionInfo("FunctionB") }; var history = DurableTestUtilities.MergeHistories( CreateHistory("FunctionA", scheduled: true, completed: true, output: "\"Result1\""), CreateHistory("FunctionB", scheduled: true, completed: true, output: "\"Result2\""), CreateHistory("FunctionA", scheduled: true, completed: true, output: "\"Result3\"") ); var orchestrationContext = new OrchestrationContext { History = history }; var allOutput = new List <object>(); var durableTaskHandler = new DurableTaskHandler(); // Replay FunctionA only for (var i = 0; i < 2; ++i) { durableTaskHandler.StopAndInitiateDurableTaskOrReplay( new ActivityInvocationTask("FunctionA", FunctionInput), orchestrationContext, noWait: false, output => { allOutput.Add(output); }); } // Expect FunctionA results only Assert.Equal(new[] { "Result1", "Result3" }, allOutput); }
public void WaitAny_WaitsForStop_WhenAllTasksAreNotCompleted(bool completed, bool expectedWaitForStop) { var history = DurableTestUtilities.MergeHistories( CreateOrchestratorStartedHistory(date: _startTime, isProcessed: true), CreateActivityHistory("FunctionA", scheduled: true, completed: false, output: "\"Result1\""), CreateActivityHistory("FunctionA", scheduled: true, completed: completed, output: "\"Result2\"") ); var durableTaskHandler = new DurableTaskHandler(); var orchestrationContext = new OrchestrationContext { History = history }; var tasksToWaitFor = new ReadOnlyCollection <DurableTask>( new DurableTask[] { new ActivityInvocationTask("FunctionA", FunctionInput), new ActivityInvocationTask("FunctionA", FunctionInput) }); DurableTestUtilities.VerifyWaitForDurableTasks( durableTaskHandler, _delayBeforeStopping, expectedWaitForStop, () => { durableTaskHandler.WaitAny(tasksToWaitFor, orchestrationContext, _ => { }); }); }
public void StopAndInitiateDurableTaskOrReplay_UpdatesCurrentUtcDateTimeToNextOrchestratorStartedTimestamp_OnlyIfTimerCreatedAndFired(bool timerCreated, bool timerFired) { var history = DurableTestUtilities.MergeHistories( CreateOrchestratorStartedHistory(date: _startTime, isProcessed: true), CreateDurableTimerHistory(timerCreated: timerCreated, timerFired: timerFired, fireAt: _fireAt, restartTime: _restartTime, orchestratorStartedIsProcessed: false), CreateOrchestratorStartedHistory(date: _shouldNotHitTime, isProcessed: false) ); var context = new OrchestrationContext { History = history, CurrentUtcDateTime = _startTime }; var durableTaskHandler = new DurableTaskHandler(); var task = new DurableTimerTask(_fireAt); if (!timerCreated || !timerFired) { DurableTestUtilities.EmulateStop(durableTaskHandler); durableTaskHandler.StopAndInitiateDurableTaskOrReplay( task: task, context: context, noWait: false, output: _ => { Assert.True(false, "Unexpected output"); }, onFailure: _ => { }); Assert.Equal(_startTime, context.CurrentUtcDateTime); } else { durableTaskHandler.StopAndInitiateDurableTaskOrReplay(task: task, context: context, noWait: false, _ => { Assert.True(false, "Unexpected output"); }, errorMessage => { }); Assert.Equal(_restartTime, context.CurrentUtcDateTime); } VerifyCreateDurableTimerActionAdded(context, _fireAt); }
public void StopAndInitiateDurableTaskOrReplay_RetriesOnFailure() { const string FunctionName = "Function"; const string FunctionInput = "Input"; var history = new[] { new HistoryEvent { EventType = HistoryEventType.TaskScheduled, Name = FunctionName, EventId = 1 }, new HistoryEvent { EventType = HistoryEventType.TaskFailed, TaskScheduledId = 1 }, new HistoryEvent { EventType = HistoryEventType.TimerCreated, EventId = 2 }, new HistoryEvent { EventType = HistoryEventType.TimerFired, TimerId = 2 }, new HistoryEvent { EventType = HistoryEventType.TaskScheduled, Name = FunctionName, EventId = 3 }, new HistoryEvent { EventType = HistoryEventType.TaskCompleted, Result = "\"OK\"", TaskScheduledId = 3 }, }; var orchestrationContext = new OrchestrationContext { History = history }; var durableTaskHandler = new DurableTaskHandler(); var retryOptions = new RetryOptions(TimeSpan.FromSeconds(1), 2, null, null, null); object result = null; durableTaskHandler.StopAndInitiateDurableTaskOrReplay( new ActivityInvocationTask(FunctionName, FunctionInput, retryOptions), orchestrationContext, noWait: false, output: output => { result = output; }, onFailure: _ => { Assert.True(false, "Unexpected failure"); }, retryOptions: retryOptions ); Assert.Equal("OK", result); var(_, actions) = orchestrationContext.OrchestrationActionCollector.WaitForActions(new AutoResetEvent(initialState: true)); var action = (CallActivityWithRetryAction)actions.Single().Single(); Assert.Equal(FunctionName, action.FunctionName); Assert.Equal(FunctionInput, action.Input); Assert.NotEmpty(action.RetryOptions); }
public static void EmulateStop(DurableTaskHandler durableTaskHandler) { // In the actual usage, Stop is supposed to be invoked from another thread. // However, in order to simplify tests and avoid spawning threads, waiting for // them to finish, and handling potentially non-deterministic behavior, // we cheat a little and invoke Stop _before_ invoking WaitAll/WaitAny, // just to let WaitAll/WaitAny finish soon. // The fact that WaitAll/WaitAny _actually_ blocks until Stop is invoked // is verified by dedicated tests. durableTaskHandler.Stop(); }
public void StopAndInitiateDurableTaskOrReplay_OutputsDurableTimerTask_IfNoWaitRequested() { var history = CreateOrchestratorStartedHistory(date: _startTime, isProcessed: true); var context = new OrchestrationContext { History = history }; var allOutput = new List <DurableTimerTask>(); var durableTaskHandler = new DurableTaskHandler(); durableTaskHandler.StopAndInitiateDurableTaskOrReplay(task: new DurableTimerTask(_fireAt), context: context, noWait: true, output => { allOutput.Add((DurableTimerTask)output); }); Assert.Equal(_fireAt, allOutput.Single().FireAt); VerifyCreateDurableTimerActionAdded(context, _fireAt); }
public void CurrentUtcDateTime_UpdatesToNextOrchestratorStartedTimestamp_IfActivityFunctionCompleted(bool completed) { var history = DurableTestUtilities.MergeHistories( CreateOrchestratorStartedHistory(startTime: _startTime, isProcessed: true), CreateActivityHistory( name: FunctionName, scheduled: true, completed: completed, output: InvocationResultJson, date: _restartTime, orchestratorStartedIsProcessed: false) ); OrchestrationContext context = new OrchestrationContext { History = history, CurrentUtcDateTime = _startTime }; var durableTaskHandler = new DurableTaskHandler(); var allOutput = new List <object>(); if (completed) { history = DurableTestUtilities.MergeHistories(history, CreateActivityHistory( name: FunctionName, scheduled: true, completed: true, output: InvocationResultJson, date: _shouldNotHitTime, orchestratorStartedIsProcessed: false)); } else { DurableTestUtilities.EmulateStop(durableTaskHandler); } durableTaskHandler.StopAndInitiateDurableTaskOrReplay( new ActivityInvocationTask(FunctionName, FunctionInput), context, noWait: false, output: output => allOutput.Add(output), onFailure: _ => { }); if (completed) { Assert.Equal(_restartTime, context.CurrentUtcDateTime); } else { Assert.Equal(_startTime, context.CurrentUtcDateTime); } }
public void CurrentUtcDateTime_UpdatesToNextOrchestratorStartedTimestamp_IfTimestampsAreIdentical() { var history = DurableTestUtilities.MergeHistories( CreateActivityHistory( name: FunctionName, scheduled: true, completed: true, date: _startTime, output: InvocationResultJson, orchestratorStartedIsProcessed: true), CreateActivityHistory( name: FunctionName, scheduled: true, completed: true, date: _startTime, output: InvocationResultJson, orchestratorStartedIsProcessed: false), CreateActivityHistory( name: FunctionName, scheduled: true, completed: true, date: _shouldNotHitTime, output: InvocationResultJson, orchestratorStartedIsProcessed: false) ); var context = new OrchestrationContext { History = history, CurrentUtcDateTime = _startTime }; var willHitEvent = context.History.First( e => e.EventType == HistoryEventType.OrchestratorStarted && e.IsProcessed); var allOutput = new List <object>(); var durableTaskHandler = new DurableTaskHandler(); durableTaskHandler.StopAndInitiateDurableTaskOrReplay( new ActivityInvocationTask(FunctionName, FunctionInput), context, noWait: false, output: output => allOutput.Add(output), onFailure: _ => { }); Assert.Equal(_startTime, context.CurrentUtcDateTime); var shouldNotHitEvent = context.History.First( e => e.Timestamp.Equals(_shouldNotHitTime)); Assert.True(willHitEvent.IsProcessed); Assert.False(shouldNotHitEvent.IsProcessed); }
public void StopAndInitiateDurableTaskOrReplay_OutputsNothing_IfActivityNotCompleted( bool scheduled, bool completed) { var history = CreateHistory(scheduled: scheduled, completed: completed, output: InvocationResultJson); var orchestrationContext = new OrchestrationContext { History = history }; var durableTaskHandler = new DurableTaskHandler(); DurableTestUtilities.EmulateStop(durableTaskHandler); durableTaskHandler.StopAndInitiateDurableTaskOrReplay( new ActivityInvocationTask(FunctionName, FunctionInput), orchestrationContext, noWait: false, _ => { Assert.True(false, "Unexpected output"); }); VerifyCallActivityActionAdded(orchestrationContext); }
public void StopAndInitiateDurableTaskOrReplay_ReplaysActivity_IfActivityCompleted( bool scheduled, bool completed) { var history = CreateHistory(scheduled: scheduled, completed: completed, output: InvocationResultJson); var orchestrationContext = new OrchestrationContext { History = history }; var allOutput = new List <object>(); var durableTaskHandler = new DurableTaskHandler(); durableTaskHandler.StopAndInitiateDurableTaskOrReplay( task: new ActivityInvocationTask(FunctionName, FunctionInput), orchestrationContext, noWait: false, output => { allOutput.Add(output); }); VerifyCallActivityActionAdded(orchestrationContext); Assert.Equal(InvocationResult, allOutput.Single()); }
public void StopAndInitiateDurableTaskOrReplay_OutputsActivityInvocationTask_WhenNoWaitRequested( bool scheduled, bool completed) { var history = CreateHistory(scheduled: scheduled, completed: completed, output: InvocationResultJson); var orchestrationContext = new OrchestrationContext { History = history }; var allOutput = new List <ActivityInvocationTask>(); var durableTaskHandler = new DurableTaskHandler(); durableTaskHandler.StopAndInitiateDurableTaskOrReplay( new ActivityInvocationTask(FunctionName, FunctionInput), orchestrationContext, noWait: true, output => { allOutput.Add((ActivityInvocationTask)output); }); VerifyCallActivityActionAdded(orchestrationContext); Assert.Equal(FunctionName, allOutput.Single().FunctionName); }
public void StopAndInitiateDurableTaskOrReplay_OutputsError_IfActivityFailed() { const string FailureReason = "Failure reason"; var history = CreateHistory(scheduled: true, completed: false, failed: true, output: InvocationResultJson, failureReason: FailureReason); var orchestrationContext = new OrchestrationContext { History = history }; var allErrors = new List <object>(); var durableTaskHandler = new DurableTaskHandler(); durableTaskHandler.StopAndInitiateDurableTaskOrReplay( task: new ActivityInvocationTask(FunctionName, FunctionInput), orchestrationContext, noWait: false, output: _ => { Assert.True(false, "Unexpected output"); }, onFailure: reason => { allErrors.Add(reason); }); VerifyCallActivityActionAdded(orchestrationContext); Assert.Equal(FailureReason, allErrors.Single()); }
public void StopAndInitiateDurableTaskOrReplay_OutputsNothing_IfNoWaitNotRequested(bool timerCreated, bool timerFired) { var history = DurableTestUtilities.MergeHistories( CreateOrchestratorStartedHistory(date: _startTime, isProcessed: true), CreateDurableTimerHistory(timerCreated: timerCreated, timerFired: timerFired, fireAt: _fireAt, restartTime: _restartTime, orchestratorStartedIsProcessed: false) ); var context = new OrchestrationContext { History = history }; var durableTaskHandler = new DurableTaskHandler(); if (!timerCreated || !timerFired) { DurableTestUtilities.EmulateStop(durableTaskHandler); } durableTaskHandler.StopAndInitiateDurableTaskOrReplay(task: new DurableTimerTask(_fireAt), context: context, noWait: false, _ => { Assert.True(false, "Unexpected output"); }); VerifyCreateDurableTimerActionAdded(context, _fireAt); }
public void StopAndInitiateDurableTaskOrReplay_WaitsForStop_IfActivityNotCompleted(bool scheduledAndCompleted, bool expectedWaitForStop) { var durableTaskHandler = new DurableTaskHandler(); var history = CreateHistory( scheduled: scheduledAndCompleted, completed: scheduledAndCompleted, output: InvocationResultJson); var orchestrationContext = new OrchestrationContext { History = history }; DurableTestUtilities.VerifyWaitForDurableTasks( durableTaskHandler, _delayBeforeStopping, expectedWaitForStop, () => { durableTaskHandler.StopAndInitiateDurableTaskOrReplay( new ActivityInvocationTask(FunctionName, FunctionInput), orchestrationContext, noWait: false, _ => { }); }); }
public void StopAndCreateTimerOrContinue_WaitsUntilTimerFires_IfNoWaitNotRequested(bool timerCreated, bool timerFired, bool expectedWaitForStop) { var history = DurableTestUtilities.MergeHistories( CreateOrchestratorStartedHistory(date: _startTime, isProcessed: true), CreateDurableTimerHistory(timerCreated: timerCreated, timerFired: timerFired, fireAt: _fireAt, restartTime: _restartTime, orchestratorStartedIsProcessed: false) ); var context = new OrchestrationContext { History = history, CurrentUtcDateTime = _startTime }; var durableTaskHandler = new DurableTaskHandler(); DurableTestUtilities.VerifyWaitForDurableTasks( durableTaskHandler, delayBeforeStopping: _longInterval, expectedWaitForStop: expectedWaitForStop, () => { durableTaskHandler.StopAndInitiateDurableTaskOrReplay(task: new DurableTimerTask(_fireAt), context: context, noWait: false, _ => { Assert.True(false, "Unexpected output"); }); }); }
public void WaitAny_OutputsEarliestCompletedTask_WhenAnyTaskCompleted(bool completed) { var history = DurableTestUtilities.MergeHistories( CreateOrchestratorStartedHistory(date: _startTime, isProcessed: true), CreateActivityHistory("FunctionA", scheduled: true, restartTime: _restartTime, completed: completed, output: "\"Result1\"", orchestratorStartedIsProcessed: false), CreateActivityHistory("FunctionA", scheduled: false, completed: false, output: "\"Result2\""), CreateDurableTimerHistory(timerCreated: true, timerFired: true, fireAt: _fireAt, restartTime: _restartTime, orchestratorStartedIsProcessed: false) ); var orchestrationContext = new OrchestrationContext { History = history }; var firedTimer = new DurableTimerTask(_fireAt); var completedActivity = new ActivityInvocationTask("FunctionA", FunctionInput); var tasksToWaitFor = new ReadOnlyCollection <DurableTask>( new DurableTask[] { completedActivity, new ActivityInvocationTask("FunctionA", FunctionInput), firedTimer }); var allOutput = new List <object>(); var durableTaskHandler = new DurableTaskHandler(); durableTaskHandler.WaitAny(tasksToWaitFor, orchestrationContext, output => { allOutput.Add(output); }); if (completed) { Assert.Equal(new[] { completedActivity }, allOutput); } else { Assert.Equal(new[] { firedTimer }, allOutput); } VerifyNoOrchestrationActionAdded(orchestrationContext); }
public void WaitAll_And_WaitAny_StartNewActivityBatch(bool invokeWaitAll, bool invokeWaitAny, int expectedNumberOfBatches) { var orchestrationContext = new OrchestrationContext { History = new HistoryEvent[0] }; var durableTaskHandler = new DurableTaskHandler(); durableTaskHandler.StopAndInitiateDurableTaskOrReplay( new ActivityInvocationTask("Function", "Input"), orchestrationContext, noWait: true, output: _ => {}, onFailure: _ => {} ); if (invokeWaitAll) { durableTaskHandler.Stop(); // just to avoid the next call getting stuck waiting for a stop event durableTaskHandler.WaitAll(new DurableTask[0], orchestrationContext, output: _ => {}); } if (invokeWaitAny) { durableTaskHandler.Stop(); // just to avoid the next call getting stuck waiting for a stop event durableTaskHandler.WaitAny(new DurableTask[0], orchestrationContext, output: _ => {}); } durableTaskHandler.StopAndInitiateDurableTaskOrReplay( new ActivityInvocationTask("Function", "Input"), orchestrationContext, noWait: true, output: _ => {}, onFailure: _ => {} ); var(_, actions) = orchestrationContext.OrchestrationActionCollector.WaitForActions(new AutoResetEvent(initialState: true)); Assert.Equal(expectedNumberOfBatches, actions.Count); }
public void StopAndInitiateDurableTaskOrReplay_AddsActivityBatch_UnlessNoWait(bool noWait, int numberOfActions, int expectedNumberOfBatches) { var orchestrationContext = new OrchestrationContext { History = new HistoryEvent[0] }; var durableTaskHandler = new DurableTaskHandler(); for (var i = 0; i < numberOfActions; ++i) { durableTaskHandler.Stop(); // just to avoid the next call getting stuck waiting for a stop event durableTaskHandler.StopAndInitiateDurableTaskOrReplay( new ActivityInvocationTask("Function", "Input"), orchestrationContext, noWait: noWait, output: _ => {}, onFailure: _ => {} ); } var(_, actions) = orchestrationContext.OrchestrationActionCollector.WaitForActions(new AutoResetEvent(initialState: true)); Assert.Equal(expectedNumberOfBatches, actions.Count); }
public void WaitAll_OutputsTaskResults_WhenAllTasksCompleted( bool scheduled, bool completed) { var history = DurableTestUtilities.MergeHistories( // Emulate invoking the same function (FunctionA) twice. This is to make sure that // both invocations are accounted for, and both results are preserved separately. // Without this test, the history lookup algorithm in the WaitForActivityTasks method // could just look for the the first history event by function name, and this error // would not be detected. CreateOrchestratorStartedHistory(date: _startTime, isProcessed: true), CreateActivityHistory("FunctionA", scheduled: scheduled, completed: completed, output: "\"Result1\""), CreateActivityHistory("FunctionA", scheduled: scheduled, completed: completed, output: "\"Result2\""), CreateDurableTimerHistory(timerCreated: scheduled, timerFired: completed, fireAt: _fireAt, _restartTime, orchestratorStartedIsProcessed: false), CreateActivityHistory("FunctionB", scheduled: scheduled, completed: completed, output: "\"Result3\"") ); var orchestrationContext = new OrchestrationContext { History = history }; var tasksToWaitFor = new ReadOnlyCollection <DurableTask>( new DurableTask[] { new ActivityInvocationTask("FunctionA", FunctionInput), new ActivityInvocationTask("FunctionA", FunctionInput), new DurableTimerTask(_fireAt), new ActivityInvocationTask("FunctionB", FunctionInput) }); var allOutput = new List <object>(); var durableTaskHandler = new DurableTaskHandler(); durableTaskHandler.WaitAll(tasksToWaitFor, orchestrationContext, output => { allOutput.Add(output); }); Assert.Equal(new[] { "Result1", "Result2", "Result3" }, allOutput); VerifyNoOrchestrationActionAdded(orchestrationContext); }
public void CurrentUtcDateTime_UpdatesToNextOrchestratorStartedTimestamp_IfAnyActivitiesCompleted_WhenWaitAnyIsCalled(bool anyCompleted) { var activityFunctions = new Dictionary <string, bool>(); activityFunctions.Add("FunctionA", false); activityFunctions.Add("FunctionB", anyCompleted); activityFunctions.Add("FunctionC", false); var history = DurableTestUtilities.MergeHistories( CreateOrchestratorStartedHistory(startTime: _startTime, isProcessed: true), CreateNoWaitActivityHistory(scheduled: activityFunctions, restartTime: _restartTime, orchestratorStartedIsProcessed: false), CreateOrchestratorStartedHistory(startTime: _shouldNotHitTime, isProcessed: false) ); OrchestrationContext context = new OrchestrationContext { History = history, CurrentUtcDateTime = _startTime }; var tasksToWaitFor = new ReadOnlyCollection <ActivityInvocationTask>( new[] { "FunctionA", "FunctionB", "FunctionC" }.Select(name => new ActivityInvocationTask(name, FunctionInput)).ToArray()); var durableTaskHandler = new DurableTaskHandler(); var allOutput = new List <object>(); if (!anyCompleted) { DurableTestUtilities.EmulateStop(durableTaskHandler); } durableTaskHandler.WaitAny(tasksToWaitFor, context, output => allOutput.Add(output)); if (anyCompleted) { Assert.Equal(_restartTime, context.CurrentUtcDateTime); } else { Assert.Equal(_startTime, context.CurrentUtcDateTime); } }