// TODO: Put strings into the resources.
        //
        Task P_HandleAppStartedNotificationAsync(ILocalSubscription subscription, ILocalMessage <IXAppStartedEventArgs> message, IContext ctx)
        {
            try {
                subscription.EnsureNotNull(nameof(subscription));
                message.EnsureNotNull(nameof(message));
                ctx.EnsureNotNull(nameof(ctx));
                //
                if (ctx.IsCancellationRequested())
                {
                    return(Task.FromCanceled(cancellationToken: ctx.Ct()));
                }
                else if (HasDeactivationRequested || !IsActive || !subscription.IsActive || !ReferenceEquals(subscription, TryReadDA(ref _appStartedSubscription)))
                {
                    return(Task.CompletedTask);
                }
                else
                {
                    var retryOptions = TryReadDA(ref _retryOptions, considerDisposeRequest: true);
                    if (retryOptions is null)
                    {
                        if (!IsDisposeRequested)
                        {
                            EnsureInitialized();
                        }
                        return(TaskUtilities.FromCanceled());
                    }
                    else
                    {
#if !DO_NOT_USE_EON_LOGGING_API
                        var logMessagePrologue = $"Отложенная активация. ИД корреляции: {ctx.FullCorrelationId}.";
                        this
                        .IssueInformation(
                            messagePrologue: logMessagePrologue,
                            message: "Получено уведомление о запуске приложения. Начало активации.",
                            severityLevel: SeverityLevel.Medium);
#endif
                        P_StartComponentActivationAttempt(retryOptions: retryOptions, rethrowException: false, retryAttemptIndex: -1, correlationId: ctx.FullCorrelationId, ct: message.Payload.App.AppShutdownToken);
                        return(Task.CompletedTask);
                    }
                }
            }
            catch (Exception exception) {
                return(Task.FromException(exception));
            }
        }
Esempio n. 2
0
 public Task <TriggerSignalEventArgs> NextSignalAwaitable()
 {
     try {
         var existingAwaitable = TryReadDA(ref _nextSignalAwaitable, considerDisposeRequest: true);
         if (existingAwaitable is null)
         {
             if (HasDeactivationRequested)
             {
                 return(TaskUtilities.FromCanceled <TriggerSignalEventArgs>());
             }
             else
             {
                 AsyncTaskCompletionSource <TriggerSignalEventArgs> newAwaitable = default;
                 try {
                     try {
                         UpdDAIfNullBool(location: ref _nextSignalAwaitable, factory: () => newAwaitable = new AsyncTaskCompletionSource <TriggerSignalEventArgs>(), current: out existingAwaitable);
                     }
                     catch (ObjectDisposedException) {
                         if (IsDisposeRequested)
                         {
                             return(TaskUtilities.FromCanceled <TriggerSignalEventArgs>());
                         }
                         else
                         {
                             throw;
                         }
                     }
                 }
                 finally {
                     if (!ReferenceEquals(existingAwaitable, newAwaitable))
                     {
                         newAwaitable?.TrySetCanceled(ct: CancellationToken.None);
                     }
                 }
             }
         }
         return(existingAwaitable.Task);
     }
     catch (Exception exception) {
         return(TaskUtilities.FromError <TriggerSignalEventArgs>(error: exception));
     }
 }
Esempio n. 3
0
        public Task <bool> WaitAsync(CancellationToken ct, TimeoutDuration timeout, bool treatCancellationAsTimeoutExpiry)
        {
            SignalAwaitable signalAwaitable = null;

            try {
                timeout.EnsureNotNull(nameof(timeout));
                //
                if (ct.IsCancellationRequested)
                {
                    return(treatCancellationAsTimeoutExpiry ? TaskUtilities.FromFalse() : TaskUtilities.FromCanceled <bool>(ct: ct));
                }
                else
                {
                    var timeoutCts            = default(CancellationTokenSource);
                    var timeoutCtRegistration = default(CancellationTokenRegistration?);
                    try {
                        signalAwaitable = new SignalAwaitable();
                        //
                        if (ct.CanBeCanceled)
                        {
                            var ctRegistration = default(CancellationTokenRegistration);
                            try {
                                signalAwaitable
                                .Task
                                .ContinueWith(
                                    continuationAction: (locTask) => { ctRegistration.Dispose(); },
                                    continuationOptions: TaskContinuationOptions.ExecuteSynchronously);
                                ctRegistration =
                                    ct
                                    .Register(
                                        callback:
                                        () => {
                                    if (treatCancellationAsTimeoutExpiry)
                                    {
                                        signalAwaitable.TrySetResult(result: false);
                                    }
                                    else
                                    {
                                        signalAwaitable.TrySetCanceled(ct: ct);
                                    }
                                });
                            }
                            catch {
                                ctRegistration.Dispose();
                                throw;
                            }
                        }
                        //
                        if (!timeout.IsInfinite)
                        {
                            timeoutCts            = new CancellationTokenSource(millisecondsDelay: timeout.Milliseconds);
                            timeoutCtRegistration =
                                timeoutCts
                                .Token
                                .Register(callback: () => signalAwaitable.TrySetResult(result: false));
                        }
                        //
                        var queue         = ReadDA(ref _queue);
                        var queueSpinLock = ReadDA(ref _queueSpinLock, considerDisposeRequest: true);
                        queueSpinLock
                        .Invoke(
                            action:
                            () => {
                            if (ct.IsCancellationRequested)
                            {
                                if (treatCancellationAsTimeoutExpiry)
                                {
                                    signalAwaitable.TrySetResult(result: false);
                                }
                                else
                                {
                                    signalAwaitable.TrySetCanceled(ct: ct);
                                }
                            }
                            else
                            {
                                EnsureNotDisposeState(considerDisposeRequest: true);
                                //
                                if (queue.Count == 1 && ReferenceEquals(queue.Peek(), __Signaled))
                                {
                                    if (signalAwaitable.TrySetResult(result: true))
                                    {
                                        queue.Dequeue();
                                    }
                                }
                                else if (timeout.Milliseconds == 0)
                                {
                                    signalAwaitable.TrySetResult(result: false);
                                }
                                else
                                {
                                    queue.Enqueue(signalAwaitable);
                                }
                            }
                        });
                        return(signalAwaitable.Task);
                    }
                    catch {
                        timeoutCtRegistration?.Dispose();
                        timeoutCts?.Dispose();
                        throw;
                    }
                }
            }
            catch (Exception exception) {
                if (signalAwaitable?.TrySetException(exception) == true)
                {
                    return(signalAwaitable.Task);
                }
                else
                {
                    return(TaskUtilities.FromError <bool>(error: exception));
                }
            }
        }
Esempio n. 4
0
        // TODO: Put strings into the resources.
        //
        protected override Task DoActivateAsync(IRunControlAttemptState state)
        {
#if !DO_NOT_USE_EON_LOGGING_API
            const string logMessagePrologue = "Активация.";
#endif
            //
            try {
                state.EnsureNotNull(nameof(state));
                //
                if (HasDeactivationRequested)
                {
                    return(TaskUtilities.FromCanceled());
                }
                else
                {
                    return(TaskUtilities.RunOnDefaultScheduler(action: doActivateParallel, cancellationToken: CancellationToken.None, state: state));
                }
            }
            catch (Exception exception) {
                return(TaskUtilities.FromError(error: exception));
            }
            //
            void doActivateParallel(IRunControlAttemptState locState)
            {
                locState.EnsureNotNull(nameof(locState));
                //
                var locActivatedItems = new List <IActivatableXAppScopeInstance>();

                try {
                    foreach (var locActivatable in ActivatableItems)
                    {
                        // Мониторинг запроса отмены операции.
                        //
                        if (HasDeactivationRequested)
                        {
                            throw new OperationCanceledException();
                        }
                        // Активация компонента.
                        //
                        try {
#if !DO_NOT_USE_EON_LOGGING_API
                            this
                            .IssueInformation(
                                messagePrologue: logMessagePrologue,
                                message: $"Активация компонента.{Environment.NewLine}\tКомпонент:{Environment.NewLine}{locActivatable.ToString().IndentLines2()}",
                                severityLevel: SeverityLevel.Lowest);
#endif
                            if (!locActivatable.IsAutoActivationEnabled)
                            {
#if !DO_NOT_USE_EON_LOGGING_API
                                this
                                .IssueWarning(
                                    messagePrologue: logMessagePrologue,
                                    message: $"Активация компонента не выполнена, так как активация отключена самим компонентом (см. '{nameof(locActivatable.IsAutoActivationEnabled)}').{Environment.NewLine}\tОбъект:{locActivatable.FmtStr().GNLI2()}",
                                    severityLevel: SeverityLevel.Lowest);
#endif
                                continue;
                            }
                            locActivatable
                            .ActivateControl
                            .StartAsync(options: TaskCreationOptions.AttachedToParent)
#if !DO_NOT_USE_EON_LOGGING_API
                            .ContinueWith(
                                continuationAction:
                                locItemActivationTask => {
                                if (locItemActivationTask.IsFaulted)
                                {
                                    this
                                    .IssueError(
                                        messagePrologue: logMessagePrologue,
                                        message: $"Ошибка активации компонента.{Environment.NewLine}\tКомпонент:{Environment.NewLine}{locActivatable.ToString().IndentLines2()}",
                                        error: locItemActivationTask.Exception,
                                        includeErrorInIssueFaultException: true,
                                        severityLevel: locItemActivationTask.Exception.GetMostHighSeverityLevel(baseLevel: SeverityLevel.Lowest));
                                }
                                else if (locItemActivationTask.IsCanceled)
                                {
                                    this
                                    .IssueWarning(
                                        messagePrologue: logMessagePrologue,
                                        message: $"Активация компонента была прервана или отменена.{Environment.NewLine}\tКомпонент:{locActivatable.FmtStr().GNLI2()}",
                                        severityLevel: SeverityLevel.Lowest);
                                }
                                else
                                {
                                    this
                                    .IssueInformation(
                                        messagePrologue: logMessagePrologue,
                                        message: $"Активация компонента успешно выполнена.{Environment.NewLine}\tКомпонент:{locActivatable.FmtStr().GNLI2()}",
                                        severityLevel: SeverityLevel.Lowest);
                                }
                            },
                                continuationOptions: TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.ExecuteSynchronously)
#endif
                            ;
                            //
                            locActivatedItems.Add(locActivatable);
                        }
                        catch {
#if !DO_NOT_USE_EON_LOGGING_API
                            this
                            .IssueError(
                                messagePrologue: logMessagePrologue,
                                message: $"Ошибка активации компонента.{Environment.NewLine}\tКомпонент:{locActivatable.FmtStr().GNLI2()}",
                                error: exception,
                                severityLevel: exception.GetMostHighSeverityLevel(baseLevel: SeverityLevel.Lowest),
                                includeErrorInIssueFaultException: true);
#endif
                            throw;
                        }
                    }
                    WriteDA(ref _activatedItems, locActivatedItems.ToArray());
                }
                catch (Exception exception) {
                    var caughtExceptions = new List <Exception>();
                    foreach (var activatedItem in locActivatedItems)
                    {
                        try { activatedItem.ActivateControl.StopAsync(TaskCreationOptions.AttachedToParent); }
                        catch (Exception secondException) { caughtExceptions.Add(secondException); }
                    }
                    //
                    if (caughtExceptions.Count > 0)
                    {
                        throw new AggregateException(exception.Sequence().Concat(caughtExceptions));
                    }
                    else
                    {
                        throw;
                    }
                }
            }
        }
Esempio n. 5
0
        // TODO: Put strings into the resources.
        //
        Task <IXAppScopeInstance> P_ResetComponentAsync(Func <IContext, bool> breakCondition = default, ITriggerSignalProperties triggerSignalProps = default, bool doFailureResponse = default, IContext ctx = default)
        {
            try {
                if (breakCondition is null)
                {
                    breakCondition =
                        (locContext) => {
                        locContext.ThrowIfCancellationRequested();
                        return(!IsActive || HasDeactivationRequested);
                    }
                }
                ;
                //
                var      startTimestamp = StopwatchUtilities.GetTimestampAsTimeSpan();
                IContext locCtx         = default;
                try {
                    var resetNumber        = Interlocked.Increment(ref _resetCounter);
                    var failureResponseDlg = ReadIA(ref _resetFailureResponseDelegate, isNotRequired: true, locationName: nameof(_resetFailureResponseDelegate));
                    var state = new P_ResetState();
                    locCtx = CreateScopedContext(outerCtx: ctx, localTag: state);
                    var logMessagePrologue = $"{(resetNumber == 0 ? "Установка компонента." : $"Замена (переустановка) компонента. Порядковый номер замены: {resetNumber:d}.")} ИД корреляции: {locCtx.FullCorrelationId}.{(triggerSignalProps is null ? string.Empty : $"{Environment.NewLine}\tСобытие-инициатор:{triggerSignalProps.FmtStr().GNLI2()}")}";
                    if (locCtx.IsCancellationRequested())
                    {
                        return(Task.FromCanceled <IXAppScopeInstance>(cancellationToken: locCtx.Ct()));
                    }
                    var resetTask = TaskUtilities.RunOnDefaultScheduler(factory: async() => await doResetAsync(locCtx: locCtx).ConfigureAwait(false));
                    // Вывод результатов ресета в лог.
                    //
#if !DO_NOT_USE_EON_LOGGING_API
                    resetTask
                    .ContinueWith(
                        continuationAction:
                        locTask => {
                        var locDuration = StopwatchUtilities.GetTimestampAsTimeSpan().Subtract(ts: startTimestamp);
                        if (locTask.IsFaulted)
                        {
                            this
                            .IssueError(
                                messagePrologue: logMessagePrologue,
                                message: $"Длительность:{locDuration.ToString("c").FmtStr().GNLI()}{Environment.NewLine}Сбой.",
                                error: locTask.Exception,
                                includeErrorInIssueFaultException: true,
                                severityLevel: locTask.Exception.GetMostHighSeverityLevel(baseLevel: SeverityLevel.Medium));
                            locTask.Exception.MarkAsObserved();
                        }
                        else if (locTask.IsCanceled)
                        {
                            this
                            .IssueWarning(
                                messagePrologue: logMessagePrologue,
                                message: $"Длительность:{locDuration.ToString("c").FmtStr().GNLI()}{Environment.NewLine}Отменено или прервано.",
                                severityLevel: SeverityLevel.Medium);
                        }
                        else
                        {
                            this
                            .IssueInformation(
                                messagePrologue: logMessagePrologue,
                                message: $"Длительность:{locDuration.ToString("c").FmtStr().GNLI()}{Environment.NewLine}Успешно выполнено.{Environment.NewLine}\tНовый экземпляр компонента:{locTask.Result.FmtStr().GNLI2()}",
                                severityLevel: SeverityLevel.Medium);
                        }
                    },
                        continuationOptions: TaskContinuationOptions.ExecuteSynchronously);
#endif
                    // Обработка сбоя ресета.
                    //
                    Task failureResponseTask;
                    if (doFailureResponse && !(failureResponseDlg is null))
                    {
                        failureResponseTask =
                            resetTask
                            .ContinueWith(
                                continuationFunction:
                                locTask => {
                            if (!(state.PreviousComponent is null))
                            {
                                // Корректирующие действие сбоя ресета выполняется только в случае именно замены компонента.
                                //
                                return
                                (doFailureCorrectiveAsync(
                                     locFailure: locTask.Exception,
                                     responseDlg: failureResponseDlg,
                                     locCtx: locCtx,
                                     logMessagePrologue: logMessagePrologue));
                            }
                            else
                            {
                                return(TaskUtilities.FromCanceled());
                            }
                        },
                                continuationOptions: TaskContinuationOptions.PreferFairness | TaskContinuationOptions.OnlyOnFaulted)
                            .Unwrap();
                        // Вывод результатов обработки сбоя в лог.
                        //
#if !DO_NOT_USE_EON_LOGGING_API
                        failureResponseTask
                        .ContinueWith(
                            continuationAction:
                            locTask => {
                            if (locTask.IsFaulted)
                            {
                                this
                                .IssueError(
                                    messagePrologue: logMessagePrologue,
                                    message: $"Корректирующее действие при сбое замены (переустановки) компонента.{Environment.NewLine}Сбой корректирующего действия.",
                                    error: locTask.Exception,
                                    includeErrorInIssueFaultException: true,
                                    severityLevel: locTask.Exception.GetMostHighSeverityLevel(baseLevel: SeverityLevel.High));
                            }
                            else
                            {
                                this
                                .IssueInformation(
                                    messagePrologue: logMessagePrologue,
                                    message: $"Корректирующее действие при сбое замены (переустановки) компонента.{Environment.NewLine}Корректирующее действие успешно выполнено.",
                                    severityLevel: SeverityLevel.Medium);
                            }
                        },
                            continuationOptions: TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.NotOnCanceled);
#endif
                    }