Example #1
0
        private async Task ProcessShardsAsync(IRecordProcessor processor)
        {
            try
            {
                var processShardsTask = new ConcurrentDictionary <Task <RecordResponse>, KShard>();

                await WatchForShardUpdates(processShardsTask);

                while (!_cancellationTokenSource.IsCancellationRequested)
                {
                    if (processShardsTask.Count > 0)
                    {
                        var task = await Task.WhenAny(processShardsTask.Select(m => m.Key)).WithCancellation(_cancellationTokenSource.Token);

                        KShard shard;
                        if (task != null && task.IsCompleted && !task.IsCanceled && !task.IsFaulted)
                        {
                            Interlocked.Add(ref _currentRecordsProcessing, 1);

                            if (processShardsTask.TryRemove(task, out shard))
                            {
                                var record = await task;

                                if (record != null && record.GetRecordsResponse.Records.Any())
                                {
                                    processor.Process(shard.ShardId, record.GetRecordsResponse.Records.LastOrDefault().SequenceNumber, shard.LastUpdateUtc, record.GetRecordsResponse.Records, SaveCheckpoint);

                                    if (record.GetRecordsResponse.NextShardIterator != null)
                                    {
                                        shard.UpdateShardInformation(record.GetRecordsResponse);

                                        var getRecordsTask = GetRecordResponse(shard, record.CancellationToken);

                                        processShardsTask.TryAdd(getRecordsTask, shard);
                                    }
                                }
                            }

                            Interlocked.Decrement(ref _currentRecordsProcessing);
                        }
                        else //the task was cancelled or faulted or there is some error
                        {
                            if (task != null)
                            {
                                processShardsTask.TryRemove(task, out shard);
                            }
                        }
                    }
                    else
                    {
                        await Task.Delay(2000); //sleep and hope that we get some cool shards to work with
                    }
                }
            }
            catch (OperationCanceledException e)
            {
                Log.Debug(e, "ProcessShardsAsync was cancelled");
            }
        }