in src/DurableTask.Emulator/LocalOrchestrationService.cs [246:325]
public async Task<OrchestrationState> WaitForOrchestrationAsync(
string instanceId,
string executionId,
TimeSpan timeout,
CancellationToken cancellationToken)
{
if (string.IsNullOrWhiteSpace(executionId))
{
executionId = string.Empty;
}
string key = instanceId + "_" + executionId;
if (!this.orchestrationWaiters.TryGetValue(key, out TaskCompletionSource<OrchestrationState> tcs))
{
tcs = new TaskCompletionSource<OrchestrationState>();
if (!this.orchestrationWaiters.TryAdd(key, tcs))
{
this.orchestrationWaiters.TryGetValue(key, out tcs);
}
if (tcs == null)
{
throw new InvalidOperationException("Unable to get tcs from orchestrationWaiters");
}
}
// might have finished already
lock (this.thisLock)
{
if (this.instanceStore.ContainsKey(instanceId))
{
Dictionary<string, OrchestrationState> stateMap = this.instanceStore[instanceId];
if (stateMap != null && stateMap.Count > 0)
{
OrchestrationState state = null;
if (string.IsNullOrWhiteSpace(executionId))
{
IOrderedEnumerable<OrchestrationState> sortedStateMap = stateMap.Values.OrderByDescending(os => os.CreatedTime);
state = sortedStateMap.First();
}
else
{
if (stateMap.ContainsKey(executionId))
{
state = this.instanceStore[instanceId][executionId];
}
}
if (state != null
&& state.OrchestrationStatus != OrchestrationStatus.Running
&& state.OrchestrationStatus != OrchestrationStatus.Pending)
{
// if only master id was specified then continueAsNew is a not a terminal state
if (!(string.IsNullOrWhiteSpace(executionId) && state.OrchestrationStatus == OrchestrationStatus.ContinuedAsNew))
{
tcs.TrySetResult(state);
}
}
}
}
}
CancellationTokenSource cts = CancellationTokenSource.CreateLinkedTokenSource(
cancellationToken,
this.cancellationTokenSource.Token);
Task timeOutTask = Task.Delay(timeout, cts.Token);
Task ret = await Task.WhenAny(tcs.Task, timeOutTask);
if (ret == timeOutTask)
{
throw new TimeoutException("timed out or canceled while waiting for orchestration to complete");
}
cts.Cancel();
return await tcs.Task;
}