Esempio n. 1
0
            static Task P_BeforeDisposeAsync(P_Lifecycle lifecycle, Action continuation)
            {
                try {
                    if (lifecycle is null)
                    {
                        throw new ArgumentNullException(paramName: nameof(lifecycle));
                    }
                    //
                    if (lifecycle.Disposing || lifecycle.IsDisposed)
                    {
                        return(TaskUtilities.FromVoidResult());
                    }
                    else
                    {
                        return(doDisposeAsync());
                    }
                }
                catch (Exception exception) {
                    return(TaskUtilities.FromError(error: exception));
                }
                //
                async Task doDisposeAsync()
                {
                    lifecycle.SetDisposeRequested();
                    var acquisition = lifecycle._acquisition;

                    if (!(acquisition is null))
                    {
                        await acquisition.ReleaseAsync().ConfigureAwait(false);
                    }
                    continuation?.Invoke();
                }
            }
Esempio n. 2
0
 public Task StopAsync()
 {
     try {
         return(ReadDA(ref _runControl).StopAsync());
     }
     catch (Exception firstException) {
         return(TaskUtilities.FromError(error: firstException));
     }
 }
Esempio n. 3
0
 static Task P_DefaultRelease(IVh <T> instance)
 {
     try {
         instance?.Dispose();
         return(TaskUtilities.FromVoidResult());
     }
     catch (Exception exception) {
         return(TaskUtilities.FromError(exception));
     }
 }
Esempio n. 4
0
 static Func <IVh <T>, Task> P_GetReleaseDelegate(Action <IVh <T> > release)
 {
     release.EnsureNotNull(nameof(release));
     //
     return
         ((locInstance) => {
         try {
             release(locInstance);
             return TaskUtilities.FromVoidResult();
         }
         catch (Exception exception) {
             return TaskUtilities.FromError(error: exception);
         }
     });
 }
Esempio n. 5
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. 6
0
        // TODO: Put strings into the resources.
        //
        Task <IRunControlAttemptSuccess> P_StopAsync(IContext ctx = default, bool finiteStop = default, AsyncOperationCallOption option = default)
        {
            try {
                if (!(option == AsyncOperationCallOption.ExistingOrNew || option == AsyncOperationCallOption.DefaultOrNew))
                {
                    throw new ArgumentOutOfRangeException(paramName: nameof(option));
                }
                //
                return(TaskUtilities.RunOnDefaultScheduler(factory: doStopAsync));
            }
            catch (Exception exception) {
                return(TaskUtilities.FromError <IRunControlAttemptSuccess>(exception));
            }
            //
            async Task <IRunControlAttemptSuccess> doStopAsync()
            {
                ctx.ThrowIfCancellationRequested();
                finiteStop = finiteStop || (Options & RunControlOptions.SingleStart) == RunControlOptions.SingleStart;
                var correlationId  = ctx?.FullCorrelationId;
                var ctxCt          = ctx.Ct();
                var existingStopOp = default(RunControlStopOperationState <TComponent>);
                var newStopOp      = default(RunControlStopOperationState <TComponent>);
                var component      = TryReadDA(ref _component);
                var beginTimestamp = StopwatchUtilities.GetTimestampAsTimeSpan();
                var tryCatchFinallyAffectsNewStopOp = true;

                try {
                    var setStopOpResult =
                        itrlck
                        .Update(
                            location: ref _existingStopOp,
                            transform:
                            (locCurrent, locPrevious) => {
                        if (locCurrent is null || (finiteStop && !locCurrent.FiniteStop))
                        {
                            return(locPrevious ?? (newStopOp = new RunControlStopOperationState <TComponent>(runControl: this, beginTimestamp: locCurrent?.BeginTimestamp ?? beginTimestamp, ct: ctxCt, finiteStop: finiteStop)));
                        }
                        else
                        {
                            return(locCurrent);
                        }
                    });
Esempio n. 7
0
 // TODO: Put strings into the resources.
 //
 protected override Task DoActivateAsync(IRunControlAttemptState state)
 {
     try {
         state.EnsureNotNull(nameof(state));
         //
         CancellationTokenSource cts = default;
         try {
             cts = CancellationTokenSource.CreateLinkedTokenSource(tokens: new CancellationToken[] { App.AppShutdownToken });
             var ct = cts.Token;
             if (UpdDAIfNullBool(ref _currentActivationCts, cts))
             {
                 P_ScheduleNextSignal(period: P_SelectNextPeriod(), ct: ct);
             }
             else
             {
                 throw
                     new EonException(
                         message: $"Недопустимый вызов операции. Операция уже была выполнена ранее. Для повторного выполнения необходимо сначала выполнить операцию '{nameof(DoDeactivateAsync)}'.{Environment.NewLine}\tКомпонент:{this.FmtStr().GNLI2()}");
             }
         }
         catch (Exception exception) {
             if (!(cts is null))
             {
                 ExceptionUtilities
                 .TryCatch(
                     op:
                     () => {
                     cts.Cancel(throwOnFirstException: false);
                     itrlck.SetNullBool(location: ref _currentActivationCts, comparand: cts);
                     cts.Dispose();
                 },
                     exception: exception);
             }
             throw;
         }
         return(TaskUtilities.FromVoidResult());
     }
     catch (Exception exception) {
         return(TaskUtilities.FromError(error: exception));
     }
 }
Esempio n. 8
0
 public static Task DisposeAsync(P_Lifecycle lifecycle)
 {
     try {
         if (lifecycle is null)
         {
             throw new ArgumentNullException(paramName: nameof(lifecycle));
         }
         //
         if (lifecycle.Disposing || lifecycle.IsDisposed)
         {
             return(TaskUtilities.FromVoidResult());
         }
         else
         {
             return(P_BeforeDisposeAsync(lifecycle: lifecycle, continuation: lifecycle.Dispose));
         }
     }
     catch (Exception exception) {
         return(TaskUtilities.FromError(error: exception));
     }
 }
Esempio n. 9
0
 Task P_DoStopAsync()
 {
     try {
         var cancellationTokenSource = ReadDA(ref _cancellationTokenSource);
         if (!cancellationTokenSource.IsCancellationRequested)
         {
             cancellationTokenSource.Cancel();
         }
         var loopTask = ReadDA(ref _loopTask);
         if (loopTask == null)
         {
             return(TaskUtilities.FromVoidResult());
         }
         else
         {
             return(loopTask);
         }
     }
     catch (Exception firstException) {
         return(TaskUtilities.FromError(error: firstException));
     }
 }
Esempio n. 10
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. 11
0
 // TODO: Put strings into the resources.
 //
 public Task <ILocalSubscription> SubscribeAsync(ILocalSubscription subscription)
 {
     try {
         subscription.EnsureNotNull(nameof(subscription));
         if (!ReferenceEquals(subscription.Publisher, this))
         {
             throw
                 new ArgumentOutOfRangeException(
                     paramName: nameof(subscription),
                     message: $"Subscription is not associated with this publisher.{Environment.NewLine}\tSubscription:{subscription.FmtStr().GNLI2()}{Environment.NewLine}\tPublisher:{this.FmtStr().GNLI2()}");
         }
         //
         var spinLock = ReadDA(ref _subscriptionsSpinLock);
         var subscriptionsDictionary          = ReadDA(ref _subscriptionsDictionary);
         var subscriptionsList                = ReadDA(ref _subscriptionsList);
         var existingSubscriptionRegistration = default(P_NewSubscriptionRegistrationState);
         //
         if (!spinLock.Invoke(() => subscriptionsDictionary.TryGetValue(subscription, out existingSubscriptionRegistration)))
         {
             var newSubscriptionRegistration = default(P_NewSubscriptionRegistrationState);
             try {
                 newSubscriptionRegistration = new P_NewSubscriptionRegistrationState(subscription);
                 spinLock
                 .Invoke(
                     () => {
                     EnsureNotDisposeState();
                     //
                     if (subscriptionsDictionary.ContainsKey(subscription))
                     {
                         existingSubscriptionRegistration = subscriptionsDictionary[subscription];
                     }
                     else
                     {
                         subscriptionsDictionary.Add(subscription, newSubscriptionRegistration);
                         existingSubscriptionRegistration = newSubscriptionRegistration;
                         subscriptionsList.Add(newSubscriptionRegistration.Subscription);
                     }
                 });
                 if (existingSubscriptionRegistration == newSubscriptionRegistration)
                 {
                     subscription
                     .ActivateAsync()
                     .ContinueWith(
                         locActivateTask => {
                         if (locActivateTask.IsCanceled)
                         {
                             newSubscriptionRegistration.SubscribeTaskProxy.TrySetCanceled();
                         }
                         else if (locActivateTask.IsFaulted)
                         {
                             if (!newSubscriptionRegistration.SubscribeTaskProxy.TrySetException(locActivateTask.Exception))
                             {
                                 throw new AggregateException(locActivateTask.Exception);
                             }
                         }
                         else
                         {
                             newSubscriptionRegistration.SubscribeTaskProxy.TrySetResult(newSubscriptionRegistration.Subscription);
                         }
                     },
                         TaskContinuationOptions.ExecuteSynchronously);
                 }
             }
             catch (Exception firstException) {
                 newSubscriptionRegistration?.SubscribeTaskProxy.TrySetException(firstException);
                 throw;
             }
             finally {
                 if (newSubscriptionRegistration != existingSubscriptionRegistration)
                 {
                     newSubscriptionRegistration?.SubscribeTaskProxy.TrySetCanceled();
                 }
             }
         }
         //
         return(existingSubscriptionRegistration.SubscribeTaskProxy.Task);
     }
     catch (Exception firstException) {
         return(TaskUtilities.FromError <ILocalSubscription>(firstException));
     }
 }
Esempio n. 12
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. 13
0
        // TODO: Put strings into the resources.
        //
        Task P_DoStartAsync(IRunControlAttemptState state)
        {
            // TODO_HIGH: Этот таймаут должен браться из контекста запуска (когда будет реализован) как время оставшееся для выполнения операции запуска.
            //
            const int loopStartMillisecondsTimeout = 10000;

            try {
                state.EnsureNotNull(nameof(state));
                //
                var ct = ReadDA(ref _cancellationTokenSource).Token;
                ManualResetEventSlim loopStartedEvent = default;
                try {
                    loopStartedEvent = new ManualResetEventSlim(initialState: false);
                    Task loopTask;
                    Interlocked
                    .Exchange(
                        location1: ref _loopTask,
                        value:
                        loopTask =
                            TaskUtilities
                            .RunOnDefaultScheduler(
                                action: P_Loop,
                                state: new P_LoopStartState(worker: this, loopStartedEvent: loopStartedEvent),
                                cancellationToken: ct,
                                options: TaskCreationOptions.PreferFairness | TaskCreationOptions.LongRunning));
                    if (!loopStartedEvent.Wait(millisecondsTimeout: loopStartMillisecondsTimeout))
                    {
                        loopStartedEvent.Dispose();
                        //
                        if (loopTask.IsCompleted)
                        {
                            throw
                                new EonException(
                                    message:
                                    "Цикл обработки очереди рабочих элементов не запустился в отведённое для запуска время. Время ожидания запуска истекло."
                                    + (loopTask.IsCanceled ? $"{Environment.NewLine}Задача цикла была отменена." : string.Empty),
                                    innerException: loopTask.IsFaulted ? loopTask.Exception : null);
                        }
                        else
                        {
                            throw
                                new TimeoutException(
                                    message: $"Цикл обработки очереди рабочих элементов не запустился в отведённое для запуска время. Время ожидания запуска истекло.{Environment.NewLine}Статус задачи цикла:{loopTask.Status.FmtStr().GNLI()}");
                        }
                    }
                    //
                    loopTask
                    .ContinueWith(
                        continuationAction: P_OnLoopTaskCompleted,
                        cancellationToken: CancellationToken.None,
                        continuationOptions: TaskContinuationOptions.PreferFairness,
                        scheduler: TaskScheduler.Default);
                }
                finally {
                    loopStartedEvent?.Dispose();
                }
                //
                return(TaskUtilities.FromVoidResult());
            }
            catch (Exception firstException) {
                return(TaskUtilities.FromError(error: firstException));
            }
        }
Esempio n. 14
0
            // TODO: Put strings into the resources.
            //
            public Task <IVh <T> > AcquireAsync(IContext context = default)
            {
                try {
                    var existingTask = itrlck.Get(ref _acquireTask);
                    var ct           = context?.Ct() ?? CancellationToken.None;
                    if (existingTask is null)
                    {
                        var newTaskProxy = default(TaskCompletionSource <IVh <T> >);
                        try {
                            newTaskProxy = new TaskCompletionSource <IVh <T> >(creationOptions: TaskCreationOptions.RunContinuationsAsynchronously);
                            if (itrlck.UpdateIfNullBool(location: ref _acquireTask, value: newTaskProxy.Task, current: out existingTask))
                            {
                                if (itrlck.Get(ref _releaseTask) is null)
                                {
                                    existingTask
                                    .ContinueWith(
                                        continuationAction: t => itrlck.SetNull(location: ref _acquireTask, comparand: t),
                                        continuationOptions: TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.NotOnRanToCompletion);
                                    doAcquireAsync(locContext: context).ContinueWithTryApplyResultTo(taskProxy: newTaskProxy);
                                }
                                else
                                {
                                    newTaskProxy.TrySetException(exception: new EonException(message: $"Invalid acquisition attempt.  Release operation has been attempted already.{Environment.NewLine}\tLease ID:{_id.FmtStr().GNLI2()}"));
                                }
                                return(existingTask);
                            }
                            else
                            {
                                return(existingTask.WaitResultAsync(ct: ct));
                            }
                        }
                        catch (Exception exception) {
                            if (newTaskProxy?.TrySetException(exception) == true)
                            {
                                return(newTaskProxy.Task);
                            }
                            else
                            {
                                throw;
                            }
                        }
                        finally {
                            if (!ReferenceEquals(newTaskProxy.Task, existingTask))
                            {
                                newTaskProxy.TrySetCanceled();
                            }
                        }
                    }
                    else
                    {
                        return(existingTask.WaitResultAsync(ct: ct));
                    }
                }
                catch (Exception exception) {
                    return(TaskUtilities.FromError <IVh <T> >(exception));
                }
                //
                async Task <IVh <T> > doAcquireAsync(IContext locContext)
                {
                    var locAcquire = itrlck.Get(ref _acquire);
                    var locRelease = itrlck.Get(ref _release);

                    if (itrlck.Get(ref _releaseTask) is null)
                    {
                        try {
                            IVh <T> locAcquired = default;
                            try {
                                locAcquired = await locAcquire(arg : locContext).ConfigureAwait(false);

                                if (locAcquired is null)
                                {
                                    throw new EonException(message: $"Instance acquisition method has returned invalid value '{locAcquired.FmtStr().G()}'.{Environment.NewLine}\tLease ID:{_id.FmtStr().GNLI2()}");
                                }
                                _acquireDateTime = DateTimeOffset.Now;
                                _logger
                                ?.LogDebug(
                                    eventId: LeasableEventIds.LeaseStart,
                                    message: $"Lease started.{Environment.NewLine}\tLease ID:{Environment.NewLine}\t\t{{lease_id}}{Environment.NewLine}\tCorrelation ID:{Environment.NewLine}\t\t{{correlation_id}}",
                                    args: new object[] { _id.ToString(), locContext?.FullCorrelationId.ToString() });

                                return(locAcquired);
                            }
                            catch (Exception locException) {
                                if (!(locAcquired is null))
                                {
                                    try {
                                        await locRelease(arg : locAcquired).ConfigureAwait(false);
                                    }
                                    catch (Exception locSecondException) {
                                        throw new AggregateException(locException, locSecondException);
                                    }
                                }
                                throw;
                            }
                        }
                        catch (Exception locException) {
                            try {
                                _logger
                                ?.LogWarning(
                                    eventId: LeasableEventIds.LeaseStart,
                                    exception: locException,
                                    message: $"Lease start error.{Environment.NewLine}\tLease ID:{Environment.NewLine}\t\t{{lease_id}}{Environment.NewLine}\tCorrelation ID:{Environment.NewLine}\t\t{{correlation_id}}",
                                    args: new object[] { _id.ToString(), locContext?.FullCorrelationId.ToString() });
                            }
                            catch (Exception locSecondException) {
                                throw new AggregateException(locException, locSecondException);
                            }
                            throw;
                        }
                    }
                    else
                    {
                        throw new EonException(message: $"Invalid lease start attempt. Lease end has been attempted already.{Environment.NewLine}\tLease ID:{_id.FmtStr().GNLI2()}");
                    }
                }
            }
Esempio n. 15
0
            public Task ReleaseAsync()
            {
                try {
                    var existingTask = itrlck.Get(ref _releaseTask);
                    if (existingTask is null)
                    {
                        var newTaskProxy = default(TaskCompletionSource <Nil>);
                        try {
                            newTaskProxy = new TaskCompletionSource <Nil>(creationOptions: TaskCreationOptions.RunContinuationsAsynchronously);
                            if (itrlck.UpdateIfNullBool(ref _releaseTask, newTaskProxy.Task, out existingTask))
                            {
                                doReleaseAsync().ContinueWithTryApplyResultTo(taskProxy: newTaskProxy);
                            }
                        }
                        catch (Exception exception) {
                            if (newTaskProxy?.TrySetException(exception) == true)
                            {
                                return(newTaskProxy.Task);
                            }
                            else
                            {
                                throw;
                            }
                        }
                        finally {
                            if (!ReferenceEquals(newTaskProxy.Task, existingTask))
                            {
                                newTaskProxy.TrySetCanceled();
                            }
                        }
                    }
                    return(existingTask);
                }
                catch (Exception exception) {
                    return(TaskUtilities.FromError(exception));
                }
                //
                async Task doReleaseAsync()
                {
                    Func <IContext, Task <IVh <T> > > locAcquire = default;
                    Task <IVh <T> >      locAcquireTask          = default;
                    Func <IVh <T>, Task> locRelease = default;

                    try {
                        locAcquire     = itrlck.Get(ref _acquire);
                        locRelease     = itrlck.Get(ref _release);
                        locAcquireTask = itrlck.Get(ref _acquireTask);
                        if (!(locAcquireTask is null))
                        {
                            await locAcquireTask.WaitCompletionAsync().ConfigureAwait(false);

                            if (locAcquireTask.IsSucceeded())
                            {
                                var       locAcquired        = locAcquireTask.Result;
                                var       locNowDateTime     = DateTimeOffset.Now;
                                Exception locCaughtException = default;
                                try {
                                    await locRelease(arg : locAcquired).ConfigureAwait(false);
                                }
                                catch (Exception locException) {
                                    locCaughtException = locException;
                                    throw;
                                }
                                finally {
                                    if (locCaughtException is null)
                                    {
                                        _logger
                                        ?.LogDebug(
                                            eventId: LeasableEventIds.LeaseEnd,
                                            message: $"Lease end.{Environment.NewLine}\tLease ID:{Environment.NewLine}\t\t{{lease_id}}{Environment.NewLine}\tLease duration:{Environment.NewLine}\t\t{{lease_duration}}",
                                            args: new object[] { _id.ToString(), locNowDateTime.Subtract(_acquireDateTime).ToString("c") });
                                    }
                                    else
                                    {
                                        try {
                                            _logger
                                            ?.LogWarning(
                                                eventId: LeasableEventIds.LeaseEnd,
                                                exception: locCaughtException,
                                                message: $"Lease end error.{Environment.NewLine}\tLease ID:{Environment.NewLine}\t\t{{lease_id}}{Environment.NewLine}\tLease duration:{Environment.NewLine}\t\t{{lease_duration}}",
                                                args: new object[] { _id.ToString(), locNowDateTime.Subtract(_acquireDateTime).ToString("c") });
                                        }
                                        catch (Exception locException) {
                                            throw new AggregateException(locCaughtException, locException);
                                        }
                                    }
                                }
                            }
                        }
                    }
                    finally {
                        itrlck.SetNullBool(ref _acquireTask, locAcquireTask);
                        itrlck.SetNullBool(ref _acquire, locAcquire);
                        itrlck.SetNullBool(ref _release, locRelease);
                    }
                }
            }