/// <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<SelectedSnapshot> LoadAsync(string persistenceId, SnapshotSelectionCriteria criteria) { IEnumerable<CloudBlockBlob> blobs = _extension .BlobSnapshotStoreSettings .GetBlobClient(persistenceId) .GetContainerReference(_extension.BlobSnapshotStoreSettings.ContainerName) .ListBlobs(persistenceId,true,BlobListingDetails.All).Cast<CloudBlockBlob>(); var results = blobs.OrderByDescending(t => SnapshotVersionHelper.Parse(t.Name)); if (results.Count() > 0) { _log.Debug("Found {0} snapshots for {1}",results.Count(), persistenceId); foreach(CloudBlockBlob clob in results) { if (SnapshotVersionHelper.Parse(clob.Name) <= criteria.MaxSequenceNr && long.Parse(clob.Metadata["SnapshotTimestamp"]) <= criteria.MaxTimeStamp.Ticks) { using (var memoryStream = new MemoryStream()) { clob.DownloadToStream(memoryStream); var snapshot = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(memoryStream.ToArray()), typeof(SelectedSnapshot), _settings); return (SelectedSnapshot)snapshot; } } } return null; } else return null; }
protected override async Task<SelectedSnapshot> LoadAsync(string persistenceId, SnapshotSelectionCriteria criteria) { CloudTableClient tableClient = _extension.TableSnapshotStoreSettings.GetClient(persistenceId); CloudTable table = tableClient.GetTableReference(_extension.TableSnapshotStoreSettings.TableName); TableQuery<Snapshot> query = new TableQuery<Snapshot>().Where( TableQuery.CombineFilters( TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, persistenceId), TableOperators.And, TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.LessThanOrEqual, Snapshot.ToRowKey(criteria.MaxSequenceNr))) ); IEnumerable<Snapshot> results = table.ExecuteQuery(query).OrderByDescending(t=>t.SequenceNr); if (results.Count() > 0) { _log.Debug("Found snapshot of {0}", persistenceId); var result = results.First(); var snapshot = JsonConvert.DeserializeObject(result.SnapshotState, typeof(SelectedSnapshot),_settings); if (((SelectedSnapshot)snapshot).Metadata.Timestamp > criteria.MaxTimeStamp) return null; return (SelectedSnapshot)snapshot; } else return null; }
protected override Task <SelectedSnapshot> LoadAsync(string persistenceId, SnapshotSelectionCriteria criteria) { return(Equals(criteria, SnapshotSelectionCriteria.Latest) ? GetLatestSnapshot(persistenceId) : (Equals(criteria, SnapshotSelectionCriteria.None) ? null : GetSnapShotByCriteria(persistenceId, criteria))); }
protected override Task<SelectedSnapshot> LoadAsync(string persistenceId, SnapshotSelectionCriteria criteria) { // Create a Query with dynamic parameters string N1QLQueryString = "select `" + _CBBucket.Name + "`.* from `" + _CBBucket.Name + "` where DocumentType = 'SnapshotEntry' AND PersistenceId = $PersistenceId "; IQueryRequest N1QLQueryRequest = new QueryRequest() .AddNamedParameter("PersistenceId", persistenceId); string N1QLQueryOrderByClauseString = "ORDER BY SequenceNr DESC"; if (criteria.MaxSequenceNr > 0 && criteria.MaxSequenceNr < long.MaxValue) { N1QLQueryString += "AND SequenceNr <= $limit "; N1QLQueryOrderByClauseString = "ORDER BY SequenceNr DESC,"; N1QLQueryRequest.AddNamedParameter("limit",criteria.MaxSequenceNr); } if (criteria.MaxTimeStamp != DateTime.MinValue && criteria.MaxTimeStamp != DateTime.MaxValue) { N1QLQueryString += " AND Timestamp <= $timelimit "; N1QLQueryOrderByClauseString = "ORDER BY Timestamp DESC,"; N1QLQueryRequest.AddNamedParameter("timelimit", criteria.MaxTimeStamp.Ticks.ToString()); } N1QLQueryString += N1QLQueryOrderByClauseString.TrimEnd(',') + " LIMIT 1"; N1QLQueryRequest.Statement(N1QLQueryString).AdHoc(false); return taskLoadAsync(N1QLQueryRequest); }
protected override async Task <SelectedSnapshot> LoadAsync(string persistenceId, SnapshotSelectionCriteria criteria) { if (criteria.Equals(SnapshotSelectionCriteria.None)) { return(null); } var streamName = GetStreamName(persistenceId); if (!criteria.Equals(SnapshotSelectionCriteria.Latest)) { var result = await FindSnapshot(streamName, criteria.MaxSequenceNr, criteria.MaxTimeStamp); return(result.Snapshot); } var slice = await _conn.ReadStreamEventsBackwardAsync(streamName, StreamPosition.End, 1, false); if (slice == null || slice.Status != SliceReadStatus.Success || !slice.Events.Any()) { return(null); } return(slice.Events.Select(_snapshotAdapter.Adapt).First()); }
protected override Task <SelectedSnapshot> LoadAsync(string persistenceId, SnapshotSelectionCriteria criteria) { // Create a Query with dynamic parameters string N1QLQueryString = "select `" + _CBBucket.Name + "`.* from `" + _CBBucket.Name + "` where DocumentType = 'SnapshotEntry' AND PersistenceId = $PersistenceId "; IQueryRequest N1QLQueryRequest = new QueryRequest() .AddNamedParameter("PersistenceId", persistenceId); string N1QLQueryOrderByClauseString = "ORDER BY SequenceNr DESC"; if (criteria.MaxSequenceNr > 0 && criteria.MaxSequenceNr < long.MaxValue) { N1QLQueryString += "AND SequenceNr <= $limit "; N1QLQueryOrderByClauseString = "ORDER BY SequenceNr DESC,"; N1QLQueryRequest.AddNamedParameter("limit", criteria.MaxSequenceNr); } if (criteria.MaxTimeStamp != DateTime.MinValue && criteria.MaxTimeStamp != DateTime.MaxValue) { N1QLQueryString += " AND Timestamp <= $timelimit "; N1QLQueryOrderByClauseString = "ORDER BY Timestamp DESC,"; N1QLQueryRequest.AddNamedParameter("timelimit", criteria.MaxTimeStamp.Ticks.ToString()); } N1QLQueryString += N1QLQueryOrderByClauseString.TrimEnd(',') + " LIMIT 1"; N1QLQueryRequest.Statement(N1QLQueryString).AdHoc(false); return(taskLoadAsync(N1QLQueryRequest)); }
protected override Task DeleteAsync(string persistenceId, SnapshotSelectionCriteria criteria) { var filter = CreateRangeFilter(persistenceId, criteria); return(Task.Run(() => { _snapshotCollection.RemoveAll(x => filter(x)); })); }
/// <summary> /// TBD /// </summary> /// <param name="persistenceId">TBD</param> /// <param name="criteria">TBD</param> /// <returns>TBD</returns> protected override async Task DeleteAsync(string persistenceId, SnapshotSelectionCriteria criteria) { foreach (var metadata in GetSnapshotMetadata(persistenceId, criteria)) { await DeleteAsync(metadata); } }
public Recover(SnapshotSelectionCriteria fromSnapshot, long toSequenceNr = long.MaxValue, long replayMax = long.MaxValue) { FromSnapshot = fromSnapshot; ToSequenceNr = toSequenceNr; ReplayMax = replayMax; }
protected async override Task DeleteAsync(string persistenceId, SnapshotSelectionCriteria criteria) { ServiceEventSource.Current.Message($"Entering ServiceFabricSnapshotStore.{nameof(DeleteAsync)} PersistenceId: {persistenceId} "); if ((criteria.MaxSequenceNr > 0 && criteria.MaxSequenceNr < long.MaxValue) && (criteria.MaxTimeStamp != DateTime.MinValue && criteria.MaxTimeStamp != DateTime.MaxValue)) { using (var tx = this.StateManager.CreateTransaction()) { var snapshots = await this.StateManager.GetOrAddAsync <IReliableDictionary <string, SnapshotEntry> >(persistenceId); long FirstSequenceNumber = 0; for (long i = 0; i < criteria.MaxSequenceNr; i++) { var result = await snapshots.TryGetValueAsync(tx, $"{persistenceId}_{i}"); var snapShot = result.HasValue ? result.Value : null; if (snapShot.Timestamp > criteria.MaxTimeStamp.Ticks) { FirstSequenceNumber = i; await snapshots.TryRemoveAsync(tx, $"{persistenceId}_{i}"); } } await tx.CommitAsync(); } } }
protected override Task DeleteAsync(string persistenceId, SnapshotSelectionCriteria criteria) { var filter = CreateRangeFilter(persistenceId, criteria); Snapshots.RemoveAll(x => filter(x)); return(TaskEx.Completed); }
protected override async Task DeleteAsync(string persistenceId, SnapshotSelectionCriteria criteria) { switch (criteria.MaxSequenceNr) { case long.MaxValue when criteria.MaxTimeStamp == DateTime.MaxValue: await _dao.DeleteAllSnapshots(persistenceId); break; case long.MaxValue: await _dao.DeleteUpToMaxTimestamp(persistenceId, criteria .MaxTimeStamp); break; default: { if (criteria.MaxTimeStamp == DateTime.MaxValue) { await _dao.DeleteUpToMaxSequenceNr(persistenceId, criteria.MaxSequenceNr); } else { await _dao .DeleteUpToMaxSequenceNrAndMaxTimestamp( persistenceId, criteria.MaxSequenceNr, criteria .MaxTimeStamp); } break; } } }
protected override async Task DeleteAsync(string persistenceId, SnapshotSelectionCriteria criteria) { var filter = Filter.And( Filter.HasAncestor(RootKey(persistenceId)), Filter.GreaterThanOrEqual(SnapshotFields.SequenceNr, criteria.MinSequenceNr), Filter.LessThanOrEqual(SnapshotFields.SequenceNr, criteria.MaxSequenceNr) //,Filter.LessThanOrEqual(SnapshotFields.Timestamp, criteria.MaxTimeStamp.Ticks) ); // if (criteria.MinTimestamp.HasValue) // { // filter = Filter.And(filter, // Filter.GreaterThanOrEqual(SnapshotFields.Timestamp, criteria.MinTimestamp.Value.Ticks) // ); // } Query query = new Query(_snapshotKind) { Filter = filter, Order = { { JournalFields.SequenceNr, PropertyOrder.Types.Direction.Ascending } } //,Limit = (int) max }; var results = await _db.RunQueryAsync(query).ConfigureAwait(false); var timestampFiltered = results.Entities?.Where( e => e[SnapshotFields.SequenceNr].IntegerValue <= criteria.MaxSequenceNr && e[SnapshotFields.SequenceNr].IntegerValue >= criteria.MinSequenceNr && e[SnapshotFields.Timestamp].IntegerValue <= criteria.MaxTimeStamp.Ticks && e[SnapshotFields.Timestamp].IntegerValue >= criteria.MinTimestamp?.Ticks ); await _db.DeleteAsync(timestampFiltered); await CheckDeleteRootsnapshot(persistenceId, criteria.MaxSequenceNr, criteria.MaxTimeStamp.Ticks); }
protected override Task <SelectedSnapshot> LoadAsync(string persistenceId, SnapshotSelectionCriteria criteria) { var proxy = ActorProxy.Create <IServiceFabricSnapshotStore>(new ActorId(persistenceId), _servicefabricServiceUri); return(Task.FromResult(Map(proxy.SelectSnapshotAsync(criteria.MaxSequenceNr, criteria.MaxTimeStamp).Result))); }
protected override void Delete(string persistenceId, SnapshotSelectionCriteria criteria) { foreach (var metadata in GetSnapshotMetadata(persistenceId, criteria)) { Delete(metadata); } }
protected override async Task DeleteAsync(string persistenceId, SnapshotSelectionCriteria criteria) { try { CloudTableClient tableClient = _extension.TableSnapshotStoreSettings.GetClient(persistenceId); CloudTable table = tableClient.GetTableReference(_extension.TableSnapshotStoreSettings.TableName); TableQuery <Snapshot> query = new TableQuery <Snapshot>().Where( TableQuery.CombineFilters( TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, persistenceId), TableOperators.And, TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.LessThanOrEqual, Snapshot.ToRowKey(criteria.MaxSequenceNr))) ); IEnumerable <Snapshot> results = table.ExecuteQuery(query).OrderByDescending(t => t.SequenceNr); if (results.Count() > 0) { TableBatchOperation batchOperation = new TableBatchOperation(); foreach (Snapshot s in results) { batchOperation.Delete(s); } table.ExecuteBatch(batchOperation); } } catch (Exception ex) { _log.Error(ex, ex.Message); throw; } }
protected override Task<SelectedSnapshot> LoadAsync(string persistenceId, SnapshotSelectionCriteria criteria) { // Heurisitics: take 3 latest snapshots //TODO: convert 3 to configurable value var metas = GetSnapshotMetadata(persistenceId, criteria); return Task.FromResult(Load(metas, 3)); }
private static bool FilterBlobTimestamp(SnapshotSelectionCriteria criteria, CloudBlob x) { var ticks = FetchBlobTimestamp(x); return(ticks <= criteria.MaxTimeStamp.Ticks && (!criteria.MinTimestamp.HasValue || criteria.MinTimestamp.Value.Ticks >= ticks)); }
public void SnapshotStore_should_not_delete_snapshots_with_non_matching_upper_timestamp_bounds() { var snapshotMetadata = _metadata[3]; var criteria = new SnapshotSelectionCriteria(snapshotMetadata.SequenceNr, snapshotMetadata.Timestamp.Subtract(TimeSpan.FromTicks(1L)), 0L, new DateTime?()); var message = new DeleteSnapshots(Pid, criteria); var testProbe = CreateTestProbe(); Subscribe <DeleteSnapshots>(testProbe.Ref); SnapshotStore.Tell(message, _senderProbe.Ref); testProbe.ExpectMsg(message, new TimeSpan?()); _senderProbe.ExpectMsg <DeleteSnapshotsSuccess>(m => m.Criteria.Equals(criteria), new TimeSpan?()); SnapshotStore.Tell( new LoadSnapshot(Pid, new SnapshotSelectionCriteria(snapshotMetadata.SequenceNr, snapshotMetadata.Timestamp, 0L, new DateTime?()), long.MaxValue), _senderProbe.Ref); _senderProbe.ExpectMsg((Predicate <LoadSnapshotResult>)(result => { if (result.ToSequenceNr == long.MaxValue && result.Snapshot != null && result.Snapshot.Metadata.Equals(_metadata[3])) { return(result.Snapshot.Snapshot.ToString() == "s-4"); } return(false); }), new TimeSpan?()); }
protected override async Task DeleteAsync(string persistenceId, SnapshotSelectionCriteria criteria) { var filter = RowFilters.Chain ( RowFilters.ColumnQualifierExact(SnapshotMetaDataColumnQualifier), // this filter ensures that we only download snapshot metadata RowFilters.TimestampRange( ToUtc(criteria.MinTimestamp), ToUtc(criteria.MaxTimeStamp)?.AddMilliseconds(1) // add a milliseconds since the upper bound is exclusive ), RowFilters.CellsPerColumnLimit(1) ); var readRowsRequest = new ReadRowsRequest { TableNameAsTableName = _tableName, Filter = filter, Rows = GetRowSet(persistenceId, criteria.MinSequenceNr, criteria.MaxSequenceNr) }; var deleteMutations = await _bigtableClient .ReadRows(readRowsRequest) .Select(SnapshotMetadataFromBigtableRow) .Where(metadata => SatisfiesTimestampCriteria(criteria, metadata)) .Select(metadata => Mutations.CreateEntry(GetRowKey(persistenceId, metadata.SequenceNr), Mutations.DeleteFromRow())) .ToList() .ConfigureAwait(false); if (deleteMutations.Count > 0) { await _bigtableClient.MutateRowsAsync(_tableName, deleteMutations).ConfigureAwait(false); } }
protected override void Delete(string persistenceId, SnapshotSelectionCriteria criteria) { var sqlCommand = QueryBuilder.DeleteMany(persistenceId, criteria.MaxSequenceNr, criteria.MaxTimeStamp); CompleteCommand(sqlCommand); sqlCommand.ExecuteNonQuery(); }
protected override Task<SelectedSnapshot> LoadAsync(string persistenceId, SnapshotSelectionCriteria criteria) { var proxy = ActorProxy.Create<IServiceFabricSnapshotStore>(new ActorId(persistenceId), _servicefabricServiceUri); return Task.FromResult(Map(proxy.SelectSnapshotAsync(criteria.MaxSequenceNr, criteria.MaxTimeStamp).Result)); }
protected override Task DeleteAsync(string persistenceId, SnapshotSelectionCriteria criteria) { base.DeleteAsync(persistenceId, criteria); // we actually delete it properly, but act as if it failed var promise = new TaskCompletionSource <object>(); promise.SetException(new InvalidOperationException("Failed to delete snapshot for some reason.")); return(promise.Task); }
protected override Task <SelectedSnapshot> LoadAsync(string persistenceId, SnapshotSelectionCriteria criteria) { // Heurisitics: take 3 latest snapshots //TODO: convert 3 to configurable value var metas = GetSnapshotMetadata(persistenceId, criteria); return(Task.FromResult(Load(metas, 3))); }
protected override Task <SelectedSnapshot> LoadAsync(string persistenceId, SnapshotSelectionCriteria criteria) { var filter = CreateRangeFilter(persistenceId, criteria); var snapshot = Snapshots.Where(filter).OrderByDescending(x => x.SequenceNr).Take(1).Select(x => ToSelectedSnapshot(x)).FirstOrDefault(); return(Task.FromResult(snapshot)); }
public Task InterceptAsync(string persistenceId, SnapshotSelectionCriteria criteria) { CalledAt = DateTime.Now; WasCalled = true; PersistenceId = persistenceId; Criteria = criteria; return(Task.CompletedTask); }
public async Task InterceptAsync(string persistenceId, SnapshotSelectionCriteria criteria) { var result = await _predicate(persistenceId, criteria); if ((_negate && !result) || (!_negate && result)) { await _next.InterceptAsync(persistenceId, criteria); } }
/// <summary> /// TBD /// </summary> /// <param name="persistenceId">TBD</param> /// <param name="criteria">TBD</param> /// <returns>TBD</returns> protected override async Task DeleteAsync(string persistenceId, SnapshotSelectionCriteria criteria) { using (var connection = CreateDbConnection()) { await connection.OpenAsync(); await QueryExecutor.DeleteBatchAsync(connection, _pendingRequestsCancellation.Token, persistenceId, criteria.MaxSequenceNr, criteria.MaxTimeStamp); } }
protected override Task <SelectedSnapshot> LoadAsync(string persistenceId, SnapshotSelectionCriteria criteria) { var filter = CreateRangeFilter(persistenceId, criteria); return (_collection .Find(filter) .Project(x => ToSelectedSnapshot(x)) .FirstOrDefaultAsync()); }
protected override async Task<SelectedSnapshot> LoadAsync(string persistenceId, SnapshotSelectionCriteria criteria) { var snapshotEntry = repository.GetData<SnapshotEntry>(persistenceId, criteria.MaxSequenceNr, criteria.MaxTimeStamp); if (snapshotEntry == null) return (SelectedSnapshot) null; var snapshot = new SelectedSnapshot(new SnapshotMetadata(snapshotEntry.PersistenceId, snapshotEntry.SequenceNr, snapshotEntry.Timestamp), snapshotEntry.Snapshot); return snapshot; }
protected override Task<SelectedSnapshot> LoadAsync(string persistenceId, SnapshotSelectionCriteria criteria) { var filter = CreateRangeFilter(persistenceId, criteria); return _collection .Find(filter) .Project(x => ToSelectedSnapshot(x)) .FirstOrDefaultAsync(); }
protected override Task<SelectedSnapshot> LoadAsync(string persistenceId, SnapshotSelectionCriteria criteria) { var filter = CreateRangeFilter(persistenceId, criteria); return _snapshotCollection.Value .Find(filter) .SortByDescending(x => x.SequenceNr) .Limit(1) .Project(x => ToSelectedSnapshot(x)) .FirstOrDefaultAsync(); }
/// <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) { var query = GetSnapshotQuery(persistenceId, criteria); var documents = query.ToList(); var deleteTasks = documents.Select(async a => { await documentClient.Value.DeleteDocumentAsync( UriFactory.CreateDocumentUri(documentDbDatabase.Value.Id, snapShotCollection.Value.Id, a.Id)); }); await Task.WhenAll(deleteTasks.ToArray()); }
/// <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) { var query = GetSnapshotQuery(persistenceId, criteria); var result = query .OrderByDescending(a => a.SequenceNr) .ToList()//DocumentDb doesnt allow constructor invocation .Select(a => new SelectedSnapshot(new SnapshotMetadata(a.PersistenceId, a.SequenceNr, a.Timestamp.ToDateTime()), a.Snapshot)) .FirstOrDefault(); return(Task.FromResult(result)); }
protected override Task <SelectedSnapshot> LoadAsync(string persistenceId, SnapshotSelectionCriteria criteria) { var filter = CreateRangeFilter(persistenceId, criteria); return (_snapshotCollection.Value .Find(filter) .SortByDescending(x => x.SequenceNr) .Limit(1) .Project(x => ToSelectedSnapshot(x)) .FirstOrDefaultAsync()); }
protected override Task DeleteAsync(string persistenceId, SnapshotSelectionCriteria criteria) { _log.Debug("DeleteAsync() -persistenceId: {0}", persistenceId); // Create an empty SnapshotMetadata var metadata = new SnapshotMetadata(persistenceId, -1); return(RunWithStreamDispatcher(() => { Delete(metadata); return new object(); })); }
protected override async Task <SelectedSnapshot> LoadAsync(string persistenceId, SnapshotSelectionCriteria criteria) { var requestOptions = GenerateOptions(); BlobResultSegment results = null; using (var cts = new CancellationTokenSource(_settings.RequestTimeout)) { results = await Container.ListBlobsSegmentedAsync(SeqNoHelper.ToSnapshotSearchQuery(persistenceId), true, BlobListingDetails.Metadata, null, null, requestOptions, new OperationContext(), cts.Token); } // if we made it down here, the initial request succeeded. async Task <SelectedSnapshot> FilterAndFetch(BlobResultSegment segment) { // apply filter criteria var filtered = segment.Results .Where(x => x is CloudBlockBlob) .Cast <CloudBlockBlob>() .Where(x => FilterBlobSeqNo(criteria, x)) .Where(x => FilterBlobTimestamp(criteria, x)) .OrderByDescending(x => FetchBlobSeqNo(x)) // ordering matters - get highest seqNo item .ThenByDescending(x => FetchBlobTimestamp( x)) // if there are multiple snapshots taken at same SeqNo, need latest timestamp .FirstOrDefault(); // couldn't find what we were looking for. Onto the next part of the query // or return null to sender possibly. if (filtered == null) { return(null); } using (var cts = new CancellationTokenSource(_settings.RequestTimeout)) using (var memoryStream = new MemoryStream()) { await filtered.DownloadToStreamAsync(memoryStream, AccessCondition.GenerateIfExistsCondition(), GenerateOptions(), new OperationContext(), cts.Token); var snapshot = _serialization.SnapshotFromBytes(memoryStream.ToArray()); return(new SelectedSnapshot(new SnapshotMetadata(persistenceId, FetchBlobSeqNo(filtered)), snapshot.Data)); } } // TODO: see if there's ever a scenario where the most recent snapshots aren't in the beginning of the pagination list. var result = await FilterAndFetch(results); return(result); }
private static FilterDefinition<SnapshotEntry> CreateRangeFilter(string persistenceId, SnapshotSelectionCriteria criteria) { var builder = Builders<SnapshotEntry>.Filter; var filter = builder.Eq(x => x.PersistenceId, persistenceId); if (criteria.MaxSequenceNr > 0 && criteria.MaxSequenceNr < long.MaxValue) filter &= builder.Lte(x => x.SequenceNr, criteria.MaxSequenceNr); if (criteria.MaxTimeStamp != DateTime.MinValue && criteria.MaxTimeStamp != DateTime.MaxValue) filter &= builder.Lte(x => x.Timestamp, criteria.MaxTimeStamp.Ticks); return filter; }
/// <summary> /// Asynchronously loads snapshot with the highest sequence number for a persistent actor/view matching specified criteria. /// </summary> protected override async Task<SelectedSnapshot> LoadAsync(string persistenceId, SnapshotSelectionCriteria criteria) { using (var connection = CreateDbConnection()) { await connection.OpenAsync(); var sqlCommand = QueryBuilder.SelectSnapshot(persistenceId, criteria.MaxSequenceNr, criteria.MaxTimeStamp); CompleteCommand(sqlCommand, connection); var reader = await sqlCommand.ExecuteReaderAsync(_pendingRequestsCancellation.Token); try { return reader.Read() ? QueryMapper.Map(reader) : null; } finally { reader.Close(); } } }
/// <summary> /// Asynchronously loads snapshot with the highest sequence number for a persistent actor/view matching specified criteria. /// </summary> protected override Task<SelectedSnapshot> LoadAsync(string persistenceId, SnapshotSelectionCriteria criteria) { var sqlCommand = QueryBuilder.SelectSnapshot(persistenceId, criteria.MaxSequenceNr, criteria.MaxTimeStamp); CompleteCommand(sqlCommand); var tokenSource = GetCancellationTokenSource(); return sqlCommand .ExecuteReaderAsync(tokenSource.Token) .ContinueWith(task => { var reader = task.Result; try { return reader.Read() ? QueryMapper.Map(reader) : null; } finally { PendingOperations.Remove(tokenSource); reader.Close(); } }, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.AttachedToParent); }
protected override async Task<SelectedSnapshot> LoadAsync(string persistenceId, SnapshotSelectionCriteria criteria) { var connection = await GetConnection(); var streamName = GetStreamName(persistenceId); var requestedSnapVersion = (int)criteria.MaxSequenceNr; StreamEventsSlice slice = null; if (criteria.MaxSequenceNr == long.MaxValue) { requestedSnapVersion = StreamPosition.End; slice = await connection.ReadStreamEventsBackwardAsync(streamName, requestedSnapVersion, 1, false); } else { slice = await connection.ReadStreamEventsBackwardAsync(streamName, StreamPosition.End, requestedSnapVersion, false); } if (slice.Status == SliceReadStatus.StreamNotFound) { await connection.SetStreamMetadataAsync(streamName, ExpectedVersion.Any, StreamMetadata.Data); return null; } if (slice.Events.Any()) { _log.Debug("Found snapshot of {0}", persistenceId); if (requestedSnapVersion == StreamPosition.End) { var @event = slice.Events.First().OriginalEvent; return (SelectedSnapshot)_serializer.FromBinary(@event.Data, typeof(SelectedSnapshot)); } else { var @event = slice.Events.Where(t => t.OriginalEvent.EventNumber == requestedSnapVersion).First().OriginalEvent; return (SelectedSnapshot)_serializer.FromBinary(@event.Data, typeof(SelectedSnapshot)); } } return null; }
protected override async Task DeleteAsync(string persistenceId, SnapshotSelectionCriteria criteria) { await repository.Delete<SnapshotEntry>(persistenceId, criteria.MaxSequenceNr, criteria.MaxTimeStamp); }
protected override async Task DeleteAsync(string persistenceId, SnapshotSelectionCriteria criteria) { using (var connection = CreateDbConnection()) { await connection.OpenAsync(); var sqlCommand = QueryBuilder.DeleteMany(persistenceId, criteria.MaxSequenceNr, criteria.MaxTimeStamp); CompleteCommand(sqlCommand, connection); await sqlCommand.ExecuteNonQueryAsync(); } }
protected override Task<SelectedSnapshot> LoadAsync(string persistenceId, SnapshotSelectionCriteria criteria) { return Task.FromResult((SelectedSnapshot)null); }
private IEnumerable<SnapshotMetadata> GetSnapshotMetadata(string persistenceId, SnapshotSelectionCriteria criteria) { var snapshots = _snapshotDirectory .EnumerateFiles("snapshot-" + persistenceId + "-*", SearchOption.TopDirectoryOnly) .Select(ExtractSnapshotMetadata) .Where(metadata => metadata != null && criteria.IsMatch(metadata) && !_saving.Contains(metadata)); return snapshots; // guaranteed to be not null in previous constraint }
protected override void Delete(string persistenceId, SnapshotSelectionCriteria criteria) { var proxy = ActorProxy.Create<IServiceFabricSnapshotStore>(new ActorId(persistenceId), _servicefabricServiceUri); proxy.DeleteSnapshotManyAsync(criteria.MaxSequenceNr, criteria.MaxTimeStamp); }
public void SnapshotStore_should_not_delete_snapshots_with_non_matching_upper_timestamp_bounds() { var md = Metadata[3]; var criteria = new SnapshotSelectionCriteria(md.SequenceNr, md.Timestamp.Subtract(TimeSpan.FromTicks(1))); var command = new DeleteSnapshots(Pid, criteria); var sub = CreateTestProbe(); Subscribe<DeleteSnapshots>(sub.Ref); SnapshotStore.Tell(command, _senderProbe.Ref); sub.ExpectMsg(command); _senderProbe.ExpectMsg<DeleteSnapshotsSuccess>(m => m.Criteria.Equals(criteria)); SnapshotStore.Tell(new LoadSnapshot(Pid, new SnapshotSelectionCriteria(md.SequenceNr, md.Timestamp), long.MaxValue), _senderProbe.Ref); _senderProbe.ExpectMsg<LoadSnapshotResult>(result => result.ToSequenceNr == long.MaxValue && result.Snapshot != null && result.Snapshot.Metadata.Equals(Metadata[3]) && result.Snapshot.Snapshot.ToString() == "s-4"); }
public DeleteSnapshots(SnapshotSelectionCriteria criteria) { Criteria = criteria; }
public void PersistentActor_with_a_failing_snapshot_should_receive_failure_message_when_bulk_deleting_snapshots_fails() { var pref = Sys.ActorOf(Props.Create(() => new DeleteSnapshotTestActor(Name, TestActor))); ExpectMsg<RecoveryCompleted>(); pref.Tell(new Cmd("hello")); ExpectMsg(1L); pref.Tell(new Cmd("hola")); ExpectMsg(2L); var criteria = new SnapshotSelectionCriteria(10); pref.Tell(new DeleteSnapshots(criteria)); ExpectMsg<DeleteSnapshotsFailure>(m => m.Criteria.Equals(criteria) && m.Cause.Message.Contains("Failed to delete")); }
/// <summary> /// Asynchronously loads a snapshot. /// </summary> protected abstract Task<SelectedSnapshot> LoadAsync(string persistenceId, SnapshotSelectionCriteria criteria);
/// <summary> /// Deletes all snapshots matching provided <paramref name="criteria"/>. /// </summary> protected abstract Task DeleteAsync(string persistenceId, SnapshotSelectionCriteria criteria);
protected override void Delete(string persistenceId, SnapshotSelectionCriteria criteria) {}
/// <summary> /// Deletes all snapshots matching provided <paramref name="criteria"/>. /// </summary> protected abstract void Delete(string persistenceId, SnapshotSelectionCriteria criteria);
protected override Task DeleteAsync(string persistenceId, SnapshotSelectionCriteria criteria) { base.DeleteAsync(persistenceId, criteria); // we actually delete it properly, but act as if it failed var promise = new TaskCompletionSource<object>(); promise.SetException(new ApplicationException("Failed to delete snapshot for some reason.")); return promise.Task; }
protected override Task DeleteAsync(string persistenceId, SnapshotSelectionCriteria criteria) { var filter = CreateRangeFilter(persistenceId, criteria); return _snapshotCollection.Value.DeleteManyAsync(filter); }
protected override Task DeleteAsync(string persistenceId, SnapshotSelectionCriteria criteria) { return Flop(); }