private void UpdateStreamHeadInBackgroundThread(string bucketId, string streamId, int streamRevision, int eventsCount)
 {
     StartBackgroundThread(() =>
     {
         try
         {
             BsonDocument streamHeadId = GetStreamHeadId(bucketId, streamId);
             PersistedStreamHeads.UpdateOne(
                 Builders <BsonDocument> .Filter.Eq(MongoStreamHeadFields.Id, streamHeadId),
                 Builders <BsonDocument> .Update
                 .Set(MongoStreamHeadFields.HeadRevision, streamRevision)
                 .Inc(MongoStreamHeadFields.SnapshotRevision, 0)
                 .Inc(MongoStreamHeadFields.Unsnapshotted, eventsCount),
                 new UpdateOptions()
             {
                 IsUpsert = true
             }
                 );
         }
         catch (OutOfMemoryException ex)
         {
             Logger.LogError(ex, "OutOfMemoryException:");
             throw;
         }
         catch (Exception ex)
         {
             //It is safe to ignore transient exception updating stream head.
             Logger.LogWarning(ex, "Ignored Exception '{exception}' when upserting the stream head Bucket Id [{id}] StreamId[{streamId}].\n", ex.GetType().Name, bucketId, streamId);
         }
     });
 }
Example #2
0
        public virtual bool AddSnapshot(ISnapshot snapshot)
        {
            CheckIfSnapshotEnabled();

            if (snapshot == null)
            {
                return(false);
            }

            if (Logger.IsDebugEnabled)
            {
                Logger.Debug(Messages.AddingSnapshot, snapshot.StreamId, snapshot.BucketId, snapshot.StreamRevision);
            }

            try
            {
                BsonDocument mongoSnapshot = snapshot.ToMongoSnapshot(_serializer);
                var          query         = Builders <BsonDocument> .Filter.Eq(MongoShapshotFields.Id, mongoSnapshot[MongoShapshotFields.Id]);

                var update = Builders <BsonDocument> .Update.Set(MongoShapshotFields.Payload, mongoSnapshot[MongoShapshotFields.Payload]);

                // Doing an upsert instead of an insert allows us to overwrite an existing snapshot and not get stuck with a
                // stream that needs to be snapshotted because the insert fails and the SnapshotRevision isn't being updated.
                PersistedSnapshots.UpdateOne(query, update, new UpdateOptions()
                {
                    IsUpsert = true
                });

                // More commits could have been made between us deciding that a snapshot is required and writing it so just
                // resetting the Unsnapshotted count may be a little off. Adding snapshots should be a separate process so
                // this is a good chance to make sure the numbers are still in-sync - it only adds a 'read' after all ...
                BsonDocument streamHeadId = GetStreamHeadId(snapshot.BucketId, snapshot.StreamId);
                StreamHead   streamHead   = PersistedStreamHeads.Find(Builders <BsonDocument> .Filter.Eq(MongoStreamHeadFields.Id, streamHeadId))
                                            .First()
                                            .ToStreamHead();

                int unsnapshotted = streamHead.HeadRevision - snapshot.StreamRevision;

                PersistedStreamHeads.UpdateOne(
                    Builders <BsonDocument> .Filter
                    .Eq(MongoStreamHeadFields.Id, streamHeadId),
                    Builders <BsonDocument> .Update
                    .Set(MongoStreamHeadFields.SnapshotRevision, snapshot.StreamRevision)
                    .Set(MongoStreamHeadFields.Unsnapshotted, unsnapshotted)
                    );

                return(true);
            }
            catch (Exception)
            {
                return(false);
            }
        }