Example #1
0
        /// <summary>
        /// Asynchronously loads a snapshot.
        /// This call is protected with a circuit-breaker
        /// </summary>
        /// <param name="persistenceId">PersistenceId</param>
        /// <param name="criteria">Selection criteria</param>
        /// <returns>
        /// TBD
        /// </returns>
        protected override Task <SelectedSnapshot> LoadAsync(string persistenceId, SnapshotSelectionCriteria criteria)
        {
            persistenceId = IdNormalizer.Normalize(persistenceId);
            var query  = GetSnapshotQuery(persistenceId, criteria);
            var result = query
                         .Where(a => a.DocumentType == "snap")
                         .OrderByDescending(a => a.SequenceNr)
                         .ToList()//CosmosDB doesn't allow constructor invocation
                         .Select(a => {
                if (a.SerializerId.HasValue && a.Snapshot != null)
                {
                    if (a.SerializerId.Value != 1)
                    {
                        a.Snapshot = serialization.Deserialize(Convert.FromBase64String((string)a.Snapshot), a.SerializerId.Value, a.Manifest);
                    }
                    else
                    {
                        if (a.Snapshot is JObject)
                        {
                            a.Snapshot = JsonConvert.DeserializeObject(((JObject)a.Snapshot).ToString(Newtonsoft.Json.Formatting.None), Type.GetType(a.Manifest), new JsonSerializerSettings
                            {
                                TypeNameHandling = TypeNameHandling.All
                            }
                                                                       );
                        }
                    }
                }
                return(new SelectedSnapshot(new SnapshotMetadata(a.PersistenceId, a.SequenceNr,
                                                                 a.Timestamp.ToDateTime()), a.Snapshot));
            })
                         .FirstOrDefault();

            return(Task.FromResult(result));
        }
        protected override async Task <IImmutableList <Exception> > WriteMessagesAsync(IEnumerable <AtomicWrite> messages)
        {
            var messageList   = messages.ToList();
            var persistenceId = messageList.First().PersistenceId;

            persistenceId = IdNormalizer.Normalize(persistenceId);
            var cosmosDBWriteTasks = messageList.Select(async(message) =>
            {
                var persistentMessages = ((IImmutableList <IPersistentRepresentation>)message.Payload).ToArray();
                var journalEntries     = persistentMessages.Select(a => new JournalEntry(a, serialization)).ToList();
                foreach (JournalEntry entry in journalEntries)
                {
                    entry.Id            = IdNormalizer.Normalize(entry.Id);
                    entry.PersistenceId = IdNormalizer.Normalize(entry.PersistenceId);
                }

                var individualWriteTasks = journalEntries.Select(async a => await documentClient.Value.CreateDocumentAsync(journalCollection.Value.SelfLink, a, new RequestOptions()
                {
                    PartitionKey = new PartitionKey(persistenceId)
                }));
                return(await Task.WhenAll(individualWriteTasks.ToArray()));
            });

            await SetHighestSequenceId(messageList);

            return(await Task <ImmutableList <Exception> >
                   .Factory
                   .ContinueWhenAll(cosmosDBWriteTasks.ToArray(),
                                    tasks => tasks.Select(t => t.IsFaulted ? TryUnwrapException(t.Exception) : null)
                                    .ToImmutableList()));
        }
 private IQueryable <MetadataEntry> GetMetadataEntryQuery(string persistenceId)
 {
     persistenceId = IdNormalizer.Normalize(persistenceId);
     return(documentClient.Value.CreateDocumentQuery <MetadataEntry>(metadataCollection.Value.SelfLink, new FeedOptions {
         MaxItemCount = -1, PartitionKey = new PartitionKey(persistenceId)
     }));
 }
Example #4
0
        /// <summary>
        /// Deletes all snapshots matching provided <paramref name="criteria" />.
        /// This call is protected with a circuit-breaker
        /// </summary>
        /// <param name="persistenceId">persistenceId</param>
        /// <param name="criteria">Criteria</param>
        /// <returns>
        /// TBD
        /// </returns>
        protected override async Task DeleteAsync(string persistenceId, SnapshotSelectionCriteria criteria)
        {
            persistenceId = IdNormalizer.Normalize(persistenceId);
            var query       = GetSnapshotQuery(persistenceId, criteria);
            var documents   = query.ToList();
            var deleteTasks = documents.Select(async a =>
            {
                await documentClient.Value.DeleteDocumentAsync(
                    UriFactory.CreateDocumentUri(cosmosDBDatabase.Value.Id, snapShotCollection.Value.Id, a.Id), new RequestOptions()
                {
                    PartitionKey = new PartitionKey(persistenceId)
                });
            });

            await Task.WhenAll(deleteTasks.ToArray());
        }
        private async Task SetHighestSequenceId(List <AtomicWrite> messages)
        {
            var persistenceId = messages.Select(c => c.PersistenceId).First();

            persistenceId = IdNormalizer.Normalize(persistenceId);
            var highSequenceId = messages.Max(c => c.HighestSequenceNr);

            var metadataEntry = new MetadataEntry
            {
                Id            = persistenceId,
                PersistenceId = persistenceId,
                SequenceNr    = highSequenceId
            };

            await documentClient.Value.UpsertDocumentAsync(metadataCollection.Value.SelfLink, metadataEntry, new RequestOptions()
            {
                PartitionKey = new PartitionKey(persistenceId)
            });
        }
        public override Task ReplayMessagesAsync(IActorContext context, string persistenceId, long fromSequenceNr, long toSequenceNr, long max, Action <IPersistentRepresentation> recoveryCallback)
        {
            persistenceId = IdNormalizer.Normalize(persistenceId);
            // Limit allows only integer
            var limitValue = max >= int.MaxValue ? int.MaxValue : (int)max;

            // Do not replay messages if limit equal zero
            if (limitValue == 0)
            {
                return(Task.FromResult(false));
            }

            IQueryable <JournalEntry> query = GetJournalEntryQuery(persistenceId)
                                              .Where(a => a.PersistenceId == persistenceId &&
                                                     a.SequenceNr >= fromSequenceNr &&
                                                     a.SequenceNr <= toSequenceNr &&
                                                     a.DocumentType == "jrnl")
                                              .OrderBy(a => a.SequenceNr)
                                              .Take(limitValue);

            var documents = query.ToList();

            documents.ForEach(doc =>
            {
                if (doc.SerializerId.HasValue)
                {
                    if (doc.SerializerId.Value != 1)
                    {
                        doc.Payload = serialization.Deserialize(Convert.FromBase64String((string)doc.Payload), doc.SerializerId.Value, doc.Manifest);
                    }
                    else
                    {
                        if (doc.Payload is JObject)
                        {
                            doc.Payload = JsonConvert.DeserializeObject(((JObject)doc.Payload).ToString(Newtonsoft.Json.Formatting.None), Type.GetType(doc.Manifest));
                        }
                    }
                }
                recoveryCallback(new Persistent(doc.Payload, doc.SequenceNr, doc.PersistenceId, doc.Manifest, doc.IsDeleted, context.Sender));
            });

            return(Task.FromResult(0));
        }
        public override async Task <long> ReadHighestSequenceNrAsync(string persistenceId, long fromSequenceNr)
        {
            persistenceId = IdNormalizer.Normalize(persistenceId);
            var documentLink = UriFactory.CreateDocumentUri(cosmosDBDatabase.Value.Id, metadataCollection.Value.Id, persistenceId);

            try
            {
                var document = await documentClient.Value.ReadDocumentAsync(documentLink, new RequestOptions()
                {
                    PartitionKey = new PartitionKey(persistenceId)
                });

                return(((MetadataEntry)((dynamic)document.Resource)).SequenceNr);
            }
            catch (DocumentClientException ex)
            {
                return(0);
            }
        }
        protected override async Task DeleteMessagesToAsync(string persistenceId, long toSequenceNr)
        {
            persistenceId = IdNormalizer.Normalize(persistenceId);
            var query = GetJournalEntryQuery(persistenceId)
                        .Where(a => a.PersistenceId == persistenceId &&
                               a.DocumentType == "jrnl");

            if (toSequenceNr != long.MaxValue)
            {
                query = query.Where(a => a.SequenceNr <= toSequenceNr);
            }

            var deleteTasks = query.ToList().Select(async a =>
            {
                await documentClient.Value.DeleteDocumentAsync(
                    UriFactory.CreateDocumentUri(cosmosDBDatabase.Value.Id, journalCollection.Value.Id, a.Id), new RequestOptions()
                {
                    PartitionKey = new PartitionKey(persistenceId)
                });
            });

            await Task.WhenAll(deleteTasks);
        }
Example #9
0
        private IQueryable <SnapshotEntry> GetSnapshotQuery(string persistenceId, SnapshotSelectionCriteria criteria)
        {
            persistenceId = IdNormalizer.Normalize(persistenceId);
            IQueryable <SnapshotEntry> query = documentClient.Value.CreateDocumentQuery <SnapshotEntry>(snapShotCollection.Value.SelfLink, new FeedOptions {
                PartitionKey = new PartitionKey(persistenceId)
            });

            query = query.Where(a => a.PersistenceId == persistenceId);

            if (criteria.MaxSequenceNr > 0 && criteria.MaxSequenceNr < long.MaxValue)
            {
                query = query.Where(a => a.SequenceNr <= criteria.MaxSequenceNr);
            }

            if (criteria.MaxTimeStamp != DateTime.MinValue && criteria.MaxTimeStamp != DateTime.MaxValue)
            {
                var dateTimeAsJson = new DateTimeJsonObject(criteria.MaxTimeStamp);
                query = query.Where(a => a.Timestamp.Date < dateTimeAsJson.Date ||
                                    a.Timestamp.Ticks <= dateTimeAsJson.Ticks);
            }


            return(query);
        }