public async Task <HttpResponseMessage> DocReplicatePost()
        {
            const int BatchSize = 512;

            var src = GetQueryStringValue("from");

            if (string.IsNullOrEmpty(src))
            {
                return(GetEmptyMessage(HttpStatusCode.BadRequest));
            }

            while (src.EndsWith("/"))
            {
                src = src.Substring(0, src.Length - 1);                // remove last /, because that has special meaning for Raven
            }
            if (string.IsNullOrEmpty(src))
            {
                return(GetEmptyMessage(HttpStatusCode.BadRequest));
            }

            var array = await ReadJsonArrayAsync();

            if (ReplicationTask != null)
            {
                ReplicationTask.HandleHeartbeat(src);
            }

            using (Database.DisableAllTriggersForCurrentThread())
            {
                string lastEtag = Etag.Empty.ToString();

                var docIndex = 0;

                while (docIndex < array.Length)
                {
                    using (Database.DocumentLock.Lock())
                    {
                        Database.TransactionalStorage.Batch(actions =>
                        {
                            for (var j = 0; j < BatchSize && docIndex < array.Length; j++, docIndex++)
                            {
                                var document = (RavenJObject)array[docIndex];
                                var metadata = document.Value <RavenJObject>("@metadata");
                                if (metadata[Constants.RavenReplicationSource] == null)
                                {
                                    // not sure why, old document from when the user didn't have replication
                                    // that we suddenly decided to replicate, choose the source for that
                                    metadata[Constants.RavenReplicationSource] = RavenJToken.FromObject(src);
                                }

                                lastEtag = metadata.Value <string>("@etag");
                                var id   = metadata.Value <string>("@id");
                                document.Remove("@metadata");

                                ReplicateDocument(actions, id, metadata, document, src);
                            }

                            SaveReplicationSource(src, lastEtag);
                        });
                    }
                }
            }

            return(GetEmptyMessage());
        }
        public override void Respond(IHttpContext context)
        {
            var src = context.Request.QueryString["from"];

            if (string.IsNullOrEmpty(src))
            {
                context.SetStatusToBadRequest();
                return;
            }
            while (src.EndsWith("/"))
            {
                src = src.Substring(0, src.Length - 1);                // remove last /, because that has special meaning for Raven
            }
            if (string.IsNullOrEmpty(src))
            {
                context.SetStatusToBadRequest();
                return;
            }
            var array = context.ReadJsonArray();

            if (ReplicationTask != null)
            {
                ReplicationTask.HandleHeartbeat(src);
            }
            using (Database.DisableAllTriggersForCurrentThread())
            {
                Database.TransactionalStorage.Batch(actions =>
                {
                    string lastEtag = Guid.Empty.ToString();
                    foreach (RavenJObject document in array)
                    {
                        var metadata = document.Value <RavenJObject>("@metadata");
                        if (metadata[Constants.RavenReplicationSource] == null)
                        {
                            // not sure why, old document from when the user didn't have replication
                            // that we suddenly decided to replicate, choose the source for that
                            metadata[Constants.RavenReplicationSource] = RavenJToken.FromObject(src);
                        }
                        lastEtag = metadata.Value <string>("@etag");
                        var id   = metadata.Value <string>("@id");
                        document.Remove("@metadata");
                        ReplicateDocument(actions, id, metadata, document, src);
                    }

                    var replicationDocKey   = Constants.RavenReplicationSourcesBasePath + "/" + src;
                    var replicationDocument = Database.Get(replicationDocKey, null);
                    var lastAttachmentId    = Guid.Empty;
                    if (replicationDocument != null)
                    {
                        lastAttachmentId =
                            replicationDocument.DataAsJson.JsonDeserialization <SourceReplicationInformation>().
                            LastAttachmentEtag;
                    }
                    Guid serverInstanceId;
                    if (Guid.TryParse(context.Request.QueryString["dbid"], out serverInstanceId) == false)
                    {
                        serverInstanceId = Database.TransactionalStorage.Id;
                    }
                    Database.Put(replicationDocKey, null,
                                 RavenJObject.FromObject(new SourceReplicationInformation
                    {
                        Source             = src,
                        LastDocumentEtag   = new Guid(lastEtag),
                        LastAttachmentEtag = lastAttachmentId,
                        ServerInstanceId   = serverInstanceId
                    }),
                                 new RavenJObject(), null);
                });
            }
        }
        public async Task <HttpResponseMessage> DocReplicatePost()
        {
            const int BatchSize = 512;

            var src         = GetQueryStringValue("from");
            var collections = GetQueryStringValue("collections");

            if (string.IsNullOrEmpty(src))
            {
                return(GetEmptyMessage(HttpStatusCode.BadRequest));
            }

            while (src.EndsWith("/"))
            {
                src = src.Substring(0, src.Length - 1);// remove last /, because that has special meaning for Raven
            }
            if (string.IsNullOrEmpty(src))
            {
                return(GetEmptyMessage(HttpStatusCode.BadRequest));
            }

            var array = await ReadJsonArrayAsync().ConfigureAwait(false);

            if (ReplicationTask != null)
            {
                ReplicationTask.HandleHeartbeat(src);
            }

            using (Database.DisableAllTriggersForCurrentThread())
            {
                var conflictResolvers = DocsReplicationConflictResolvers;

                string lastEtag = Etag.Empty.ToString();

                var docIndex = 0;
                var retries  = 0;
                while (retries < 3 && docIndex < array.Length)
                {
                    var lastIndex = docIndex;
                    using (Database.DocumentLock.Lock())
                    {
                        Database.TransactionalStorage.Batch(actions =>
                        {
                            for (var j = 0; j < BatchSize && docIndex < array.Length; j++, docIndex++)
                            {
                                var document = (RavenJObject)array[docIndex];
                                var metadata = document.Value <RavenJObject>("@metadata");
                                if (metadata[Constants.RavenReplicationSource] == null)
                                {
                                    // not sure why, old document from when the user didn't have replication
                                    // that we suddenly decided to replicate, choose the source for that
                                    metadata[Constants.RavenReplicationSource] = RavenJToken.FromObject(src);
                                }

                                lastEtag = metadata.Value <string>("@etag");
                                var id   = metadata.Value <string>("@id");
                                document.Remove("@metadata");

                                ReplicateDocument(actions, id, metadata, document, src, conflictResolvers);
                            }

                            SaveReplicationSource(src, lastEtag, array.Length, collections);
                            retries = lastIndex == docIndex ? retries : 0;
                        });
                    }

                    if (lastIndex == docIndex)
                    {
                        if (retries == 3)
                        {
                            Log.Warn("Replication processing did not end up replicating any documents for 3 times in a row, stopping operation", retries);
                        }
                        else
                        {
                            Log.Warn("Replication processing did not end up replicating any documents, due to possible storage error, retry number: {0}", retries);
                        }
                        retries++;
                    }
                }
            }

            return(GetEmptyMessage());
        }