private void ActivatePendingDocuments() { using (_database.DisableAllTriggersForCurrentThread()) { var revisionKeys = PendingRevisionsIndex.GetRevisionsRequiringActivation(_database); foreach (var revisionkey in revisionKeys) { _log.Info("Activating Temporal Document {0}", revisionkey); // Establish a new transaction var transactionInformation = new TransactionInformation { Id = Guid.NewGuid().ToString(), Timeout = TimeSpan.FromMinutes(1) }; // Get the current key from the revision key var currentKey = revisionkey.Substring(0, revisionkey.IndexOf(TemporalConstants.TemporalKeySeparator, StringComparison.Ordinal)); // Mark the document as non-pending _database.SetDocumentMetadata(revisionkey, transactionInformation, TemporalMetadata.RavenDocumentTemporalPending, false); // Mark it in the history also Etag historyEtag; var history = _database.GetTemporalHistoryFor(currentKey, transactionInformation, out historyEtag); history.Revisions.First(x => x.Key == revisionkey).Pending = false; _database.SaveTemporalHistoryFor(currentKey, history, transactionInformation, historyEtag); // Load the new revisions document var newRevisionDoc = _database.Get(revisionkey, transactionInformation); var temporal = newRevisionDoc.Metadata.GetTemporalMetadata(); if (temporal.Deleted) { // When the revision is a deletion, delete the current document _database.Delete(currentKey, null, transactionInformation); } else { // Prepare the current document metadata newRevisionDoc.Metadata.Remove(TemporalMetadata.RavenDocumentTemporalDeleted); newRevisionDoc.Metadata.Remove(TemporalMetadata.RavenDocumentTemporalPending); newRevisionDoc.Metadata.Remove("@id"); temporal.Status = TemporalStatus.Current; temporal.RevisionNumber = int.Parse(newRevisionDoc.Key.Split('/').Last()); // Copy the revision to the current document _database.Put(currentKey, null, newRevisionDoc.DataAsJson, newRevisionDoc.Metadata, transactionInformation); } // Commit the transaction _database.Commit(transactionInformation.Id); } } }
public static int PutRevision(this DocumentDatabase database, string key, RavenJObject document, RavenJObject metadata, TransactionInformation transactionInformation, DateTime now, bool deleted = false) { Log.Debug("Putting new temporal revision for {0}", key); // The revision is a copy of the document. var revisionDocument = new RavenJObject(document); var revisionMetadata = new RavenJObject(metadata); // Set metadata on the revision var temporal = revisionMetadata.GetTemporalMetadata(); var effective = temporal.EffectiveStart.GetValueOrDefault(); temporal.Status = TemporalStatus.Revision; temporal.Deleted = deleted; temporal.Pending = effective > now; // Store the revision var newRevisionDoc = database.Put(key + TemporalConstants.TemporalKeySeparator, null, revisionDocument, revisionMetadata, transactionInformation); // Get the revision number that was generated var revisionNumber = int.Parse(newRevisionDoc.Key.Split('/').Last()); // Get the history doc and add this revision Etag historyEtag; var history = database.GetTemporalHistoryFor(key, transactionInformation, out historyEtag); history.AddRevision(newRevisionDoc.Key, temporal); if (revisionNumber > 1) { // Artifact any revisions that already exist on or after the new effective date var futureRevisions = history.Revisions.Where(x => x.Key != newRevisionDoc.Key && x.Status == TemporalStatus.Revision && x.EffectiveStart >= effective); foreach (var revisionInfo in futureRevisions) { // in the history revisionInfo.Status = TemporalStatus.Artifact; // on the revision doc database.SetDocumentMetadata(revisionInfo.Key, transactionInformation, TemporalMetadata.RavenDocumentTemporalStatus, TemporalStatus.Artifact.ToString()); } // Update the until date of the last revison prior to this one var lastRevision = history.Revisions.LastOrDefault(x => x.Key != newRevisionDoc.Key && x.Status == TemporalStatus.Revision && x.EffectiveStart < effective); if (lastRevision != null) { // in the history lastRevision.EffectiveUntil = effective; lastRevision.AssertedUntil = now; // on the revision doc var md = new Dictionary <string, RavenJToken> { { TemporalMetadata.RavenDocumentTemporalEffectiveUntil, effective }, { TemporalMetadata.RavenDocumentTemporalAssertedUntil, now } }; database.SetDocumentMetadata(lastRevision.Key, transactionInformation, md); } } // Update the history doc database.SaveTemporalHistoryFor(key, history, transactionInformation, historyEtag); // Reset the activation timer with each put. // This is so future revisions can become current without having to constantly poll. database.StartupTasks.OfType <TemporalActivator>().Single().ResetTimer(effective.UtcDateTime, now); // Return the revision number return(revisionNumber); }