/// <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) })); }
/// <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); }
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); }