/// <summary>
        /// Create orchestrator host
        /// </summary>
        /// <param name="graph">graph to be executed</param>
        /// <param name="jobHost">job host to use</param>
        /// <param name="maxParallel">max number of parallel task, if null or 0, there is no limit</param>
        public OrchestratorHost(GraphMap <TKey, TNode, TEdge> graph, IJobHost jobHost, int?maxParallel = null)
        {
            graph.Verify(nameof(graph)).IsNotNull();
            jobHost.Verify(nameof(jobHost)).IsNotNull();
            maxParallel.Verify(nameof(maxParallel)).Assert(x => x == null || x >= 0, "value must be greater then or equal to zero");

            _graph   = graph;
            _jobHost = jobHost;

            _runningKeys = new HashSet <TKey>(_graph.KeyCompare);
            _maxParallel = maxParallel;
            _semaphore   = maxParallel > 0 ? _semaphore = new SemaphoreSlim((int)maxParallel, (int)maxParallel) : null;
        }
        public OrchestratorBuilder(GraphMap <TKey, TNode, TEdge> graph)
        {
            graph.Verify(nameof(graph)).IsNotNull();

            Graph = graph;
        }