Пример #1
0
 protected override void Dispose(bool explicitDispose)
 {
     if (explicitDispose)
     {
         _activateControl?.Dispose();
     }
     _component       = null;
     _activateControl = null;
     //
     base.Dispose(explicitDispose);
 }
Пример #2
0
 internal P_ComponentActivationAttempt(int retryIndex, IActivatableXAppScopeInstance component, XFullCorrelationId correlationId, CancellationToken ct)
 {
     retryIndex
     .Arg(nameof(retryIndex))
     .EnsureNotLessThan(operand: -1);
     component.EnsureNotNull(nameof(component));
     correlationId.EnsureNotNull(nameof(correlationId));
     //
     _retryIndex      = retryIndex;
     _correlationId   = correlationId;
     _component       = component;
     _activateControl =
         new RunControl <P_ComponentActivationAttempt>(
             options: RunControlOptions.SingleStart,
             component: this,
             start: P_DoActivateAsync,
             stop: P_DoDeactivateAsync,
             stopToken: ct);
 }
Пример #3
0
        // 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
            }
        }
Пример #4
0
        // 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);
                }
            }
        }