private void UpdateDestinationChangeVectorHeartbeat(ReplicationMessageReply replicationBatchReply) { _lastSentDocumentEtag = replicationBatchReply.LastEtagAccepted; LastAcceptedChangeVector = replicationBatchReply.DatabaseChangeVector; if (_external == false) { var update = new UpdateSiblingCurrentEtag(replicationBatchReply, _waitForChanges); if (update.InitAndValidate(_lastDestinationEtag)) { // we intentionally not waiting here, there is nothing that depends on the timing on this, since this // is purely advisory. We just want to have the information up to date at some point, and we won't // miss anything much if this isn't there. _database.TxMerger.Enqueue(update).IgnoreUnobservedExceptions(); } } _lastDestinationEtag = replicationBatchReply.CurrentEtag; using (_database.DocumentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext documentsContext)) using (documentsContext.OpenReadTransaction()) { if (DocumentsStorage.ReadLastEtag(documentsContext.Transaction.InnerTransaction) != replicationBatchReply.LastEtagAccepted) { // We have changes that the other side doesn't have, this can be because we have writes // or because we have documents that were replicated to us. Either way, we need to sync // those up with the remove side, so we'll start the replication loop again. // We don't care if they are locally modified or not, because we filter documents that // the other side already have (based on the change vector). if ((DateTime.UtcNow - _lastDocumentSentTime).TotalMilliseconds > _parent.MinimalHeartbeatInterval) { _waitForChanges.Set(); } } } }
private void UpdateDestinationChangeVector(ReplicationMessageReply replicationBatchReply) { if (replicationBatchReply.MessageType == null) { throw new InvalidOperationException("MessageType on replication response is null. This is likely is a symptom of an issue, and should be investigated."); } _destinationLastKnownDocumentChangeVector.Clear(); UpdateDestinationChangeVectorHeartbeat(replicationBatchReply); }
private void UpdateDestinationChangeVectorHeartbeat(ReplicationMessageReply replicationBatchReply) { _lastSentDocumentEtag = Math.Max(_lastSentDocumentEtag, replicationBatchReply.LastEtagAccepted); _lastSentIndexOrTransformerEtag = Math.Max(_lastSentIndexOrTransformerEtag, replicationBatchReply.LastIndexTransformerEtagAccepted); _destinationLastKnownDocumentChangeVectorAsString = replicationBatchReply.DocumentsChangeVector.Format(); _destinationLastKnownIndexOrTransformerChangeVectorAsString = replicationBatchReply.IndexTransformerChangeVector.Format(); foreach (var changeVectorEntry in replicationBatchReply.DocumentsChangeVector) { _destinationLastKnownDocumentChangeVector[changeVectorEntry.DbId] = changeVectorEntry.Etag; } foreach (var changeVectorEntry in replicationBatchReply.IndexTransformerChangeVector) { _destinationLastKnownIndexOrTransformerChangeVector[changeVectorEntry.DbId] = changeVectorEntry.Etag; } //using (_documentsContext.OpenReadTransaction()) { if (DocumentsStorage.ReadLastEtag(_documentsContext.Transaction.InnerTransaction) != replicationBatchReply.LastEtagAccepted) { // We have changes that the other side doesn't have, this can be because we have writes // or because we have documents that were replicated to us. Either way, we need to sync // those up with the remove side, so we'll start the replication loop again. // We don't care if they are locally modified or not, because we filter documents that // the other side already have (based on the change vector). if ((DateTime.UtcNow - _lastDocumentSentTime).TotalMilliseconds > _minimalHeartbeatInterval) { _waitForChanges.SetByAsyncCompletion(); } } } if ( _database.IndexMetadataPersistence.ReadLastEtag(_configurationContext.Transaction.InnerTransaction) != replicationBatchReply.LastIndexTransformerEtagAccepted) { if ((DateTime.UtcNow - _lastIndexOrTransformerSentTime).TotalMilliseconds > _minimalHeartbeatInterval) { _waitForChanges.SetByAsyncCompletion(); } } }
public UpdateSiblingCurrentEtag(ReplicationMessageReply replicationBatchReply, AsyncManualResetEvent trigger) { _replicationBatchReply = replicationBatchReply; _trigger = trigger; }