/// <summary>
 /// Creates a new instance of the <see cref="EntityNotFoundException"/> class with the specified information about the entity.
 /// </summary>
 /// <param name="uri">URI identifying the reactive entity that was not found.</param>
 /// <param name="type">Reactive entity kind.</param>
 /// <param name="qeId">URI identifier the query engine whose registry does not contain an entity with the specified URI.</param>
 /// <param name="paramName">Parameter name of the argument containing the URI of the entity that was not found.</param>
 public EntityNotFoundException(Uri uri, ReactiveEntityKind type, Uri qeId, string paramName)
     : base(GetMessage(uri, type, qeId), paramName)
 {
     QueryEngineUri = qeId;
     EntityUri      = uri;
     EntityType     = type;
 }
            private void AddEntityPlaceholder(ReactiveEntityKind kind, string key)
            {
                var uri = new Uri(key);

#pragma warning disable IDE0079 // Remove unnecessary suppression.
#pragma warning disable CA2000  // Dispose objects before losing scope. (Entities are owned by the registry.)

                var added = kind switch
                {
                    ReactiveEntityKind.Observable => Registry.Observables.TryAdd(key, ObservableDefinitionEntity.CreateInvalidInstance(uri)),
                    ReactiveEntityKind.Observer => Registry.Observers.TryAdd(key, ObserverDefinitionEntity.CreateInvalidInstance(uri)),
                    ReactiveEntityKind.Stream => Registry.Subjects.TryAdd(key, SubjectEntity.CreateInvalidInstance(uri)),
                    ReactiveEntityKind.StreamFactory => Registry.SubjectFactories.TryAdd(key, StreamFactoryDefinitionEntity.CreateInvalidInstance(uri)),
                    ReactiveEntityKind.SubscriptionFactory => Registry.SubscriptionFactories.TryAdd(key, SubscriptionFactoryDefinitionEntity.CreateInvalidInstance(uri)),
                    ReactiveEntityKind.Subscription => Registry.Subscriptions.TryAdd(key, SubscriptionEntity.CreateInvalidInstance(uri)),
                    ReactiveEntityKind.ReliableSubscription => Registry.ReliableSubscriptions.TryAdd(key, ReliableSubscriptionEntity.CreateInvalidInstance(uri)),
                    ReactiveEntityKind.Other => Registry.Other.TryAdd(key, OtherDefinitionEntity.CreateInvalidInstance(uri)),
                    ReactiveEntityKind.Template => Registry.Templates.TryAdd(key, OtherDefinitionEntity.CreateInvalidInstance(uri)),
                    _ => throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Cannot create an invalid entity '{0}' of type '{1}'.", key, kind)),
                };

#pragma warning restore CA2000
#pragma warning restore IDE0079

                if (added)
                {
                    Parent.TraceSource.Registry_AddEntityPlaceholder(Parent.Uri, kind.ToString(), key);
                }
            }
Ejemplo n.º 3
0
 /// <summary>
 /// Creates a new instance of the <see cref="EntityAlreadyExistsException"/> class with the specified information about the entity and an inner exception.
 /// </summary>
 /// <param name="uri">URI identifying the reactive entity that already exists.</param>
 /// <param name="type">Reactive entity kind.</param>
 /// <param name="qeId">URI identifier the query engine whose registry already contains an entity with the specified URI.</param>
 /// <param name="paramName">Parameter name of the argument containing the URI that caused the conflict.</param>
 /// <param name="inner">Inner exception with additional information about the naming conflict.</param>
 public EntityAlreadyExistsException(Uri uri, ReactiveEntityKind type, Uri qeId, string paramName, Exception inner)
     : base(GetMessage(uri, type, qeId), paramName, inner)
 {
     QueryEngineUri = qeId;
     EntityUri      = uri;
     EntityType     = type;
 }
Ejemplo n.º 4
0
        public ReactiveEntity Load(ReactiveEntityKind kind)
        {
            var expression = DeserializeExpression();
            var uri        = _serializer.Deserialize <Uri>(_stream);
            var state      = _serializer.Deserialize <object>(_stream);
            var entity     = CreateEntity(kind, uri, expression, state);

            entity.Deserialize(_serializer, _stream);
            return(entity);
        }
Ejemplo n.º 5
0
 /// <summary>
 /// Creates an invalid instance of the given reactive entity kind with the given URI.
 /// </summary>
 /// <param name="uri">The URI.</param>
 /// <param name="kind">The reactive entity kind.</param>
 /// <returns>
 /// The invalid instance, or null if an unexpected kind is provided.
 /// </returns>
 public static ReactiveEntity CreateInvalidInstance(Uri uri, ReactiveEntityKind kind)
 {
     return(kind switch
     {
         ReactiveEntityKind.Observable => ObservableDefinitionEntity.CreateInvalidInstance(uri),
         ReactiveEntityKind.Observer => ObserverDefinitionEntity.CreateInvalidInstance(uri),
         ReactiveEntityKind.Stream => SubjectEntity.CreateInvalidInstance(uri),
         ReactiveEntityKind.StreamFactory => StreamFactoryDefinitionEntity.CreateInvalidInstance(uri),
         ReactiveEntityKind.Subscription => SubscriptionEntity.CreateInvalidInstance(uri),
         ReactiveEntityKind.ReliableSubscription => ReliableSubscriptionEntity.CreateInvalidInstance(uri),
         ReactiveEntityKind.Template or ReactiveEntityKind.Other => OtherDefinitionEntity.CreateInvalidInstance(uri),
         _ => null,
     });
Ejemplo n.º 6
0
            private bool OnEntitySaveFailed(Uri uri, IReactiveResource entity, ReactiveEntityKind kind, Exception error)
            {
                var entitySaveFailed = Parent.EntitySaveFailed;

                if (entitySaveFailed != null)
                {
                    var e = new ReactiveEntitySaveFailedEventArgs(uri, entity, kind, error);

                    entitySaveFailed.InvokeSafe(Parent, e);

                    return(e.Handled);
                }

                return(false);
            }
                private void HandleError(ReactiveEntityKind kind, string key, IReactiveResource entity, Exception ex, Action <Exception> unhandled)
                {
                    if (ex is EngineUnloadedException)
                    {
                        return;
                    }

                    var uri = new Uri(key);

                    var error = new EntitySaveFailedException(uri, kind, ex);

                    if (!_engine.OnEntitySaveFailed(uri, entity, kind, error))
                    {
                        unhandled(error);
                    }
                }
                /// <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);
                }
                private void HandleError(ReactiveEntityKind kind, string key, IReactiveResource entity, Exception ex, Action <Exception> unhandled)
                {
                    if (ex is EngineUnloadedException)
                    {
                        return;
                    }

                    var uri = new Uri(key);

                    var error = new EntityLoadFailedException(uri, kind, ex);

                    // TODO: support mitigation for any kind of artifact
                    if (!_engine.OnEntityLoadFailed(uri, entity, kind, error, out _))
                    {
                        unhandled(error);
                    }
                }
Ejemplo n.º 10
0
            private bool OnEntityLoadFailed(Uri uri, IReactiveResource entity, ReactiveEntityKind kind, Exception error, out ReactiveEntityRecoveryFailureMitigation mitigation)
            {
                mitigation = ReactiveEntityRecoveryFailureMitigation.Ignore;

                if (error is MitigationBailOutException)
                {
                    return(true);
                }

                var entityLoadFailed = Parent.EntityLoadFailed;

                if (entityLoadFailed != null)
                {
                    var e = new ReactiveEntityLoadFailedEventArgs(uri, entity, kind, error);

                    entityLoadFailed.InvokeSafe(Parent, e);

                    mitigation = e.Mitigation;
                    return(e.Handled);
                }

                return(false);
            }
Ejemplo n.º 11
0
 /// <summary>
 /// Creates a new instance of the <see cref="ReactiveEntityEventArgs"/> class for the specified entity.
 /// </summary>
 /// <param name="uri">URI of the reactive entity.</param>
 /// <param name="entity">Reactive entity.</param>
 /// <param name="entityType">Kind of the reactive entity.</param>
 protected ReactiveEntityEventArgs(Uri uri, IReactiveResource entity, ReactiveEntityKind entityType)
 {
     Uri        = uri;
     Entity     = entity;
     EntityType = entityType;
 }
Ejemplo n.º 12
0
 /// <summary>
 /// Creates a new instance of the <see cref="EntityLoadFailedException"/> type for the entity with the specified URI and entity kind, including an inner exception.
 /// </summary>
 /// <param name="uri">URI identifying the entity that failed to be loaded.</param>
 /// <param name="type">Reactive entity kind of the entity that failed to be loaded.</param>
 /// <param name="inner">Exception that caused the entity save failure.</param>
 public EntityLoadFailedException(Uri uri, ReactiveEntityKind type, Exception inner)
     : base(GetMessage(uri, type), inner)
 {
     EntityUri  = uri;
     EntityType = type;
 }
 /// <summary>
 /// Creates a new instance of the <see cref="ReactiveEntityLoadFailedEventArgs"/> class for the specified entity.
 /// </summary>
 /// <param name="uri">URI of the reactive entity.</param>
 /// <param name="entity">Reactive entity.</param>
 /// <param name="entityType">Kind of the reactive entity.</param>
 /// <param name="error">The error that occured during load.</param>
 public ReactiveEntityLoadFailedEventArgs(Uri uri, IReactiveResource entity, ReactiveEntityKind entityType, Exception error)
     : base(uri, entity, entityType)
 {
     Error = error;
 }
                /// <summary>
                /// Loads the definitions.
                /// </summary>
                /// <typeparam name="TEntity">The type of the entity.</typeparam>
                /// <param name="category">The category.</param>
                /// <param name="kind">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 LoadDefinitions <TEntity>(
                    string category,
                    ReactiveEntityKind kind,
                    Action <TEntity> onLoading,
                    Action <string, TEntity, Exception> onError,
                    BlobLogger blobLogger,
                    CancellationToken token)
                    where TEntity : ReactiveEntity
                {
                    Debug.Assert(!string.IsNullOrEmpty(category), "Category should not be null or empty.");
                    Debug.Assert(onLoading != null, "onLoading should not be null.");

                    var trace = _engine.Parent.TraceSource;

                    trace.Recovery_LoadingDefinitionsStarted(_engine.Parent.Uri, category);

                    if (!_reader.TryGetItemKeys(category, out IEnumerable <string> entities))
                    {
                        entities = Array.Empty <string>();
                    }

                    var total  = 0;
                    var failed = 0;

                    Parallel.ForEach(
                        entities,
                        new ParallelOptions
                    {
                        MaxDegreeOfParallelism = _engine.Parent.Options.RecoveryDegreeOfParallelism,
                        TaskScheduler          = RecoveryScheduler.Default,
                        CancellationToken      = token,
                    },
                        key =>
                    {
                        var entity = default(TEntity);

                        try
                        {
                            var stopwatch = Stopwatch.StartNew();
                            if (!_reader.TryGetItemReader(category, key, out Stream stream))
                            {
                                throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "No items in key '{0}' for category '{1}'.", key, category));
                            }
                            var elapsedReading = stopwatch.Elapsed;

                            blobLogger.Append(category, key, stream);

                            var policy = _engine.Parent._serializationPolicy;

                            stopwatch.Restart();
                            using (var reader = new EntityReader(stream, _engine.Registry, policy))
                            {
                                reader.ReadHeader();
                                _engine.TryMitigate(
                                    () => entity = (TEntity)reader.Load(kind),
                                    ReactiveEntity.CreateInvalidInstance(new Uri(key), kind),
                                    true,
                                    _placeholderMitigator);
                                reader.ReadFooter();
                            }
                            var elapsedLoading = stopwatch.Elapsed;

                            entity.SetMetric(EntityMetric.ReadEntity, elapsedReading);
                            entity.SetMetric(EntityMetric.LoadEntity, elapsedLoading);

                            onLoading(entity);
                        }
                        catch (MitigationBailOutException) { }
#pragma warning disable CA1031 // Do not catch general exception types. (By design; mitigation callback is the "handler".)
                        catch (Exception ex)
                        {
                            Interlocked.Increment(ref failed);

                            trace.Recovery_LoadingDefinitionsFailure(_engine.Parent.Uri, category, key, ex.Message);

                            onError(key, entity, ex);
                        }
#pragma warning restore CA1031

                        Interlocked.Increment(ref total);
                    });

                    token.ThrowIfCancellationRequested();

                    trace.Recovery_LoadingDefinitionsCompleted(_engine.Parent.Uri, category, total, failed);
                }
Ejemplo n.º 15
0
 private static string GetMessage(Uri uri, ReactiveEntityKind type, Uri qeId)
 {
     return(string.Format(CultureInfo.InvariantCulture, "An entity of type '{0}' with identifier '{1}' already exists in query engine '{2}'.", type, uri.ToCanonicalString(), qeId.ToCanonicalString()));
 }
Ejemplo n.º 16
0
 private static string GetMessage(Uri uri, ReactiveEntityKind type)
 {
     return(string.Format(CultureInfo.InvariantCulture, "The entity of type '{0}' with identifier '{1}' failed to load.", type, uri.ToCanonicalString()));
 }
 /// <summary>
 /// Creates a new instance of the <see cref="EntitySaveFailedException"/> type for the entity with the specified URI and entity kind.
 /// </summary>
 /// <param name="uri">URI identifying the entity that failed to be saved.</param>
 /// <param name="type">Reactive entity kind of the entity that failed to be saved.</param>
 public EntitySaveFailedException(Uri uri, ReactiveEntityKind type)
     : base(GetMessage(uri, type))
 {
     EntityUri  = uri;
     EntityType = type;
 }