static CompleteParsing ParseRecipients(StartParsing message, IActorRef sender, CancellationToken cancellation)
        {
            cancellation.ThrowIfCancellationRequested();

            using (var csvReader = new CsvReader(new StreamReader(File.OpenRead(message.DataPath))))
            {
                var batch = new List<IDictionary<string, string>>(BatchSize);
                int numberOfParsedRecipients = 0;

                while (csvReader.Read())
                {
                    cancellation.ThrowIfCancellationRequested();

                    var recipientValues =
                        csvReader.FieldHeaders.Zip(csvReader.CurrentRecord,
                            (h, v) => new KeyValuePair<string, string>(h, v)).ToDictionary(p => p.Key, p => p.Value);

                    numberOfParsedRecipients++;
                    batch.Add(recipientValues);

                    if (numberOfParsedRecipients == message.RecipientLimit)
                        break;

                    if (numberOfParsedRecipients >= FailAfter)
                        throw new CsvBadDataException("Simulated failure occured.");

                    if (batch.Count < BatchSize)
                        continue;

                    sender.Tell(new ProcessParsedRecipients(batch.ToArray()));
                    batch.Clear();
                }

                cancellation.ThrowIfCancellationRequested();

                if (batch.Count > 0)
                    sender.Tell(new ProcessParsedRecipients(batch.ToArray()));

                return new CompleteParsing(numberOfParsedRecipients);
            }
        }
        void OnStartParsing(StartParsing message)
        {
            logger.Debug("Started parsing...");

            var sender = Sender;
            Task.Factory.StartNew(() => ParseRecipients(message, sender, cancellationSource.Token),
                cancellationSource.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default)
                .PipeTo(Self, sender);

            Become(Parsing);
        }