protected override void Dispose(bool explicitDispose) { if (explicitDispose) { _appStartedSubscription?.Dispose(); _lastComponentActivation?.Dispose(); } _appStartedSubscription = null; _retryOptions = null; _lastComponentActivation = null; _activateControlFactory = null; // base.Dispose(explicitDispose); }
// TODO: Put strings into the resources. // void P_HandleComponentActivationAttemptResult( RetrySettings retryOptions, IActivatableXAppScopeInstance component, int retryAttemptIndex, Task activationTask, XFullCorrelationId correlationId, CancellationToken ct) { // retryOptions = retryOptions.EnsureNotNull(nameof(retryOptions)).AsReadOnly().EnsureValid(); component.EnsureNotNull(nameof(component)); retryAttemptIndex.Arg(nameof(retryAttemptIndex)).EnsureNotLessThan(-1); activationTask.EnsureNotNull(nameof(activationTask)); // var logMessagePrologue = $"Отложенная активация. ИД корреляции: {correlationId.FmtStr().G()}."; if (activationTask.IsFaulted || activationTask.IsCanceled) { if (activationTask.IsCanceled) { #if !DO_NOT_USE_EON_LOGGING_API this .IssueWarning( messagePrologue: logMessagePrologue, message: $"Активация компонента была прервана или отменена.{Environment.NewLine}Повторная попытка не предусмотрена опциями активации компонента.{Environment.NewLine}\tКомпонент:{component.FmtStr().GNLI2()}", severityLevel: SeverityLevel.Medium); #endif } else { string retryActivationLogMessage; bool doRetryActivation; if (retryOptions.IsDisabled) { doRetryActivation = false; retryActivationLogMessage = $"Повторная попытка активации компонента запрещена настройками активации (см. '{nameof(RetrySettings)}.{nameof(RetrySettings.IsDisabled)}')."; } else if (retryOptions.MaxCount == -1) { doRetryActivation = true; retryActivationLogMessage = $"Повторная попытка активации компонента будет выполнена {(retryOptions.Interval == TimeoutDuration.Zero ? "немедленно" : $"через '{retryOptions.Interval.ToString()}'")}."; } else if (retryOptions.MaxCount == 0) { doRetryActivation = false; retryActivationLogMessage = $"Повторная попытка не предусмотрена настройками активации компонента (см. '{nameof(RetrySettings)}.{nameof(RetrySettings.MaxCount)}')."; } else if ((retryAttemptIndex + 1) < retryOptions.MaxCount) { doRetryActivation = true; retryActivationLogMessage = $"Повторная попытка активации компонента ({retryAttemptIndex + 2:d} из {retryOptions.MaxCount:d}) будет выполнена {(retryOptions.Interval == TimeoutDuration.Zero ? "немедленно" : $"через '{retryOptions.Interval.ToString()}'")}."; } else { doRetryActivation = false; retryActivationLogMessage = $"Повторной попытки активации компонента не будет, так как все попытки исчерпаны (кол-во попыток {retryOptions.MaxCount:d})."; } #if !DO_NOT_USE_EON_LOGGING_API this .IssueError( messagePrologue: logMessagePrologue, message: $"Ошибка активации компонента.{Environment.NewLine}{retryActivationLogMessage}{Environment.NewLine}\tКомпонент:{Environment.NewLine}{component.ToString().IndentLines2()}", error: activationTask.Exception, includeErrorInIssueFaultException: true, severityLevel: activationTask.Exception.GetMostHighSeverityLevel(baseLevel: SeverityLevel.Medium)); #endif // if (doRetryActivation) { if (retryOptions.Interval == TimeoutDuration.Zero) { P_StartComponentActivationAttempt(retryOptions: retryOptions, rethrowException: false, retryAttemptIndex: retryAttemptIndex + 1, correlationId: correlationId, ct: ct); } else { TaskUtilities .Delay(duration: retryOptions.Interval) .ContinueWith( continuationAction: locDelayTask => P_StartComponentActivationAttempt( retryOptions: retryOptions, rethrowException: false, retryAttemptIndex: retryAttemptIndex + 1, ct: ct, correlationId: correlationId), continuationOptions: TaskContinuationOptions.PreferFairness | TaskContinuationOptions.OnlyOnRanToCompletion, cancellationToken: ct, scheduler: TaskScheduler.Default); } } } } else { #if !DO_NOT_USE_EON_LOGGING_API this .IssueInformation( messagePrologue: logMessagePrologue, message: $"Активация компонента успешно выполнена.{Environment.NewLine}\tКомпонент:{component.FmtStr().GNLI2()}", severityLevel: SeverityLevel.Medium); #endif } }
// TODO: Put strings into the resources. // void P_StartComponentActivationAttempt( RetrySettings retryOptions, bool rethrowException, int retryAttemptIndex, XFullCorrelationId correlationId, CancellationToken ct, Func <bool> breakCondition = default) { // retryOptions = retryOptions.EnsureNotNull(nameof(retryOptions)).AsReadOnly().EnsureValid(); // if (breakCondition is null) { breakCondition = () => ct.IsCancellationRequested || HasDeactivationRequested || !IsActive; } if (!breakCondition()) { var logMessagePrologue = $"Отложенная активация. ИД корреляции: {correlationId.FmtStr().G()}."; try { IActivatableXAppScopeInstance componentNewInstance = default; P_ComponentActivationAttempt newActivation = default; P_ComponentActivationAttempt existingActivation = default; for (; ;) { existingActivation = TryReadDA(ref _lastComponentActivation, considerDisposeRequest: true); if (existingActivation is null) { if (breakCondition()) { cleanup(ref componentNewInstance, ref newActivation); break; } else { newActivation = newActivation ?? new P_ComponentActivationAttempt( retryIndex: retryAttemptIndex, component: componentNewInstance = P_CreateComponent(), correlationId: correlationId, ct: ct); if (itrlck.UpdateBool(location: ref _lastComponentActivation, value: newActivation, comparand: existingActivation)) { if (breakCondition()) { itrlck.SetNullBool(location: ref _lastComponentActivation, comparand: newActivation); cleanup(ref componentNewInstance, ref newActivation); } break; } else { continue; } } } else { cleanup(ref componentNewInstance, ref newActivation); break; } } // if (!(newActivation is null)) { newActivation .ActivateControl .StartAsync() .ContinueWith( continuationAction: locTask => { var locCaughtException = default(Exception); try { if (locTask.IsCanceled || locTask.IsFaulted) { itrlck.SetNullBool(location: ref _lastComponentActivation, comparand: newActivation); } // P_HandleComponentActivationAttemptResult( retryOptions: retryOptions, component: componentNewInstance, retryAttemptIndex: newActivation.RetryAttemptIndex, activationTask: locTask, correlationId: correlationId, ct: ct); } catch (Exception locException) { locCaughtException = locException; throw; } finally { if (locTask.IsCanceled || locTask.IsFaulted) { try { cleanup(ref componentNewInstance, ref newActivation); } catch (Exception locException) { if (locCaughtException is null) { throw; } else { throw new AggregateException(locCaughtException, locException); } } } } }, continuationOptions: TaskContinuationOptions.PreferFairness); } } catch (Exception exception) { if (rethrowException) { throw new EonException(message: $"Ошибка запуска попытки активации.{Environment.NewLine}\tКомпонент:{this.FmtStr().GNLI2()}", innerException: exception); } else { #if !DO_NOT_USE_EON_LOGGING_API this .IssueError( messagePrologue: logMessagePrologue, message: "Ошибка запуска попытки активации.", error: exception, includeErrorInIssueFaultException: true, severityLevel: exception.GetMostHighSeverityLevel(baseLevel: SeverityLevel.Medium)); #endif } } } // void cleanup(ref IActivatableXAppScopeInstance locTarget, ref P_ComponentActivationAttempt locActivation) { var locCaughtExceptions = new List <Exception>(); try { locTarget?.Dispose(); locTarget = null; } catch (Exception locException) { locCaughtExceptions.Add(locException); } try { locActivation?.ActivateControl.StopAsync().WaitWithTimeout(); locActivation?.Dispose(); locActivation = null; } catch (Exception locException) { locCaughtExceptions.Add(locException); } if (locCaughtExceptions.Count > 0) { throw new AggregateException(innerExceptions: locCaughtExceptions); } } }