public async Task ProcessAsync(CancellationToken token)
        {
            var cursorService = new CursorService();
            var start         = await cursorService.GetValueAsync(_processor.CursorName);

            DateTimeOffset end;
            var            dependencyCursorNames = _processor.DependencyCursorNames;

            if (dependencyCursorNames.Any())
            {
                end = await cursorService.GetMinimumAsync(dependencyCursorNames);
            }
            else
            {
                end = DateTimeOffset.UtcNow;
            }

            _taskQueue.Start();
            var failureTask             = _taskQueue.FailureTask;
            var produceThenCompleteTask = ProduceThenCompleteAsync(start, end, token);
            var firstTask = await Task.WhenAny(failureTask, produceThenCompleteTask);

            if (firstTask == failureTask)
            {
                await await failureTask;
            }
            else
            {
                await produceThenCompleteTask;
            }
        }
        public async Task ProcessAsync(ProcessMode processMode, CancellationToken token)
        {
            var start = await _cursorService.GetValueAsync(_processor.CursorName);

            var end = await _cursorService.GetMinimumAsync(_processor.DependencyCursorNames);

            int commitCount;

            do
            {
                var commits = await _enumerator.GetCommitsAsync(
                    start,
                    end,
                    _processor.BatchSize);

                var entityCount = commits.Sum(x => x.Entities.Count);
                commitCount = commits.Count;

                if (commits.Any())
                {
                    var min = commits.Min(x => x.CommitTimestamp);
                    var max = commits.Max(x => x.CommitTimestamp);
                    start = max;
                    _logger.LogInformation(
                        "Fetched {CommitCount} commits ({EntityCount} {EntityName}) between {Min:O} and {Max:O}.",
                        commitCount,
                        entityCount,
                        typeof(TEntity).Name,
                        min,
                        max);
                }
                else
                {
                    _logger.LogInformation("No more commits were found within the bounds.");
                }

                switch (processMode)
                {
                case ProcessMode.Sequentially:
                    await ProcessSequentiallyAsync(commits, token);

                    break;

                case ProcessMode.TaskQueue:
                    await ProcessTaskQueueAsync(commits, token);

                    break;

                default:
                    throw new NotImplementedException();
                }

                if (commits.Any())
                {
                    _logger.LogInformation("Cursor {CursorName} moving to {Start:O}.", _processor.CursorName, start);
                    await _cursorService.SetValueAsync(_processor.CursorName, start);
                }
            }while (commitCount > 0);
        }