Explorar o código

PsQueue working StartStop, StartFail, StopFail - not working

Dalibor Votruba hai 1 ano
pai
achega
910cc75a9b

+ 52 - 3
qdr.fnd.core.pqueue.test/Process/PsProcessProviderBaseTest.cs

@@ -1,6 +1,5 @@
-using Newtonsoft.Json.Linq;
-using NUnit.Framework.Interfaces;
-using qdr.fnd.core.pqueue.Enums;
+using qdr.fnd.core.pqueue.Enums;
+using qdr.fnd.core.pqueue.Exceptions;
 using qdr.fnd.core.pqueue.fnd.candidates;
 using qdr.fnd.core.pqueue.Process;
 using qdr.fnd.core.pqueue.test.Mocks;
@@ -121,6 +120,56 @@ namespace qdr.fnd.core.pqueue.test.Process
             Assert.That(_statusDonePool[process.ItemId].Any(x => x.Item1 == PsStatusEnum.DoneOk), Is.True);
         }
 
+        [Test(TestOf=typeof(PsProcessProviderBase))]
+        public void StartFail()
+        {
+            var args = PsProcessProviderBaseMock.CreateArguments().ToArray();
+            args.SetArgumentValue<TimeSpan>(PsProcessProviderBase.CS_ARG_PROCESS_TIMEOUT, TimeSpan.FromSeconds(15));
+
+            var process = CreateProcess(args);
+            var dtStart = DateTime.Now;
+            process.Start();
+            Assert.That(process.IsRunning, Is.True);
+            var e = Assert.Throws<PsProcessProviderException>(()=>process.Start());
+            process.Stop();
+            Assert.That(e.Code, Is.EqualTo(PsProcessProviderException.ErrorCodes.ProcessProviderIsRunning));
+        }
+
+        [Test(TestOf=typeof(PsProcessProviderBase))]
+        public void StopFail()
+        {
+            var args = PsProcessProviderBaseMock.CreateArguments().ToArray();
+            args.SetArgumentValue<TimeSpan>(PsProcessProviderBase.CS_ARG_PROCESS_TIMEOUT, TimeSpan.FromSeconds(5));
+
+            var process = CreateProcess(args);
+            Assert.That(process.IsRunning, Is.False);
+            var e = Assert.Throws<PsProcessProviderException>(()=>process.Stop());
+            Assert.That(e.Code, Is.EqualTo(PsProcessProviderException.ErrorCodes.ProcessProviderNotRunning));
+        }
+
+
+
+        [Test(TestOf=typeof(PsProcessProviderBase))]
+        public void StartStopOk()
+        {
+            var args = PsProcessProviderBaseMock.CreateArguments().ToArray();
+            args.SetArgumentValue<TimeSpan>(PsProcessProviderBase.CS_ARG_PROCESS_TIMEOUT, TimeSpan.FromSeconds(5));
+
+            var process = CreateProcess(args);
+            var dtStart = DateTime.Now;
+            process.Start();
+            Task.Delay(TimeSpan.FromSeconds(1)).Wait();
+            process.Stop();
+            process.WaitToDone();
+            TestContext.WriteLine($"#Process duration check: {(DateTime.Now - dtStart).ToReadableString()}");
+
+            Assert.That(process.IsRunning, Is.False);
+            Assert.That(_statusDonePool.ContainsKey(process.ItemId), Is.True);
+            Assert.That(_statusDonePool[process.ItemId].Any(x => x.Item1 == PsStatusEnum.DoneFailed), Is.True);
+        }
+
+
+
         [Test(TestOf=typeof(PsProcessProviderBase))]
         public void StartTimeoutFail()
         {

+ 11 - 0
qdr.fnd.core.pqueue/Process/IPsProcessProvider.cs

@@ -18,6 +18,17 @@ namespace qdr.fnd.core.pqueue.Process
         /// </summary>
         string ItemId { get; }
 
+        /// <summary>
+        /// Gets information when the process started (by calling <see cref="Start"/> operation).
+        /// If process haven't been started yet, returns null.
+        /// </summary>
+        DateTime? StartedTimestamp { get; }
+        /// <summary>
+        /// Gets information when the process was finished (by calling <see cref="Stop"/> operation or when operation regullary ends).
+        /// If process haven't been finished yet, returns null.
+        /// </summary>
+        DateTime? FinishedTimestamp { get; }
+
         /// <summary>
         /// Validates the process arguments. Throws <see cref="PsProcessProviderException"/> if validation fails.
         /// </summary>

+ 33 - 36
qdr.fnd.core.pqueue/Process/PsProcessProviderBase.cs

@@ -33,9 +33,15 @@ namespace qdr.fnd.core.pqueue.Process
         protected ILog Log { get; private set; }
         protected ProcessDoneCallback ProcessDoneCallback { get; private set; }
         protected ProcessStdOutputCallback ProcessStdOutputCallback { get; private set; }
+        /// <inheritdoc />
         public IDictionary<string, TypedArgument> Arguments { get; private set; }
         public bool IsRunning { get; private set; }
+        /// <inheritdoc />
         public string ItemId { get; private set; }
+        /// <inheritdoc />
+        public DateTime? StartedTimestamp { get; private set; }
+        /// <inheritdoc />
+        public DateTime? FinishedTimestamp { get; private set; }
 
         #endregion
 
@@ -70,10 +76,11 @@ namespace qdr.fnd.core.pqueue.Process
                 throw new PsProcessProviderException(PsProcessProviderException.ErrorCodes.ProcessProviderIsRunning, GetType().Name, ItemId);
 
             Validate();
+            Log.Log(LogSeverityEnum.Info, $"Provider for ItemId='{ItemId}' starting.");
             IsRunning = true;
+            StartedTimestamp = DateTime.Now;
             var timeout = GetArgumentValue<TimeSpan>(CS_ARG_PROCESS_TIMEOUT);
 
-            var dtStart = DateTime.Now;
             try
             {
                 await TimeoutUtils.ExecuteWithTimeoutAsync(async () =>
@@ -81,10 +88,7 @@ namespace qdr.fnd.core.pqueue.Process
 
                     await OnProcess().ContinueWith(task =>
                     {
-                        Log.Log(LogSeverityEnum.Info, $"Provider for ItemId='{ItemId}' done. Duration {(DateTime.Now - dtStart).ToReadableString()}.");
-                        if (ProcessDoneCallback != null)
-                            ProcessDoneCallback(ItemId, PsStatusEnum.DoneOk, "Succesfuly done.");
-                        IsRunning = false;
+                        ProcessDoneOk("Succesfuly done.");
                     });
                 }, timeout);
             }
@@ -92,10 +96,7 @@ namespace qdr.fnd.core.pqueue.Process
             {
                 await OnProcessError(e).ContinueWith(task =>
                 {
-                    Log.Log(LogSeverityEnum.Error, $"Provider running failed. Duration {(DateTime.Now - dtStart).ToReadableString()}.", e);
-                    if (ProcessDoneCallback != null)
-                        ProcessDoneCallback(ItemId, PsStatusEnum.DoneFailed, e.Message);
-                    IsRunning = false;
+                    ProcessDoneFailed(e.Message, e);
                 });
             }
         }
@@ -106,8 +107,9 @@ namespace qdr.fnd.core.pqueue.Process
             if (!IsRunning)
                 throw new PsProcessProviderException(PsProcessProviderException.ErrorCodes.ProcessProviderNotRunning, GetType().Name, ItemId);
 
-            _cancelationToken?.Cancel();
-            IsRunning = false;
+            _cancelationToken?.Cancel();            
+            ProcessDoneFailed("Process was forced stopped.");
+            Log.Log(LogSeverityEnum.Info, $"Provider for ItemId='{ItemId}' was forced stopped.");
         }
 
         /// <summary>
@@ -164,7 +166,9 @@ namespace qdr.fnd.core.pqueue.Process
             if (!ContainsArgument(CS_ARG_PROCESS_TIMEOUT) || Arguments[CS_ARG_PROCESS_TIMEOUT].IsOutput)
                 throw new PsProcessProviderException(PsProcessProviderException.ErrorCodes.ProcessProviderNotDefinedArgument, GetType().Name, ItemId, CS_ARG_PROCESS_TIMEOUT);
         }
+#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
         protected virtual async Task OnProcessError(Exception exception)
+#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
         {
             if (exception == null)
                 throw new ArgumentNullException(nameof(exception));
@@ -176,7 +180,9 @@ namespace qdr.fnd.core.pqueue.Process
                 Arguments[CS_ARG_RESULT_TEXT].Value = exception.Message;
         }
 
+#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
         protected virtual async Task OnProcess()
+#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
         {
             //nothing to do
         }
@@ -184,38 +190,29 @@ namespace qdr.fnd.core.pqueue.Process
         /// <inheritdoc />
         protected override void OnDisposing()
         {
+            _cancelationToken?.Dispose();
             ProcessDoneCallback = null!;
             ProcessStdOutputCallback = null!;
+            _cancelationToken = null;
         }
 
 
-        private async Task StartInternal()
+        private void ProcessDoneFailed(string message, Exception? e = null)
         {
-            var dtStart = DateTime.Now;
-            try
-            {
-
-                await OnProcess().ContinueWith(task =>
-                {
-                    Log.Log(LogSeverityEnum.Info, $"Provider for ItemId='{ItemId}' done. Duration {(DateTime.Now - dtStart).ToReadableString()}.");
-                    if (ProcessDoneCallback != null)
-                        ProcessDoneCallback(ItemId, PsStatusEnum.DoneOk, "Succesfuly done.");
-                    IsRunning = false;
-                });
-
-            }
-            catch (Exception e)
-            {
-                await OnProcessError(e).ContinueWith(task =>
-                {
-                    Log.Log(LogSeverityEnum.Error, $"Provider running failed. Duration {(DateTime.Now - dtStart).ToReadableString()}.", e);
-                    if (ProcessDoneCallback != null)
-                        ProcessDoneCallback(ItemId, PsStatusEnum.DoneFailed, e.Message);
-                    IsRunning = false;
-                });
-            }
+            Log.Log(LogSeverityEnum.Error, $"Provider running failed. Duration {(DateTime.Now - StartedTimestamp.GetValueOrDefault()).ToReadableString()}.", e);
+            if (ProcessDoneCallback != null)
+                ProcessDoneCallback(ItemId, PsStatusEnum.DoneFailed, message);
+            IsRunning = false;
+            FinishedTimestamp = DateTime.Now;
+        }
+        private void ProcessDoneOk(string message)
+        {
+            Log.Log(LogSeverityEnum.Info, $"Provider for ItemId='{ItemId}' done. Duration {(DateTime.Now - StartedTimestamp.GetValueOrDefault()).ToReadableString()}.");
+            if (ProcessDoneCallback != null)
+                ProcessDoneCallback(ItemId, PsStatusEnum.DoneOk, message);
+            IsRunning = false;
+            FinishedTimestamp = DateTime.Now;
         }
-
 
 
         #endregion