Skip to content

Instantly share code, notes, and snippets.

@kpko
Created December 31, 2018 16:08
Show Gist options
  • Save kpko/f4c10ae7646d58038e0137278e6f49f9 to your computer and use it in GitHub Desktop.
Save kpko/f4c10ae7646d58038e0137278e6f49f9 to your computer and use it in GitHub Desktop.
Utility class to execute a workflow synchronously via WorkflowCore
public class SynchronousWorkflowExecutionResult
{
public string WorkflowId { get; set; }
public string WorkflowInstanceId { get; set; }
public string Reference { get; set; }
public LifeCycleEvent LastLifeCycleEvent { get; set; }
}
public class SynchronousWorkflowExecutionUtility
{
private readonly IWorkflowHost _host;
private readonly ILifeCycleEventHub _hub;
private readonly Dictionary<string, TaskCompletionSource<SynchronousWorkflowExecutionResult>> _completionSources = new Dictionary<string, TaskCompletionSource<SynchronousWorkflowExecutionResult>>();
public SynchronousWorkflowExecutionUtility(IWorkflowHost host, ILifeCycleEventHub hub)
{
_host = host;
_hub = hub;
_hub.Subscribe(HandleWorkflowEvent);
}
private void HandleWorkflowEvent(LifeCycleEvent @event)
{
switch (@event)
{
case WorkflowCompleted completed:
case WorkflowTerminated terminated:
case WorkflowError error:
if (_completionSources.ContainsKey(@event.WorkflowInstanceId))
{
var completionSource = _completionSources[@event.WorkflowInstanceId];
var result = (SynchronousWorkflowExecutionResult)completionSource.Task.AsyncState;
result.LastLifeCycleEvent = @event;
completionSource.SetResult(result);
}
break;
}
}
public async Task<SynchronousWorkflowExecutionResult> StartWorkflowAndWait<TData>(string workflowId, int? version = null, TData data = null, string reference = null) where TData : class, new()
{
var result = new SynchronousWorkflowExecutionResult()
{
WorkflowId = workflowId,
Reference = reference
};
var completionSource = new TaskCompletionSource<SynchronousWorkflowExecutionResult>(result);
var instanceId = await _host.StartWorkflow(workflowId, version, data, reference);
result.WorkflowInstanceId = instanceId;
_completionSources.Add(instanceId, completionSource);
return await completionSource.Task;
}
}
@araxis
Copy link

araxis commented Apr 16, 2021

thank you

@christopher-watanabe-snkeos
Copy link

christopher-watanabe-snkeos commented Jan 5, 2022

Hello all,

Though this was posted a few years ago, I wanted to ask about this implementation. My expectation was that a single instance of the workflow would run when calling StartWorkflowAndWait. However, for me the method call never returns, meaning the completionSource.Task never returns.

I've noticed as well that in the Console window, it seems the Host continues to poll for runnable workflows and unprocessed events. Perhaps it is this Task that never comes to an end? It sounds at least this way, that the Host is still running after the single workflow ends...

Any help is appreciated!

UPDATE: After I wrote this, some more Googling uncovered an issue here, namely that the WorkflowCompleted event never gets published by the SingleNodeEventHub when the workflow completes. A Pull Request has been made to fix this, but that was in Sept. 2021.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment