Sfoglia il codice sorgente

finalize PsProcessProviderBase. Add PsProcessProviderDummy

Dalibor Votruba 1 anno fa
parent
commit
4938cf42d4

+ 1 - 1
qdr.fnd.core.pqueue.test/Process/Mock/PsProcessProviderBaseMock.cs

@@ -6,7 +6,7 @@ namespace qdr.fnd.core.pqueue.test.Process.Mock
 {
     internal class PsProcessProviderBaseMock : PsProcessProviderBase
     {
-        public PsProcessProviderBaseMock(string itemId, TypedArgument[] arguments, ILogger logger) : base(itemId, arguments, logger)
+        public PsProcessProviderBaseMock(ProcessDoneCallback processDoneCallback, ProcessStdOutputCallback processStdOutputCallback, string itemId, TypedArgument[] arguments, ILogger logger) : base(processDoneCallback, processStdOutputCallback, itemId, arguments, logger)
         {
         }
     }

+ 0 - 19
qdr.fnd.core.pqueue.test/Process/Mock/PsProcessProviderDummyMock.cs

@@ -1,19 +0,0 @@
-using qdr.fnd.core.pqueue.Process;
-using Quadarax.Foundation.Core.Data;
-using Quadarax.Foundation.Core.Logging;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace qdr.fnd.core.pqueue.test.Process.Mock
-{
-    public class PsProcessProviderDummyMock : PsProcessProviderBase
-    {
-        public PsProcessProviderDummyMock(string itemId, TypedArgument[] arguments, ILogger logger) : base(itemId, arguments, logger)
-        {
-        }
-    }
-
-}

+ 50 - 0
qdr.fnd.core.pqueue/Exceptions/PsProcessProviderException.cs

@@ -0,0 +1,50 @@
+using Quadarax.Foundation.Core.Attributes;
+using Quadarax.Foundation.Core.Exceptions;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace qdr.fnd.core.pqueue.Exceptions
+{
+    public class PsProcessProviderException: CodeException<PsProcessProviderException.ErrorCodes>
+    {
+
+        #region *** Error Codes ***
+
+        public enum ErrorCodes : int
+        {
+            [ErrorMessage("Cannot start, process provider '{0}' (ItemId='{1}') is already running.")]
+            ProcessProviderIsRunning = 8000,
+            [ErrorMessage("Cannot stop, process provider '{0}' (ItemId='{1}') is not running.")]
+            ProcessProviderNotRunning = 8001,
+            [ErrorMessage("Process provider '{0}' (ItemId='{1}') has not defined argument '{2}'.")]
+            ProcessProviderNotDefinedArgument = 8002,
+        }
+        #endregion
+
+        #region *** Constructors ***
+
+        /// <inheritdoc />
+        public PsProcessProviderException(ErrorCodes code, Exception innerException) : base(code, innerException)
+        {
+        }
+
+        /// <inheritdoc />
+        public PsProcessProviderException(ErrorCodes code) : base(code)
+        {
+        }
+
+        /// <inheritdoc />
+        public PsProcessProviderException(ErrorCodes code, params object[] messageArguments) : base(code, messageArguments)
+        {
+        }
+
+        /// <inheritdoc />
+        public PsProcessProviderException(ErrorCodes code, Exception innerException, params object[] messageArguments) : base(code, innerException, messageArguments)
+        {
+        }
+        #endregion
+    }
+}

+ 2 - 2
qdr.fnd.core.pqueue/Process/IPsProcessProvider.cs

@@ -1,9 +1,9 @@
 namespace qdr.fnd.core.pqueue.Process
 {
-    public interface IPsProcessProvider
+    public interface IPsProcessProvider : IDisposable
     {
         void Validate();
-        void Start();
+        Task Start();
         void Stop();
     }
 }

+ 110 - 25
qdr.fnd.core.pqueue/Process/PsProcessProviderBase.cs

@@ -1,72 +1,157 @@
-using Quadarax.Foundation.Core.Data;
+using qdr.fnd.core.pqueue.Enums;
+using qdr.fnd.core.pqueue.Exceptions;
+using Quadarax.Foundation.Core.Data;
 using Quadarax.Foundation.Core.Logging;
 using Quadarax.Foundation.Core.Object;
+using Quadarax.Foundation.Core.Thread.Extensions;
+using Quadarax.Foundation.Core.Value.Extensions;
 
 namespace qdr.fnd.core.pqueue.Process
 {
-    public class PsProcessProviderBase : DisposableObject
+    public delegate void ProcessDoneCallback(string itemId, PsStatusEnum newStatus, string message);
+    public delegate void ProcessStdOutputCallback(string itemId, string message);
+
+    public abstract class PsProcessProviderBase : DisposableObject, IPsProcessProvider
     {
-        protected ILog Log { get; private set; }
 
+        #region *** Constants ***
+        /// <summary>
+        /// (Output) Argument name for the result code. Type is <see cref="long"/>
+        /// </summary>
+        public const string CS_ARG_RESULT_CODE = "result-code";
+        /// <summary>
+        /// (Output) Argument name for the result test. Type is <see cref="string"/>
+        /// </summary>
+        public const string CS_ARG_RESULT_TEXT = "result-text";
+        /// <summary>
+        /// (Input) Argument name for process timeout. Type is <see cref="TimeSpan"/>
+        /// </summary>
+        public const string CS_ARG_PROCESS_TIMEOUT = "process-timeout";
+        #endregion
+
+        #region *** Properties ***
+        protected ILog Log { get; private set; }
+        protected ProcessDoneCallback ProcessDoneCallback { get; private set; }
+        protected ProcessStdOutputCallback ProcessStdOutputCallback { get; private set; }
         public IDictionary<string, TypedArgument> Arguments { get; private set; }
         public bool IsRunning { get; private set; }
         public string ItemId { get; private set; }
 
-        public PsProcessProviderBase(string itemId, TypedArgument[] arguments, ILogger logger)
+        #endregion
+
+        #region *** Private fields ***
+        private CancellationTokenSource? _cancelationToken;
+        #endregion
+
+        #region *** Constructors ***
+        public PsProcessProviderBase(ProcessDoneCallback processDoneCallback, ProcessStdOutputCallback processStdOutputCallback, string itemId, TypedArgument[] arguments, ILogger logger)
         {
             if (string.IsNullOrEmpty(itemId)) throw new ArgumentNullException(nameof(itemId));
+            ProcessDoneCallback = processDoneCallback ?? throw new ArgumentNullException(nameof(processDoneCallback));
+            ProcessStdOutputCallback = processStdOutputCallback ?? throw new ArgumentNullException(nameof(processStdOutputCallback));
             ItemId = itemId;
             Log = logger.GetLogger(GetType());
             Arguments = arguments.ToDictionary(x => x.Name, x => x);
+            _cancelationToken = new CancellationTokenSource();
         }
-        #region Overrides of DisposableObject
-
-        /// <inheritdoc />
-        protected override void OnDisposing()
-        {
-            throw new NotImplementedException();
-        }
-
         #endregion
 
-        #region Implementation of IPsProcessProvider
+        #region *** Public Operations ***
 
         /// <inheritdoc />
         public void Validate()
         {
+            OnValidate();
         }
-
         /// <inheritdoc />
         public async Task Start()
         {
+            if (IsRunning)
+                throw new PsProcessProviderException(PsProcessProviderException.ErrorCodes.ProcessProviderIsRunning, GetType().Name, ItemId);
+
             Validate();
+            var dtStart = DateTime.Now;
+            IsRunning = true;
+            var timeout = GetArgumentValue<TimeSpan>(CS_ARG_PROCESS_TIMEOUT);
             try
             {
-                await OnProcess();
+                await OnProcess().TimeoutAfter(timeout).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.");
+                });
+                
             }
             catch (Exception e)
             {
-                await OnProcessError(e);
-                Log.Log(LogSeverityEnum.Error, "Provider running failed.", 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);
+                });
             }
+            finally
+            {
+                IsRunning = false;
+            }
+        }
+
+        /// <inheritdoc />
+        public async void Stop()
+        {
+               if (!IsRunning)
+                throw new PsProcessProviderException(PsProcessProviderException.ErrorCodes.ProcessProviderNotRunning, GetType().Name, ItemId);
+
+               //TODO: stops here
+        }
+        #endregion
+
+
+        #region *** Protected Operations ***
+        protected TValue? GetArgumentValue<TValue>(string name)
+        {
+            if (Arguments.TryGetValue(name, out var arg))
+                return arg.GetTypedValue<TValue>();
+            return default;
+        }
+        protected bool ContainsArgument(string name)
+        {
+            return Arguments.ContainsKey(name);
         }
 
-        private async Task OnProcessError(Exception exception)
+        protected virtual void OnValidate()
         {
-            throw new NotImplementedException();
+            if (!ContainsArgument(CS_ARG_RESULT_CODE) || !Arguments[CS_ARG_RESULT_CODE].IsOutput)
+                throw new PsProcessProviderException(PsProcessProviderException.ErrorCodes.ProcessProviderNotDefinedArgument, GetType().Name, ItemId, CS_ARG_RESULT_CODE);
+            if (!ContainsArgument(CS_ARG_RESULT_TEXT) || !Arguments[CS_ARG_RESULT_TEXT].IsOutput)
+                throw new PsProcessProviderException(PsProcessProviderException.ErrorCodes.ProcessProviderNotDefinedArgument, GetType().Name, ItemId, CS_ARG_RESULT_TEXT);
+            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);
+        }
+        protected virtual async Task OnProcessError(Exception exception)
+        {
+            if (ProcessStdOutputCallback != null)
+                ProcessStdOutputCallback(ItemId, exception.Message);
+
+            if (ContainsArgument(CS_ARG_RESULT_TEXT))
+                Arguments[CS_ARG_RESULT_TEXT].Value = exception.Message;
         }
 
-        private async Task OnProcess()
+        protected virtual async Task OnProcess()
         {
-            throw new NotImplementedException();
+            //nothing to do
         }
 
         /// <inheritdoc />
-        public async void Stop()
+        protected override void OnDisposing()
         {
-            throw new NotImplementedException();
+            ProcessDoneCallback = null!;
+            ProcessStdOutputCallback = null!;
         }
-
         #endregion
+
     }
-}
+
+}

+ 40 - 0
qdr.fnd.core.pqueue/Process/PsProcessProviderDummy.cs

@@ -0,0 +1,40 @@
+using qdr.fnd.core.pqueue.Exceptions;
+using Quadarax.Foundation.Core.Data;
+using Quadarax.Foundation.Core.Logging;
+
+namespace qdr.fnd.core.pqueue.Process
+{
+    public class PsProcessProviderDummy : PsProcessProviderBase
+    {
+
+        #region *** Constants ***
+        /// <summary>
+        /// (Input) Argument name for the result code. Type is <see cref="string"/>
+        /// </summary>
+        public const string CS_ARG_INPUT_TEXT = "input-text";
+        #endregion
+
+
+        #region *** Constructors ***
+        public PsProcessProviderDummy(ProcessDoneCallback processDoneCallback, ProcessStdOutputCallback processStdOutputCallback, string itemId, TypedArgument[] arguments, ILogger logger) : base(processDoneCallback, processStdOutputCallback, itemId, arguments, logger)
+        {
+        }
+        #endregion
+
+        #region *** Overrides ***
+        protected override void OnValidate()
+        {
+            base.OnValidate();
+            if (!ContainsArgument(CS_ARG_INPUT_TEXT) || !Arguments[CS_ARG_INPUT_TEXT].IsOutput)
+                throw new PsProcessProviderException(PsProcessProviderException.ErrorCodes.ProcessProviderNotDefinedArgument, GetType().Name, ItemId, CS_ARG_INPUT_TEXT);
+        }
+
+        protected override Task OnProcess()
+        {
+            Arguments[CS_ARG_RESULT_CODE].Value = "0";
+            Arguments[CS_ARG_RESULT_TEXT].Value = GetArgumentValue<string>(CS_ARG_INPUT_TEXT);
+            return base.OnProcess();
+        }
+        #endregion
+    }
+}