// 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)); } }
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)); } }
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)); } } }
// 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; } } } }
// 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 }