public async Task SaveAsync(Aggregate aggregate, Action <IDictionary <string, object> > updateHeaders = null)
        {
            var headers = new Dictionary <string, object>();

            updateHeaders?.Invoke(headers);

            var streamName = getStreamName(aggregate.GetType(), aggregate.Id);

            var newEvents = aggregate.Changes.ToList();

            var originalVersion = aggregate.State.Version - newEvents.Count;
            var expectedVersion = originalVersion == InitialVersion
                                    ? ExpectedVersion.NoStream
                                    : originalVersion.Subtract(1);

            var events      = newEvents.Select(@event => (EventData)ToEventData(@event, headers));
            var eventToSave = events as IList <EventData> ?? events.ToList();

            if (eventToSave.Count < WritePageSize)
            {
                try
                {
                    await connection.AppendToStreamAsync(streamName, expectedVersion, eventToSave);
                }
                catch (Exception exception)
                {
                    log.Error(exception);
                }
            }
            else
            {
                try
                {
                    using (var transaction = await connection.StartTransactionAsync(streamName, expectedVersion))
                    {
                        var position = 0;

                        while (position < eventToSave.Count)
                        {
                            var pageEvents = eventToSave.Skip(position).Take(WritePageSize);
                            try
                            {
                                await transaction.WriteAsync(pageEvents);
                            }
                            catch (Exception e) when(e.Message.Contains("WrongExpectedVersion"))
                            {
                                log.Error(e);
                                // todo: throw appropriate exception e.g. AggregateVersionException
                            }
                            catch (Exception e)
                            {
                                log.Error(e);
                            }
                            position += WritePageSize;
                        }
                        await transaction.CommitAsync();
                    }
                }
                catch (Exception e)
                {
                    log.Error(e);
                }
            }
            aggregate.ClearCommittedEvents();
        }