/// <summary>
                /// Loads stateful entities.
                /// </summary>
                /// <typeparam name="TEntity">The type of the entity.</typeparam>
                /// <param name="category">The category.</param>
                /// <param name="stateCategory">The state category.</param>
                /// <param name="kind">The reactive entity kind.</param>
                /// <param name="onLoading">The function is called for each loading entity.</param>
                /// <param name="onError">Function to report an error.</param>
                /// <param name="blobLogger">The blob logger to write raw recovery blobs to.</param>
                /// <param name="token">Cancellation token.</param>
                private void LoadStatefulEntities <TEntity>(
                    string category,
                    string stateCategory,
                    ReactiveEntityKind kind,
                    Action <TEntity, Stream> onLoading,
                    Action <string, TEntity, Exception> onError,
                    BlobLogger blobLogger,
                    CancellationToken token)
                    where TEntity : ReactiveEntity
                {
                    Debug.Assert(!string.IsNullOrEmpty(stateCategory), "Category should not be null or empty.");
                    Debug.Assert(onLoading != null, "onLoading should not be null.");

                    LoadDefinitions <TEntity>(category, kind, entity =>
                    {
                        var key = entity.Uri.ToCanonicalString();

                        var stopwatch = Stopwatch.StartNew();
                        if (!_reader.TryGetItemReader(stateCategory, key, out Stream stateStream))
                        {
                            // Stateless entity, i.e. no state has been written yet.
                            // At the very least, there will always be a header if anything has been written.
                            stateStream = null;
                        }
                        else
                        {
                            entity.SetMetric(EntityMetric.ReadState, stopwatch.Elapsed);

                            blobLogger.Append(stateCategory, key, stateStream);
                        }

                        using (stateStream) // notice null is fine for a C# using statement
                        {
                            try
                            {
                                onLoading(entity, stateStream);
                            }
                            catch (MitigationBailOutException) { throw; }
                            catch (Exception ex)
                            {
                                _engine.Parent.TraceSource.Recovery_LoadingStateFailure(_engine.Parent.Uri, category, stateCategory, key, ex.Message);

                                throw;
                            }
                        }
                    }, onError, blobLogger, token);
                }
Beispiel #2
0
        /// <summary>
        /// Gets an item reader for the specified <paramref name="category"/> and <paramref name="key"/>.
        /// </summary>
        /// <param name="reader">The reader to obtain the item reader from.</param>
        /// <param name="category">The category of the item to get a reader for.</param>
        /// <param name="key">The key of the item to get a reader for.</param>
        /// <returns>A <see cref="Stream"/> that can be used to read the item.</returns>
        /// <exception cref="InvalidOperationException">An item with the specified <paramref name="category"/> and <paramref name="key"/> does not exist.</exception>
        public static Stream GetItemReader(this IStateReader reader, string category, string key)
        {
            if (!reader.TryGetItemReader(category, key, out var stream))
            {
                throw new InvalidOperationException(FormattableString.Invariant($"Failed to load '{category}/{key}'."));
            }

            return(stream);
        }
Beispiel #3
0
        public void InMemoryStorageBasicWritingReadingTest()
        {
            InMemoryStorageProvider provider = new InMemoryStorageProvider();

            string category = "someCategory";
            string itemKey  = "someItem";
            string id       = "someId";

            byte[]   buffer1 = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
            byte[]   buffer2 = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0 };
            byte[][] buffers = new byte[][] { buffer1, buffer2 };

            for (int i = 0; i < 2; i++)
            {
                byte[] expectedBuffer = buffers[i];

                using (IStateWriter writer =
                           i == 0 ? provider.StartNewCheckpoint(id) : provider.UpdateCheckpoint(id))
                {
                    using (Stream stream = writer.GetItemWriter(category, itemKey))
                    {
                        stream.Write(expectedBuffer, 0, expectedBuffer.Length);
                    }

                    writer.CommitAsync().Wait();
                }

                IStateReader reader = null;
                try
                {
                    if (provider.TryReadCheckpoint(out id, out reader))
                    {
                        bool success = reader.TryGetItemReader(category, itemKey, out var stream);

                        Assert.IsTrue(success, "Could not get a reader for the requested item.");
                        Assert.AreEqual(expectedBuffer.Length, stream.Length);

                        byte[] actualBuffer = new byte[expectedBuffer.Length];

                        int byteRead = stream.Read(actualBuffer, 0, actualBuffer.Length);
                        Assert.AreEqual(byteRead, stream.Length);
                        CollectionAssert.AreEqual(expectedBuffer, actualBuffer);
                    }
                }
                finally
                {
                    reader?.Dispose();
                }
            }
        }
Beispiel #4
0
 public bool TryGetItemReader(string category, string key, out Stream stream)
 {
     LogStart(nameof(TryGetItemReader), category, key);
     try
     {
         return(_reader.TryGetItemReader(category, key, out stream));
     }
     catch (Exception ex) when(LogError(nameof(TryGetItemReader), ex, category, key))
     {
         throw;
     }
     finally
     {
         LogStop(nameof(TryGetItemReader), category, key);
     }
 }
            /// <summary>
            /// Get a stream to read the state of the item specified by the provided category and key.
            /// </summary>
            /// <param name="category">Category of the item to read state for.</param>
            /// <param name="key">Key of the item to read state for.</param>
            /// <param name="stream">Stream to read that state of the item from.</param>
            /// <returns><b>true</b> if the category and item key exists; otherwise, <b>false</b>.</returns>
            /// <exception cref="EngineUnloadedException">The request is rejected because the engine has been unloaded.</exception>
            /// <exception cref="ObjectDisposedException">The reader has been disposed.</exception>
            public bool TryGetItemReader(string category, string key, out Stream stream)
            {
                CheckAccess();

                return(_reader.TryGetItemReader(category, key, out stream));
            }
 /// <summary>
 /// Gets an item reader for the persisted entity state in the specified <paramref name="category"/> and with the specified <paramref name="key"/>.
 /// </summary>
 /// <param name="category">The category of the persisted entity state to read from.</param>
 /// <param name="key">The key of the persisted entity state to read from.</param>
 /// <param name="stream">The <see cref="Stream"/> used to read the item.</param>
 /// <returns><c>true</c> if an item with th specified <paramref name="category"/> and <paramref name="key"/> was found; otherwise, <c>false</c>.</returns>
 public bool TryGetItemReader(string category, string key, out Stream stream) => _reader.TryGetItemReader(_prefix + category, key, out stream);
Beispiel #7
0
        public void InMemoryStorageItemDeletionTest()
        {
            InMemoryStorageProvider provider = new InMemoryStorageProvider();

            string category = "someCategory";
            string itemKey  = "someItem";
            string id       = "someId";

            byte[] buffer = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

            using (IStateWriter writer = provider.StartNewCheckpoint(id))
            {
                using (Stream stream = writer.GetItemWriter(category, itemKey))
                {
                    stream.Write(buffer, 0, buffer.Length);
                }

                writer.CommitAsync().Wait();
            }

            IStateReader reader = null;

            try
            {
                if (provider.TryReadCheckpoint(out id, out reader))
                {
                    bool success = reader.TryGetItemReader(category, itemKey, out _);
                    Assert.IsTrue(success, "An stream could not be retrieved for the requested item.");
                }
                else
                {
                    Assert.Fail("Could not retrieve the checkpoint.");
                }
            }
            finally
            {
                reader?.Dispose();
            }

            using (IStateWriter writer = provider.UpdateCheckpoint(id))
            {
                writer.DeleteItem(category, itemKey);
                writer.CommitAsync().Wait();
            }

            reader = null;
            try
            {
                if (provider.TryReadCheckpoint(out id, out reader))
                {
                    bool success = reader.TryGetItemReader(category, itemKey, out _);
                    Assert.IsFalse(success, "An stream could be retrieved for the requested item.");
                }
                else
                {
                    Assert.Fail("Could not retrieve the checkpoint.");
                }
            }
            finally
            {
                reader?.Dispose();
            }
        }