/// <summary> /// Initializes a new instance of the <see cref="StateLoader"/> class. /// </summary> /// <param name="reader">The reader.</param> /// <param name="engine">The engine.</param> public StateLoader(IStateReader reader, CoreReactiveEngine engine) { Debug.Assert(reader != null, "Reader should not be null."); Debug.Assert(engine != null, "Engine should not be null."); _reader = reader; _engine = engine; _registry = new ShadowRegistry(); _placeholderMitigator = new PlaceholderMitigator(engine); }
/// <summary> /// Try to invoke the specified <paramref name="action"/> and handle any exception that occurs. /// If an exception occurs and <paramref name="shouldMitigate"/> is true, the specified <paramref name="mitigator"/> is used to apply a mitigation. /// </summary> /// <param name="action">The action to try.</param> /// <param name="entity">The entity being loaded/mitigated.</param> /// <param name="shouldMitigate">true if errors should be mitigated; otherwise, false.</param> /// <param name="mitigator">The mitigator to use if the failed action should be mitigated.</param> private void TryMitigate(Action action, ReactiveEntity entity, bool shouldMitigate, ReactiveEntityRecoveryFailureMitigator mitigator) { try { action(); } catch (Exception ex) { var error = new EntityLoadFailedException(entity.Uri, entity.Kind, ex); if (shouldMitigate && Parent._engine.OnEntityLoadFailed(entity.Uri, entity, entity.Kind, error, out ReactiveEntityRecoveryFailureMitigation mitigation)) { var trace = Parent.TraceSource; trace.Mitigation_Execute(entity.Uri, mitigation); #pragma warning disable IDE0079 // Remove unnecessary suppression. #pragma warning disable CA1031 // Do not catch general exception types. (Protecting against engine unavailability; last resort mitigation with tracing of errors.) try { if (!mitigator.DoMitigate(entity, mitigation)) { trace.Mitigation_NotAccepted(mitigation, entity.Uri, ex); } } catch (Exception mx) { trace.Mitigation_Failure(mitigation, entity.Uri, mx); } #pragma warning restore CA1031 #pragma warning restore IDE0079 // For this implementation, whenever a mitigation occurs, we will throw a // bail out exception. This is to prevent further processing of the // 'normal' recovery process from throwing additional errors that will // trigger additional mitigations. An unfortunate consequence is that the // mitigations must ensure all steps that would have occurred in the // 'normal' recovery process occur in the mitigation (esp. for things // mitigations like `Regenerate`. Right now, this is not a problem, as the // steps being mitigated are late in the recovery process. throw new MitigationBailOutException(); } // This may result in a second call to the `EntityLoadFailed` event. throw; } }