소스 검색

PsQueue: finished PsQueueTest

Dalibor Votruba 1 년 전
부모
커밋
48bea1c882

+ 40 - 0
qdr.fnd.core.pqueue.test/Mocks/PsQueueItemMock.cs

@@ -0,0 +1,40 @@
+using qdr.fnd.core.pqueue.Storages;
+using Quadarax.Foundation.Core.Data;
+using Quadarax.Foundation.Core.Logging;
+using System.Xml.Linq;
+
+namespace qdr.fnd.core.pqueue.test.Mocks
+{
+    public class PsQueueItemMock : PsQueueItem
+    {
+        public PsQueueItemMock(string id) : base(id)
+        {
+        }
+        public PsQueueItemMock(string id, string owner, string ownerRef, string providerClass, DateTime created, ITypedArgument[]? arguments, int initialAttempts = 0): base(id, owner, ownerRef, providerClass, created, arguments, initialAttempts)
+        {
+        }
+
+        public void SetOwner(string owner, string ownerRef)
+        {
+            Owner = owner;
+            OwnerRef = ownerRef;
+        }
+
+        public void ClearArguments()
+        {
+            Arguments = new ITypedArgument[0];
+        }
+
+        public void AddToStorage(IPsQueueStorage storage)
+        {
+            var itemId = storage.CreateItem(Owner, OwnerRef, ProcessProviderClass, AtteptsInitial, null);
+            foreach (var argument in Arguments)
+            {
+                if (argument.ValueType.FullName == null) throw new InvalidOperationException($"Cannot obtain fullName of type '{argument.ValueType.Name}'");
+                
+                storage.CreateItemAttribute(itemId, argument.Name, argument.Value, argument.ValueType.FullName, argument.IsOutput);
+            }
+            Id = itemId;
+        }
+    }
+}

+ 5 - 2
qdr.fnd.core.pqueue.test/Mocks/PsQueueMock.cs

@@ -10,6 +10,9 @@ namespace qdr.fnd.core.pqueue.test.Mocks
 {
     internal class PsQueueMock : PsQueue
     {
+       
+        public IPsQueueStorage Storage => _storage;
+
         #region *** Constructors ***
         public PsQueueMock(string queueName, PsQueueConfiguration configuration, IPsQueueStorage storageProvider, ILogger logger) : base(queueName, configuration, storageProvider, logger)
         {
@@ -38,9 +41,9 @@ namespace qdr.fnd.core.pqueue.test.Mocks
         {
             SetItemStatusInternal(item, newStatus, isTransient, message);
         }
-        public IPsProcessProvider TestResolveProvider(string providerClass, IEnumerable<ITypedArgument> arguments)
+        public IPsProcessProvider TestResolveProvider(string itemId, string providerClass, IEnumerable<TypedArgument> arguments)
         {
-            return ResolveProvider(providerClass, arguments);
+            return ResolveProvider(itemId, providerClass, arguments);
         }
         public void TestEnsureItemStateExpired(IPsQueueItem item)
         {

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

@@ -4,11 +4,11 @@ using Quadarax.Foundation.Core.Logging;
 
 namespace qdr.fnd.core.pqueue.test.Process.Mock
 {
-    internal class PsProcessProviderBaseMock : PsProcessProviderBase
+    public class PsProcessProviderBaseMock : PsProcessProviderBase
     {
         public const string CS_ARG_EMIT_EXC = "emmit-exception";
 
-        public PsProcessProviderBaseMock(ProcessDoneCallback processDoneCallback, ProcessStdOutputCallback processStdOutputCallback, string itemId, TypedArgument[] arguments, ILogger logger) : base(processDoneCallback, processStdOutputCallback, itemId, arguments, logger)
+        public PsProcessProviderBaseMock(Callbacks callbacks, string itemId, TypedArgument[] arguments, ILogger logger) : base(callbacks, itemId, arguments, logger)
         {
         }
 

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

@@ -37,11 +37,11 @@ namespace qdr.fnd.core.pqueue.test.Process
         {
             var args = PsProcessProviderBaseMock.CreateArguments().ToArray();
             var itemId = "a";
-            Assert.Throws<ArgumentNullException>(() => new PsProcessProviderBaseMock(null!, OnProcessStdOut,itemId, args, new LoggerMock()));
-            Assert.Throws<ArgumentNullException>(() => new PsProcessProviderBaseMock(OnProcessDone, null!,itemId, args, new LoggerMock()));
-            Assert.Throws<ArgumentNullException>(() => new PsProcessProviderBaseMock(OnProcessDone, OnProcessStdOut,null!, args, new LoggerMock()));
-            Assert.Throws<ArgumentNullException>(() => new PsProcessProviderBaseMock(OnProcessDone, OnProcessStdOut,string.Empty, args, new LoggerMock()));
-            Assert.Throws<ArgumentNullException>(() => new PsProcessProviderBaseMock(OnProcessDone, OnProcessStdOut,itemId, null!, new LoggerMock()));
+            Assert.Throws<ArgumentNullException>(() => new PsProcessProviderBaseMock(new PsProcessProviderBase.Callbacks(null!, OnProcessStdOut),itemId, args, new LoggerMock()));
+            Assert.Throws<ArgumentNullException>(() => new PsProcessProviderBaseMock(new PsProcessProviderBase.Callbacks(OnProcessDone, null!),itemId, args, new LoggerMock()));
+            Assert.Throws<ArgumentNullException>(() => new PsProcessProviderBaseMock(new PsProcessProviderBase.Callbacks(OnProcessDone, OnProcessStdOut),null!, args, new LoggerMock()));
+            Assert.Throws<ArgumentNullException>(() => new PsProcessProviderBaseMock(new PsProcessProviderBase.Callbacks(OnProcessDone, OnProcessStdOut),string.Empty, args, new LoggerMock()));
+            Assert.Throws<ArgumentNullException>(() => new PsProcessProviderBaseMock(new PsProcessProviderBase.Callbacks(OnProcessDone, OnProcessStdOut),itemId, null!, new LoggerMock()));
         }
 
         [Test(TestOf=typeof(PsProcessProviderBase))]
@@ -211,7 +211,7 @@ namespace qdr.fnd.core.pqueue.test.Process
         private PsProcessProviderBaseMock CreateProcess(TypedArgument[] args)
         {
             var itemId = "a";
-            return new PsProcessProviderBaseMock(OnProcessDone, OnProcessStdOut, itemId, args, new LoggerMock());
+            return new PsProcessProviderBaseMock(new PsProcessProviderBase.Callbacks(OnProcessDone, OnProcessStdOut), itemId, args, new LoggerMock());
         }
 
         private void OnProcessStdOut(string itemId, string message)

+ 3 - 4
qdr.fnd.core.pqueue.test/PsQueueItemTest.cs

@@ -1,5 +1,4 @@
 using qdr.fnd.core.pqueue.Enums;
-using qdr.fnd.core.pqueue.test.Mocks;
 
 namespace qdr.fnd.core.pqueue.test
 {
@@ -22,7 +21,7 @@ namespace qdr.fnd.core.pqueue.test
         [Test(TestOf=typeof(PsQueueItem))]
         public void ConstructorOk()
         {
-            var item = new PsQueueItem(_id, _owner,_ownerRef,_providerClass,_created);
+            var item = new PsQueueItem(_id, _owner,_ownerRef,_providerClass,_created, null);
             Assert.That(item.Id, Is.EqualTo(_id));
             Assert.That(item.Owner, Is.EqualTo(_owner));
             Assert.That(item.OwnerRef, Is.EqualTo(_ownerRef));
@@ -46,7 +45,7 @@ namespace qdr.fnd.core.pqueue.test
         [Test(TestOf=typeof(PsQueueItem))]
         public void SetStatusOk()
         {
-            var item = new PsQueueItem(_id, _owner,_ownerRef,_providerClass,_created);
+            var item = new PsQueueItem(_id, _owner,_ownerRef,_providerClass,_created,null);
             Assert.That(item.Status, Is.EqualTo(_status));
             Assert.That(item.StatusJournal.Count, Is.EqualTo(0));
 
@@ -60,7 +59,7 @@ namespace qdr.fnd.core.pqueue.test
         [Test(TestOf=typeof(PsQueueItem))]
         public void SetStatusFail()
         {
-            var item = new PsQueueItem(_id, _owner,_ownerRef,_providerClass,_created);
+            var item = new PsQueueItem(_id, _owner,_ownerRef,_providerClass,_created, null);
             Assert.Throws<ArgumentNullException>(() => item.SetStatus(null,true,string.Empty));
         }
     }

+ 140 - 10
qdr.fnd.core.pqueue.test/PsQueueTest.cs

@@ -1,13 +1,11 @@
 using qdr.fnd.core.pqueue.Configuration;
 using qdr.fnd.core.pqueue.Enums;
+using qdr.fnd.core.pqueue.Exceptions;
 using qdr.fnd.core.pqueue.Storages;
 using qdr.fnd.core.pqueue.test.Mocks;
+using qdr.fnd.core.pqueue.test.Process.Mock;
 using Quadarax.Foundation.Core.Logging;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using Quadarax.Foundation.Core.Value.Generators;
 
 namespace qdr.fnd.core.pqueue.test
 {
@@ -32,7 +30,9 @@ namespace qdr.fnd.core.pqueue.test
         private PsStatusEnum _status = PsStatusEnum.New;
         private bool _statusTrancient = false;
         private string _statusMessage = "message";
-
+        private int _attemptsLeft = 3;
+        private TinyHash _hash = new TinyHash();
+        private IDictionary<string, List<PsStatusEnum>> _ItemStatuses = new Dictionary<string, List<PsStatusEnum>>();
         #endregion
 
         [SetUp]
@@ -42,6 +42,7 @@ namespace qdr.fnd.core.pqueue.test
             _logger = new LoggerMock();
             _configuration = new PsQueueConfiguration();
             _storageProvider = new MemoryStorageProvider(_logger);
+            _providerClass = typeof(PsProcessProviderBaseMock).AssemblyQualifiedName!;
         }
 
         [Test(TestOf=typeof(PsQueue))]
@@ -64,6 +65,12 @@ namespace qdr.fnd.core.pqueue.test
         {
             var queue = CreateQueue();
             queue.TestValidateItemId("aaa");
+        }
+
+        [Test(TestOf=typeof(PsQueue))]
+        public void ValidateItemIdFail()
+        {
+            var queue = CreateQueue();
             Assert.Throws<ArgumentNullException>(() => queue.TestValidateItemId(string.Empty));
             Assert.Throws<ArgumentNullException>(() => queue.TestValidateItemId(null!));
         }
@@ -73,28 +80,151 @@ namespace qdr.fnd.core.pqueue.test
         {
             var queue = CreateQueue();
             queue.TestValidateEmitter("aaa");
+        }
+
+        [Test(TestOf=typeof(PsQueue))]
+        public void ValidateEmitterFail()
+        {
+            var queue = CreateQueue();
             Assert.Throws<ArgumentNullException>(() => queue.TestValidateEmitter(string.Empty));
             Assert.Throws<ArgumentNullException>(() => queue.TestValidateEmitter(null!));
         }
 
+
         [Test(TestOf=typeof(PsQueue))]
         public void ValidateItemOk()
         {
             var queue = CreateQueue();
-            var item = CreaeQueueItem(_id);
+            var item = CreateQueueItem(_id);
             queue.TestValidateItem(item);
+        }
+
+        [Test(TestOf=typeof(PsQueue))]
+        public void ValidateItemFail()
+        {
+            var queue = CreateQueue();
+            var item = CreateQueueItem(_id);
+            Assert.Throws<ArgumentNullException>(()=>queue.TestValidateItem(null!));
+
+            item.SetOwner(string.Empty, string.Empty);
+            var e = Assert.Throws<PSQueueValidationException>(()=>queue.TestValidateItem(item));
+            Assert.That(e.Code, Is.EqualTo(PSQueueValidationException.ErrorCodes.OwnerRequired));
+            
+            item.SetOwner(_owner, string.Empty);
+            e = Assert.Throws<PSQueueValidationException>(()=>queue.TestValidateItem(item));
+            Assert.That(e.Code, Is.EqualTo(PSQueueValidationException.ErrorCodes.OwnerRefRequired));
+            
+            item.SetOwner(_owner, _ownerRef);
+            item.ClearArguments();
+            Assert.Throws<PsProcessProviderException>(() => queue.TestValidateItem(item));
+           
+        }
+
+        [Test(TestOf=typeof(PsQueue))]
+        public void SetItemStatusInternalOk()
+        {
+            var queue = CreateQueue();
+            var item = CreateQueueItem(_id);
+            item.AddToStorage(queue.Storage);
+
+
+            var testStatus = PsStatusEnum.Pending;
+            var initStatus = item.Status;
+
+            Assert.That(item.Status, Is.Not.EqualTo(testStatus));
+            queue.TestSetItemStatusInternal(item, testStatus, false, _owner);
+
+            var changedItem = queue.Storage.GetItem(item.Id);
+            Assert.That(changedItem.Status, Is.EqualTo(testStatus));
+            Assert.That(changedItem.IsStatusTransient, Is.EqualTo(false));
+            Assert.That(_ItemStatuses[changedItem.Id].LastOrDefault(), Is.EqualTo(testStatus));
+            Assert.That(changedItem.StatusJournal.Count, Is.EqualTo(1));
+            Assert.That(changedItem.StatusJournal.FirstOrDefault()?.PreviousStatus, Is.EqualTo(initStatus));
 
+            queue.TestSetItemStatusInternal(item, null, true, _owner);
+
+            changedItem = queue.Storage.GetItem(item.Id);
+            Assert.That(changedItem.Status, Is.EqualTo(testStatus));
+            Assert.That(changedItem.IsStatusTransient, Is.EqualTo(true));
+            Assert.That(_ItemStatuses[changedItem.Id].LastOrDefault(), Is.EqualTo(testStatus));
+            Assert.That(changedItem.StatusJournal.Count, Is.EqualTo(2));
+            Assert.That(changedItem.StatusJournal.LastOrDefault()?.PreviousIsStatusTransient, Is.EqualTo(false));
+            Assert.That(changedItem.StatusJournal.LastOrDefault()?.PreviousStatus, Is.EqualTo(testStatus));
+
+        }
+
+        [Test(TestOf=typeof(PsQueue))]
+        public void SetItemStatusInternalFail()
+        {
+            var queue = CreateQueue();
+            var item = CreateQueueItem(_id);
+            item.AddToStorage(queue.Storage);
+
+
+            var testStatus = PsStatusEnum.DoneOk;
+            var initStatus = item.Status;
+
+            Assert.That(item.Status, Is.Not.EqualTo(testStatus));
+            var e1 = Assert.Throws<PSQueueValidationException>(()=>queue.TestSetItemStatusInternal(item, null, false, _owner));
+            Assert.That(e1.Code, Is.EqualTo(PSQueueValidationException.ErrorCodes.InvalidStatusTransientCombination));
+
+            e1 = Assert.Throws<PSQueueValidationException>(()=>queue.TestSetItemStatusInternal(item, PsStatusEnum.DoneOk, false, _owner));
+            Assert.That(e1.Code, Is.EqualTo(PSQueueValidationException.ErrorCodes.InvalidStatusTransition));
+            
+        }
+
+        [Test(TestOf=typeof(PsQueue))]
+        public void ResolveProviderOk()
+        {
+            var queue = CreateQueue();
+            var arguments = PsProcessProviderBaseMock.CreateArguments();
+            var provider = queue.TestResolveProvider(_id, _providerClass, arguments);
+            Assert.That(provider, Is.Not.Null);
+            Assert.That(provider.ItemId, Is.EqualTo(_id));
+            Assert.That(provider.IsRunning, Is.EqualTo(false));
+            Assert.That(provider.Arguments.Values.Select(x=>x.Name), Is.EquivalentTo(arguments.Select(x=>x.Name)));
+            Assert.That(provider.Arguments.Values.Select(x=>x.Value), Is.EquivalentTo(arguments.Select(x=>x.Value)));
+            Assert.That(provider.Arguments.Values.Select(x=>x.ValueType), Is.EquivalentTo(arguments.Select(x=>x.ValueType)));
+        }
+
+        [Test(TestOf=typeof(PsQueue))]
+        public void ResolveProviderFail()
+        {
+            var queue = CreateQueue();
+            var arguments = PsProcessProviderBaseMock.CreateArguments();
+
+            var e1 = Assert.Throws<PSQueueValidationException>(()=>queue.TestResolveProvider(_id, null!, arguments));
+            Assert.That(e1.Code, Is.EqualTo(PSQueueValidationException.ErrorCodes.ProcessProviderRequired));
+            e1 = Assert.Throws<PSQueueValidationException>(()=>queue.TestResolveProvider(_id, string.Empty, arguments));
+            Assert.That(e1.Code, Is.EqualTo(PSQueueValidationException.ErrorCodes.ProcessProviderRequired));
+
+            e1 = Assert.Throws<PSQueueValidationException>(()=>queue.TestResolveProvider(string.Empty, "aaa", arguments));
+            Assert.That(e1.Code, Is.EqualTo(PSQueueValidationException.ErrorCodes.ProcessProviderCannotResolve));
+
+            e1 = Assert.Throws<PSQueueValidationException>(()=>queue.TestResolveProvider(string.Empty, _providerClass, arguments));
+            Assert.That(e1.Code, Is.EqualTo(PSQueueValidationException.ErrorCodes.ProcessProviderCannotResolve));
 
         }
 
         private PsQueueMock CreateQueue()
         {
-            return new PsQueueMock(_queueName, _configuration!, _storageProvider!, _logger!);
+            var ps = new PsQueueMock(_queueName, _configuration!, _storageProvider!, _logger!);
+            ps.ProcessItemStatusChanged += OnProcessItemStatusChanged;
+            return ps;
+        }
+
+        private void OnProcessItemStatusChanged(IPsQueue sender, PsQueueStatusChangedEventArgs e)
+        {
+            TestContext.WriteLine($"#StaChg: ItemId={e.ProcessQueueItemId}; newStatus={e.CurrentStatus}; isTransient='{e.CurrentIsStatusTransient}'");
+            if (_ItemStatuses.ContainsKey(e.ProcessQueueItemId))
+                _ItemStatuses[e.ProcessQueueItemId].Add(e.CurrentStatus);
+            else
+                _ItemStatuses.Add(e.ProcessQueueItemId, new List<PsStatusEnum> { e.CurrentStatus });
         }
 
-        private PsQueueItem CreaeQueueItem(string id)
+        private PsQueueItemMock CreateQueueItem(string id)
         {
-            var item = new PsQueueItem(id, _owner,_ownerRef,_providerClass,_created);
+            var item = new PsQueueItemMock(id, _owner,_ownerRef,_providerClass,_created, PsProcessProviderBaseMock.CreateArguments(), _attemptsLeft);
             return item;
         }
     }

+ 1 - 1
qdr.fnd.core.pqueue.test/Storages/Mocks/BaseStorageProviderMock.cs

@@ -28,7 +28,7 @@ namespace qdr.fnd.core.pqueue.test.Storages.Mocks
 
         /// <inheritdoc />
         protected override string OnCreateItem(string id, string owner, string ownerRef, string providerClass, int initialAttempts,
-            DateTime created, string s)
+            DateTime created)
         {
             return TestId;
         }

+ 1 - 1
qdr.fnd.core.pqueue/Exceptions/PSQueueValidationException.cs

@@ -20,7 +20,7 @@ namespace qdr.fnd.core.pqueue.Exceptions
             OwnerRefRequired = 7001,
             [ErrorMessage("Queue item validation: ProcessProvider value is required.")]
             ProcessProviderRequired = 7002,
-            [ErrorMessage("Queue item validation: ProcessProvider '{0}' type cannot be resolved.")]
+            [ErrorMessage("Queue item validation: ProcessProvider '{0}' type cannot be resolved. See inner exception ({1}) for more details.")]
             ProcessProviderCannotResolve = 7003,
             [ErrorMessage("Queue item validation: InitialAttempt must be bigger than zero.")]
             InitialAttemptMustBePositive = 7004,

+ 38 - 3
qdr.fnd.core.pqueue/Process/PsProcessProviderBase.cs

@@ -50,16 +50,22 @@ namespace qdr.fnd.core.pqueue.Process
         #endregion
 
         #region *** Constructors ***
-        public PsProcessProviderBase(ProcessDoneCallback processDoneCallback, ProcessStdOutputCallback processStdOutputCallback, string itemId, TypedArgument[] arguments, ILogger logger)
+        public PsProcessProviderBase(Callbacks callbacks, 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));
+            if (callbacks==null) throw new ArgumentNullException(nameof(callbacks));
+
+            ProcessDoneCallback = callbacks.ProcessDoneCallback ?? throw new ArgumentNullException("callbacks.ProcessDoneCallback");
+            ProcessStdOutputCallback = callbacks.ProcessStdOutputCallback ?? throw new ArgumentNullException("callbacks.ProcessStdOutputCallback");
             ItemId = itemId;
             Log = logger.GetLogger(GetType());
             Arguments = arguments.ToDictionary(x => x.Name, x => x);
             _cancelationToken = new CancellationTokenSource();
         }
+        public PsProcessProviderBase(ConstructorArguments constructorArguments)
+            : this(constructorArguments.Callbacks, constructorArguments.ItemId, constructorArguments.Arguments, constructorArguments.Logger)
+        {
+        }
         #endregion
 
         #region *** Public Operations ***
@@ -237,6 +243,35 @@ namespace qdr.fnd.core.pqueue.Process
 
         #endregion
 
+        #region *** Nested Classes ***
+        public class Callbacks
+        {
+            public ProcessDoneCallback ProcessDoneCallback { get; private set; }
+            public ProcessStdOutputCallback ProcessStdOutputCallback { get; private set; }
+
+            public Callbacks(ProcessDoneCallback processDoneCallback, ProcessStdOutputCallback processStdOutputCallback)
+            {
+                ProcessDoneCallback = processDoneCallback;
+                ProcessStdOutputCallback = processStdOutputCallback;
+            }
+        }
+        public class ConstructorArguments
+        {
+            public Callbacks Callbacks { get; private set; }
+            public string ItemId { get; private set; }
+            public TypedArgument[] Arguments { get; private set; }
+            public ILogger Logger { get; private set; }
+
+            public ConstructorArguments(Callbacks callbacks, string itemId, TypedArgument[] arguments, ILogger logger)
+            {
+                Callbacks = callbacks;
+                ItemId = itemId;
+                Arguments = arguments;
+                Logger = logger;
+            }
+        }
+        #endregion
+
     }
 
 }

+ 1 - 1
qdr.fnd.core.pqueue/Process/PsProcessProviderDummy.cs

@@ -16,7 +16,7 @@ namespace qdr.fnd.core.pqueue.Process
 
 
         #region *** Constructors ***
-        public PsProcessProviderDummy(ProcessDoneCallback processDoneCallback, ProcessStdOutputCallback processStdOutputCallback, string itemId, TypedArgument[] arguments, ILogger logger) : base(processDoneCallback, processStdOutputCallback, itemId, arguments, logger)
+        public PsProcessProviderDummy(Callbacks callbacks, string itemId, TypedArgument[] arguments, ILogger logger) : base(callbacks, itemId, arguments, logger)
         {
         }
         #endregion

+ 31 - 8
qdr.fnd.core.pqueue/PsQueue.cs

@@ -30,6 +30,7 @@ namespace qdr.fnd.core.pqueue
 
         #region *** Private Fields ***
         private TinyHash _hashGenerator;
+        private ILogger? _logger;
         protected IPsQueueStorage _storage;
         private List<Tuple<PsStatusEnum,PsStatusEnum[]>> _statusTransitions = new List<Tuple<PsStatusEnum, PsStatusEnum[]>>();
 
@@ -44,6 +45,8 @@ namespace qdr.fnd.core.pqueue
             if (string.IsNullOrEmpty(queueName))
                 queueName =CS_DEF_QUEUE_NAME + _hashGenerator.NewId();
 
+            _logger = logger;
+
             Configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
             _storage = storageProvider ?? throw new ArgumentNullException(nameof(storageProvider));
 
@@ -277,7 +280,7 @@ namespace qdr.fnd.core.pqueue
                         continue;
                     }
                     _storage.UpdateItemAttempts(item.Id, item.AttemptsLeft - 1);
-                    var provider = ResolveProvider(item.ProcessProviderClass, item.Arguments);
+                    var provider = ResolveProvider(item.Id, item.ProcessProviderClass, item.Arguments);
                     _storage.UpdateItemStarted(item.Id, DateTime.Now);
                     _storage.UpdateItemFinished(item.Id, null);
                     _workingItems.TryAdd(item.Id, provider);
@@ -329,7 +332,8 @@ namespace qdr.fnd.core.pqueue
             if (string.IsNullOrEmpty(item.OwnerRef))
                 throw new PSQueueValidationException(PSQueueValidationException.ErrorCodes.OwnerRefRequired);
 
-            var provider =  ResolveProvider(item.ProcessProviderClass, item.Arguments);
+            // put OwnerRef instead of Id because Id is not known yet
+            var provider =  ResolveProvider(item.OwnerRef, item.ProcessProviderClass, item.Arguments);
             provider.Validate();
 
             if (item.AtteptsInitial <= 0)
@@ -351,25 +355,35 @@ namespace qdr.fnd.core.pqueue
                     throw new PSQueueValidationException(PSQueueValidationException.ErrorCodes.InvalidStatusTransition, oldStatus,newStatus ?? oldStatus, string.Join(",", _statusTransitions.First(x => x.Item1 == oldStatus).Item2.Select(x=>x.ToString())));
             }
 
-            _storage.AppendStatusJournal(item.Id, newStatus ?? oldStatus, isTransient, message);
+            _storage.AppendStatusJournal(item.Id, oldStatus, oldIsTransient, message);
             _storage.UpdateItemStatus(item.Id, newStatus, isTransient);
             ((PsQueueItem)item).SetStatus(newStatus, isTransient, message);
             ProcessItemStatusChanged?.Invoke(this, new PsQueueStatusChangedEventArgs(item.Id) { CurrentStatus = newStatus ?? oldStatus, CurrentIsStatusTransient = isTransient, PreviousStatus = oldStatus, PreviousIsStatusTransient = oldIsTransient });
             Log(LogSeverityEnum.Debug, $"{Name} - Item [{item.Id}] changed status '{oldStatus}[{oldIsTransient}]' to '{(newStatus ?? oldStatus)}[{isTransient}]'.");
         }
 
-        protected IPsProcessProvider ResolveProvider(string providerClass, IEnumerable<ITypedArgument> arguments)
+        protected IPsProcessProvider ResolveProvider(string itemId, string providerClass, IEnumerable<ITypedArgument> arguments)
         {
             if (string.IsNullOrEmpty(providerClass))
                 throw new PSQueueValidationException(PSQueueValidationException.ErrorCodes.ProcessProviderRequired);
 
             var providerType = Type.GetType(providerClass);
             if (providerType == null)
-                throw new PSQueueValidationException(PSQueueValidationException.ErrorCodes.ProcessProviderCannotResolve, providerClass);
-
-            var provider = Activator.CreateInstance(providerType, arguments) as IPsProcessProvider;
+                throw new PSQueueValidationException(PSQueueValidationException.ErrorCodes.ProcessProviderCannotResolve, providerClass, string.Empty);
+            //public PsProcessProviderBaseMock(Callbacks callbacks, string itemId, TypedArgument[] arguments, ILogger logger)
+            var callbacks = new PsProcessProviderBase.Callbacks(OnProcessDone, OnProcessStdOut);
+            var typedArguments = arguments.Select(x => new TypedArgument(x.Name, x.ValueType, x.Value, x.IsOutput)).ToArray();
+            IPsProcessProvider? provider;
+            try
+            {
+                provider = Activator.CreateInstance(providerType, callbacks,itemId, typedArguments, _logger) as IPsProcessProvider;
+            }
+            catch (Exception ex)
+            {
+                throw new PSQueueValidationException(PSQueueValidationException.ErrorCodes.ProcessProviderCannotResolve, ex.InnerException!, providerClass, ex.InnerException?.Message!);
+            }
             if (provider == null)
-                throw new PSQueueValidationException(PSQueueValidationException.ErrorCodes.ProcessProviderCannotResolve, providerClass);
+                throw new PSQueueValidationException(PSQueueValidationException.ErrorCodes.ProcessProviderCannotResolve, providerClass, string.Empty);
 
             return provider;
         }
@@ -422,6 +436,15 @@ namespace qdr.fnd.core.pqueue
             _workingItems = null!;
         }
         
+        private void OnProcessDone(string itemId, PsStatusEnum newStatus, string message)
+        {
+            //TODO: implements
+        }
+        private void OnProcessStdOut(string itemId, string message)
+        {
+            //TODO: implements
+        }
+
         #endregion
     }
 }

+ 4 - 3
qdr.fnd.core.pqueue/PsQueueItem.cs

@@ -61,10 +61,10 @@ namespace qdr.fnd.core.pqueue
         #endregion
         #region *** Constructors ***
 
-        public PsQueueItem(string id) : this(id, string.Empty, string.Empty, string.Empty, DateTime.Now)
+        public PsQueueItem(string id) : this(id, string.Empty, string.Empty, string.Empty, DateTime.Now, null)
         {
         }
-        public PsQueueItem(string id, string owner, string ownerRef, string providerClass, DateTime created)
+        public PsQueueItem(string id, string owner, string ownerRef, string providerClass, DateTime created, ITypedArgument[]? arguments, int initialAttempts = 0)
         {
             Id = id;
             Status = PsStatusEnum.New;
@@ -73,8 +73,9 @@ namespace qdr.fnd.core.pqueue
             OwnerRef = ownerRef;
             ProcessProviderClass = providerClass;
             Created = created;
+            AtteptsInitial = initialAttempts;
 
-            Arguments = new List<ITypedArgument>();
+            Arguments = arguments == null ? new List<ITypedArgument>() : new List<ITypedArgument>(arguments);
             Log = new List<IError>();
             StatusJournal = new List<PsStatusHistory>();
         }

+ 2 - 2
qdr.fnd.core.pqueue/Storages/BaseStorageProvider.cs

@@ -48,13 +48,13 @@ namespace qdr.fnd.core.pqueue.Storages
 
             var id = _tranGenerator.NewId();
 
-            var newId = OnCreateItem(id, owner, ownerRef, providerClass, initialAttempts, created.Value, id);
+            var newId = OnCreateItem(id, owner, ownerRef, providerClass, initialAttempts, created.Value);
 
             _log?.Log(LogSeverityEnum.Trace, $"Item [id={id}, owner={owner}, ownerRef{ownerRef}] created.");
             return newId;
         }
 
-        protected abstract string OnCreateItem(string id, string owner, string ownerRef, string providerClass, int initialAttempts, DateTime created, string s);
+        protected abstract string OnCreateItem(string id, string owner, string ownerRef, string providerClass, int initialAttempts, DateTime created);
 
         /// <inheritdoc />
         public void DeleteItem(string itemId)

+ 2 - 2
qdr.fnd.core.pqueue/Storages/MemoryStorageProvider.cs

@@ -35,9 +35,9 @@ namespace qdr.fnd.core.pqueue.Storages
 
         /// <inheritdoc />
         protected override string OnCreateItem(string id, string owner, string ownerRef, string providerClass, int initialAttempts,
-            DateTime created, string s)
+            DateTime created)
         {
-            var item = new PsQueueItem(id, owner, ownerRef, providerClass, created)
+            var item = new PsQueueItem(id, owner, ownerRef, providerClass, created, null)
             {
                 AttemptsLeft = initialAttempts
             };