void SyncInternal(Action <string> logger)
        {
            try
            {
                var next = _cache.GetCurrentVersion();

                while (true)
                {
                    long next1 = next;
                    var  items = Retry(() => _remote.ReadRecords(next1, BatchSize).ToArray(), logger);
                    if (items.Length == 0)
                    {
                        break;
                    }

                    // Check that versions are contiguous
                    var nextCopy = next;
                    var versions = items
                                   .Select((r, i) => new { Actual = r.Version, Expected = nextCopy + 1 + i })
                                   .ToArray();

                    if (!versions.All(v => v.Actual == v.Expected))
                    {
                        throw new InvalidOperationException("Versions are not contiguous.");
                    }

                    next = items.Max(m => m.Version);

                    _cache.AppendNonAtomic(items);
                    logger(string.Format("Downloaded {0} records", items.Length));

                    if (items.Length <= 4)
                    {
                        break;
                    }
                }
            }
            catch (Exception ex)
            {
                logger(ex.Message);
                Trace.WriteLine(ex);
            }
        }
        public void Can_continue_after_recreation()
        {
            foreach (var b in _batch)
            {
                _stream.TryAppend(b);
            }

            var version = _stream.GetCurrentVersion();

            _stream = null;
            FreeResources();

            _stream = InitializeAndGetTapeStorage();

            _stream.TryAppend(_batch[0]);

            var readings = _stream.ReadRecords(version, 1).ToArray();

            Assert.AreEqual(1, readings.Length, "Number of records mismatch");
            Assert.Greater(readings[0].Version, version, "Version mismatch");
            CollectionAssert.AreEqual(_batch[0], readings[0].Data, "Data mismatch");
        }
        public void Can_continue_after_recreation()
        {
            foreach (var b in _batch)
            {
                _stream.TryAppend(b);
            }

            var version = _stream.GetCurrentVersion();

            _stream = null;
            FreeResources();

            _stream = InitializeAndGetTapeStorage();

            _stream.TryAppend(_batch[0]);

            var readings = _stream.ReadRecords(version, 1).ToArray();

            Assert.AreEqual(1, readings.Length, "Number of records mismatch");
            Assert.Greater(readings[0].Version, version, "Version mismatch");
            CollectionAssert.AreEqual(_batch[0], readings[0].Data, "Data mismatch");
        }
        static void Observe(ITapeStream tapes, RedirectToDynamicEvent wire)
        {
            var date  = DateTime.MinValue;
            var watch = Stopwatch.StartNew();

            foreach (var record in tapes.ReadRecords(0, int.MaxValue))
            {
                var env = Streamer.ReadAsEnvelopeData(record.Data);
                if (date.Month != env.CreatedOnUtc.Month)
                {
                    date = env.CreatedOnUtc;
                    SystemObserver.Notify("Observing {0:yyyy-MM-dd} {1}", date, Math.Round(watch.Elapsed.TotalSeconds, 2));
                    watch.Restart();
                }
                foreach (var item in env.Items)
                {
                    var e = item.Content as IEvent;
                    if (e != null)
                    {
                        wire.InvokeEvent(e);
                    }
                }
            }
        }