コード例 #1
0
        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);
        }