ソースを参照

complete MemoryStorageProvider tests

Dalibor Votruba 2 年 前
コミット
6f57e704a3

+ 6 - 6
qdr.fnd.core.pqueue.test/Mocks/LogMock.cs

@@ -15,31 +15,31 @@ namespace qdr.fnd.core.pqueue.test.Mocks
         /// <inheritdoc />
         public void Log(LogSeverityEnum severity, int code, string message)
         {
-            Trace.WriteLine($"[{code}]: {message}", severity.ToString());
+            TestContext.WriteLine($"[{code}]: {message}", severity.ToString());
         }
 
         /// <inheritdoc />
         public void Log(LogSeverityEnum severity, string message)
         {
-            Trace.WriteLine($"{message}", severity.ToString());
+            TestContext.WriteLine($"{message}", severity.ToString());
         }
 
         /// <inheritdoc />
         public void Log(LogSeverityEnum severity, string message, Exception? exception)
         {
             if (exception != null)
-                Trace.WriteLine($"{message}\n{exception}", severity.ToString());
+                TestContext.WriteLine($"{message}\n{exception}", severity.ToString());
             else
-                Trace.WriteLine($"{message}", severity.ToString());
+                TestContext.WriteLine($"{message}", severity.ToString());
         }
 
         /// <inheritdoc />
         public void Log(LogSeverityEnum severity, int code, string message, Exception? exception)
         {
             if (exception != null)
-                Trace.WriteLine($"[{code}] {message}\n{exception}", severity.ToString());
+                TestContext.WriteLine($"[{code}] {message}\n{exception}", severity.ToString());
             else
-                Trace.WriteLine($"[{code}] {message}", severity.ToString());
+                TestContext.WriteLine($"[{code}] {message}", severity.ToString());
 
         }
 

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

@@ -5,19 +5,16 @@ namespace qdr.fnd.core.pqueue.test
 {
     public class PsQueueItemTest
     {
-        private LoggerMock _logger;
         private string _id = "id";
         private string _owner = "owner";
         private string _ownerRef = "ownerRef";
         private string _providerClass = "providerClass";
-        private int _initialAttempts = 10;
         private DateTime _created = DateTime.Now;
         private PsStatusEnum _status = PsStatusEnum.New;
 
         [SetUp]
         public void Setup()
         {
-            _logger = new LoggerMock();
         }
 
         [Test(TestOf=typeof(PsQueueItem))]

+ 5 - 0
qdr.fnd.core.pqueue.test/Storages/BaseStorageProviderTest.cs

@@ -8,6 +8,11 @@ namespace qdr.fnd.core.pqueue.test.Storages
     {
         private LoggerMock _logger;
         
+        [SetUp]
+        public void Setup()
+        {
+            _logger = new LoggerMock();
+        }
         
         [Test(TestOf=typeof(BaseStorageProvider))]
         public void CreateItemOk()

+ 423 - 2
qdr.fnd.core.pqueue.test/Storages/MemoryStorageProviderTest.cs

@@ -1,7 +1,11 @@
-using qdr.fnd.core.pqueue.Exceptions;
+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.Storages.Mocks;
+using Quadarax.Foundation.Core.Data;
+using Quadarax.Foundation.Core.Value.Extensions;
+using Quadarax.Foundation.Core.Value.Generators;
 
 namespace qdr.fnd.core.pqueue.test.Storages
 {
@@ -10,7 +14,6 @@ namespace qdr.fnd.core.pqueue.test.Storages
         private LoggerMock _logger;
 
 
-        private string _id = "id";
         private string _owner = "owner";
         private string _ownerRef = "ownerRef";
         private string _providerClass = "providerClass";
@@ -66,7 +69,425 @@ namespace qdr.fnd.core.pqueue.test.Storages
             Assert.That(psEx.Code, Is.EqualTo(PSStorageException.ErrorCodes.PsStorageItemNotFound));
         }
 
+        [Test(TestOf=typeof(MemoryStorageProvider))]
+        public void UpdateItemPriorityOk()
+        {
+            var provider = new MemoryStorageProvider(_logger);
+            var itemId = provider.CreateItem(_owner, _ownerRef, _providerClass, _initialAttempts, _created);
+            var priority = 99;
+            var item = provider.GetItem(itemId);
+            Assert.That(item.Priority, Is.Not.EqualTo(priority));
+
+            provider.UpdateItemPriority(itemId, priority);
+
+            item = provider.GetItem(itemId);
+            Assert.That(item.Priority, Is.EqualTo(priority));
+        }
+
+        [Test(TestOf = typeof(MemoryStorageProvider))]
+        public void UpdateItemPriorityFail()
+        {
+            var provider = new MemoryStorageProvider(_logger);
+            Assert.Throws<ArgumentNullException>(() => provider.UpdateItemPriority(string.Empty,0));
+            var psEx = Assert.Throws<PSStorageException>(() => provider.DeleteItem("not-exists"));
+            Assert.That(psEx, Is.Not.Null);
+            Assert.That(psEx.Code, Is.EqualTo(PSStorageException.ErrorCodes.PsStorageItemNotFound));
+        }
+
+        [Test(TestOf=typeof(MemoryStorageProvider))]
+        public void UpdateItemValidityOk()
+        {
+            var provider = new MemoryStorageProvider(_logger);
+            var itemId = provider.CreateItem(_owner, _ownerRef, _providerClass, _initialAttempts, _created);
+            var validFrom = DateTime.Now;
+            var validTo = validFrom.AddHours(1);
+            var item = provider.GetItem(itemId);
+            Assert.That(item.ValidFrom, Is.Not.EqualTo(validFrom));
+            Assert.That(item.ValidTo, Is.Not.EqualTo(validTo));
+
+            provider.UpdateItemValidity(itemId, validFrom, validTo);
+
+            item = provider.GetItem(itemId);
+            Assert.That(item.ValidFrom, Is.EqualTo(validFrom));
+            Assert.That(item.ValidTo, Is.EqualTo(validTo));
+
+            provider.UpdateItemValidity(itemId, validFrom, null);
+            Assert.That(item.ValidTo, Is.Null);
+        }
+
+        [Test(TestOf = typeof(MemoryStorageProvider))]
+        public void UpdateItemValidityFail()
+        {
+            var provider = new MemoryStorageProvider(_logger);
+            Assert.Throws<ArgumentNullException>(() => provider.UpdateItemValidity(string.Empty,DateTime.Now, DateTime.Now));
+            var psEx = Assert.Throws<PSStorageException>(() => provider.UpdateItemValidity("not-exists",DateTime.Now, DateTime.Now));
+            Assert.That(psEx, Is.Not.Null);
+            Assert.That(psEx.Code, Is.EqualTo(PSStorageException.ErrorCodes.PsStorageItemNotFound));
+        }
+        [Test(TestOf = typeof(MemoryStorageProvider))]
+        public void GetItemFail()
+        {
+            var provider = new MemoryStorageProvider(_logger);
+            Assert.Throws<ArgumentNullException>(() => provider.GetItem(string.Empty));
+            var psEx = Assert.Throws<PSStorageException>(() => provider.GetItem("not-exists"));
+            Assert.That(psEx, Is.Not.Null);
+            Assert.That(psEx.Code, Is.EqualTo(PSStorageException.ErrorCodes.PsStorageItemNotFound));
+        }
+
+        [Test(TestOf=typeof(MemoryStorageProvider))]
+        public void UpdateItemStatusOk()
+        {
+            var provider = new MemoryStorageProvider(_logger);
+            var itemId = provider.CreateItem(_owner, _ownerRef, _providerClass, _initialAttempts, _created);
+            var status = PsStatusEnum.DoneOk;
+            var transient = true;
+            var item = provider.GetItem(itemId);
+            Assert.That(item.Status, Is.Not.EqualTo(status));
+            Assert.That(item.IsStatusTransient, Is.Not.EqualTo(transient));
+
+            provider.UpdateItemStatus(itemId, status, transient);
+
+            item = provider.GetItem(itemId);
+            Assert.That(item.Status, Is.EqualTo(status));
+            Assert.That(item.IsStatusTransient, Is.EqualTo(transient));
+
+            provider.UpdateItemStatus(itemId, null, !transient);
+            item = provider.GetItem(itemId);
+            Assert.That(item.Status, Is.EqualTo(status));
+            Assert.That(item.IsStatusTransient, Is.EqualTo(!transient));
+          
+        }
+
+        [Test(TestOf = typeof(MemoryStorageProvider))]
+        public void UpdateItemStatusFail()
+        {
+            var provider = new MemoryStorageProvider(_logger);
+            Assert.Throws<ArgumentNullException>(() => provider.UpdateItemStatus(string.Empty,null, true));
+            var psEx = Assert.Throws<PSStorageException>(() => provider.UpdateItemStatus("not-exists",null, true));
+            Assert.That(psEx, Is.Not.Null);
+            Assert.That(psEx.Code, Is.EqualTo(PSStorageException.ErrorCodes.PsStorageItemNotFound));
+        }
+
+        [Test(TestOf=typeof(MemoryStorageProvider))]
+        public void UpdateItemStartedOk()
+        {
+            var provider = new MemoryStorageProvider(_logger);
+            var itemId = provider.CreateItem(_owner, _ownerRef, _providerClass, _initialAttempts, _created);
+            var started = DateTime.Now;
+            var item = provider.GetItem(itemId);
+            Assert.That(item.Started, Is.Not.EqualTo(started));
+
+            provider.UpdateItemStarted(itemId, started);
+
+            item = provider.GetItem(itemId);
+            Assert.That(item.Started, Is.EqualTo(started));
+
+            provider.UpdateItemStarted(itemId, null);
+            item = provider.GetItem(itemId);
+            Assert.That(item.Started, Is.Null);
+          
+        }
+
+        [Test(TestOf = typeof(MemoryStorageProvider))]
+        public void UpdateItemStartedFail()
+        {
+            var provider = new MemoryStorageProvider(_logger);
+            Assert.Throws<ArgumentNullException>(() => provider.UpdateItemStarted(string.Empty,null));
+            var psEx = Assert.Throws<PSStorageException>(() => provider.UpdateItemStarted("not-exists",null));
+            Assert.That(psEx, Is.Not.Null);
+            Assert.That(psEx.Code, Is.EqualTo(PSStorageException.ErrorCodes.PsStorageItemNotFound));
+        }
+
+        [Test(TestOf=typeof(MemoryStorageProvider))]
+        public void UpdateItemFinishedOk()
+        {
+            var provider = new MemoryStorageProvider(_logger);
+            var itemId = provider.CreateItem(_owner, _ownerRef, _providerClass, _initialAttempts, _created);
+            var finished = DateTime.Now;
+            var item = provider.GetItem(itemId);
+            Assert.That(item.Finished, Is.Not.EqualTo(finished));
+
+            provider.UpdateItemFinished(itemId, finished);
+
+            item = provider.GetItem(itemId);
+            Assert.That(item.Finished, Is.EqualTo(finished));
+
+            provider.UpdateItemFinished(itemId, null);
+            item = provider.GetItem(itemId);
+            Assert.That(item.Finished, Is.Null);
+          
+        }
+
+        [Test(TestOf = typeof(MemoryStorageProvider))]
+        public void UpdateItemFinishedFail()
+        {
+            var provider = new MemoryStorageProvider(_logger);
+            Assert.Throws<ArgumentNullException>(() => provider.UpdateItemFinished(string.Empty,null));
+            var psEx = Assert.Throws<PSStorageException>(() => provider.UpdateItemFinished("not-exists",null));
+            Assert.That(psEx, Is.Not.Null);
+            Assert.That(psEx.Code, Is.EqualTo(PSStorageException.ErrorCodes.PsStorageItemNotFound));
+        }
+
+        [Test(TestOf=typeof(MemoryStorageProvider))]
+        public void CreateItemAttributeOk()
+        {
+            var provider = new MemoryStorageProvider(_logger);
+            var typeClass = "System.String";
+            var value = "valueXXX";
+            var itemId = provider.CreateItem(_owner, _ownerRef, _providerClass, _initialAttempts, _created);
+            var item = provider.GetItem(itemId);
+            Assert.That(item.Arguments.Count(), Is.EqualTo(0));
+
+            provider.CreateItemAttribute(itemId, _owner, value,typeClass,true);
+            item = provider.GetItem(itemId);
+
+            Assert.That(item.Arguments.FirstOrDefault(x=>x.Name == _owner), Is.Not.Null);
+            var attr = item.Arguments.First(x=>x.Name == _owner);
+            Assert.That(attr.ValueType.FullName, Is.EqualTo(Type.GetType(typeClass)?.FullName));
+            Assert.That(attr.IsOutput, Is.EqualTo(true));
+          
+        }
+
+        [Test(TestOf = typeof(MemoryStorageProvider))]
+        public void CreateItemAttributeFail()
+        {
+            var provider = new MemoryStorageProvider(_logger);
+            var typeClass = "System.String";
+            var value = "valueXXX";
+
+            Assert.Throws<ArgumentNullException>(() => provider.CreateItemAttribute(string.Empty,_owner,typeClass, value, true));
+            var psEx = Assert.Throws<PSStorageException>(() => provider.CreateItemAttribute("non=exists",_owner,typeClass, value, true));
+            Assert.That(psEx, Is.Not.Null);
+            Assert.That(psEx.Code, Is.EqualTo(PSStorageException.ErrorCodes.PsStorageItemNotFound));
+
+            var itemId = provider.CreateItem(_owner, _ownerRef, _providerClass, _initialAttempts, _created);
+            provider.CreateItemAttribute(itemId, _owner, value,typeClass,true); 
+            psEx = Assert.Throws<PSStorageException>(() => provider.CreateItemAttribute(itemId,_owner,typeClass, value, true));
+            Assert.That(psEx, Is.Not.Null);
+            Assert.That(psEx.Code, Is.EqualTo(PSStorageException.ErrorCodes.PsStorageItemArgumentAlreadyExists));
+
+            Assert.Throws<ArgumentNullException>(() => provider.CreateItemAttribute(itemId,string.Empty,typeClass, value, true));
+            Assert.Throws<ArgumentNullException>(() => provider.CreateItemAttribute(itemId, null!, typeClass, value, true));
+            Assert.Throws<ArgumentNullException>(() => provider.CreateItemAttribute(itemId,"non-exists",string.Empty, value, true));
+            Assert.Throws<ArgumentNullException>(() => provider.CreateItemAttribute(itemId, "non-exists", null!, value, true));
+        }
+
+        [Test(TestOf=typeof(MemoryStorageProvider))]
+        public void UpdateItemAttributeOk()
+        {
+            var provider = new MemoryStorageProvider(_logger);
+            var typeClass = "System.String";
+            var value = "valueXXX";
+            var itemId = provider.CreateItem(_owner, _ownerRef, _providerClass, _initialAttempts, _created);
+            var item = provider.GetItem(itemId);
+            Assert.That(item.Arguments.Count(), Is.EqualTo(0));
+
+            provider.CreateItemAttribute(itemId, _owner, value,typeClass,true);
+            item = provider.GetItem(itemId);
+            var attr = item.Arguments.FirstOrDefault(x=>x.Name == _owner);
+            Assert.That(attr, Is.Not.Null);
+            provider.UpdateItemAttribute(itemId, _owner, value + "1");
+            item = provider.GetItem(itemId);
+            attr = item.Arguments.FirstOrDefault(x=>x.Name == _owner);
+            Assert.That(attr, Is.Not.Null);
+            Assert.That(attr.Value, Is.EqualTo(value + "1"));
+          
+        }
+
+        [Test(TestOf = typeof(MemoryStorageProvider))]
+        public void UpdateItemAttributeFail()
+        {
+            var provider = new MemoryStorageProvider(_logger);
+            var typeClass = "System.String";
+
+            var itemId = provider.CreateItem(_owner, _ownerRef, _providerClass, _initialAttempts, _created);
+            var psEx = Assert.Throws<PSStorageException>(() => provider.UpdateItemAttribute(itemId,_owner,typeClass));
+            Assert.That(psEx, Is.Not.Null);
+            Assert.That(psEx.Code, Is.EqualTo(PSStorageException.ErrorCodes.PsStorageItemArgumentNotFound));
+
+            Assert.Throws<ArgumentNullException>(() => provider.UpdateItemAttribute(itemId,string.Empty,typeClass));
+            Assert.Throws<ArgumentNullException>(() => provider.UpdateItemAttribute(itemId, null!, typeClass));
+           
+        }
 
+        [Test(TestOf=typeof(MemoryStorageProvider))]
+        public void DeleteItemAttributeOk()
+        {
+            var provider = new MemoryStorageProvider(_logger);
+            var typeClass = "System.String";
+            var value = "valueXXX";
+            var itemId = provider.CreateItem(_owner, _ownerRef, _providerClass, _initialAttempts, _created);
+            var item = provider.GetItem(itemId);
+            Assert.That(item.Arguments.Count(), Is.EqualTo(0));
+
+            provider.CreateItemAttribute(itemId, _owner, value,typeClass,true);
+            item = provider.GetItem(itemId);
+            var attr = item.Arguments.FirstOrDefault(x=>x.Name == _owner);
+            Assert.That(attr, Is.Not.Null);
+            provider.DeleteItemAttribute(itemId, _owner);
+            item = provider.GetItem(itemId);
+            Assert.That(item.Arguments.Count(), Is.EqualTo(0));
+          
+        }
 
+        [Test(TestOf = typeof(MemoryStorageProvider))]
+        public void DeleteItemAttributeFail()
+        {
+            var provider = new MemoryStorageProvider(_logger);
+
+            var itemId = provider.CreateItem(_owner, _ownerRef, _providerClass, _initialAttempts, _created);
+            var psEx = Assert.Throws<PSStorageException>(() => provider.DeleteItemAttribute(itemId,_owner));
+            Assert.That(psEx, Is.Not.Null);
+            Assert.That(psEx.Code, Is.EqualTo(PSStorageException.ErrorCodes.PsStorageItemArgumentNotFound));
+
+            Assert.Throws<ArgumentNullException>(() => provider.DeleteItemAttribute(itemId,string.Empty));
+            Assert.Throws<ArgumentNullException>(() => provider.DeleteItemAttribute(itemId, null!));
+           
+        }
+
+        [Test(TestOf=typeof(MemoryStorageProvider))]
+        public void AppendLogOk()
+        {
+            var provider = new MemoryStorageProvider(_logger);
+            var value = "valueXXX";
+            var code = -1;
+            ErrorLevelEnum level = ErrorLevelEnum.Error;
+            var itemId = provider.CreateItem(_owner, _ownerRef, _providerClass, _initialAttempts, _created);
+            var item = provider.GetItem(itemId);
+            Assert.That(item.Log.Count(), Is.EqualTo(0));
+
+            provider.AppendLog(itemId, value, code, level);
+            item = provider.GetItem(itemId);
+            var logItem = item.Log.FirstOrDefault(x=>x.Message == value);
+            
+            Assert.That(logItem, Is.Not.Null);
+            Assert.That(logItem.Code, Is.EqualTo(code));
+            Assert.That(logItem.Level, Is.EqualTo(level));
+        }
+
+        [Test(TestOf = typeof(MemoryStorageProvider))]
+        public void AppendLogFail()
+        {
+            var provider = new MemoryStorageProvider(_logger);
+            var itemId = provider.CreateItem(_owner, _ownerRef, _providerClass, _initialAttempts, _created);
+           
+            Assert.Throws<ArgumentNullException>(() => provider.AppendLog(itemId,string.Empty, 0,ErrorLevelEnum.Error));
+            Assert.Throws<ArgumentNullException>(() => provider.AppendLog(itemId,null!, 0,ErrorLevelEnum.Error));
+           
+        }
+
+        [Test(TestOf=typeof(MemoryStorageProvider))]
+        public void AppendStatusJournalOk()
+        {
+            var provider = new MemoryStorageProvider(_logger);
+            var value = "valueXXX";
+            PsStatusEnum status = PsStatusEnum.DoneOk;
+            var isTransient = true;
+            var itemId = provider.CreateItem(_owner, _ownerRef, _providerClass, _initialAttempts, _created);
+            var item = provider.GetItem(itemId);
+            Assert.That(item.StatusJournal.Count(), Is.EqualTo(0));
+
+            provider.AppendStatusJournal(itemId, status, isTransient, value);
+            item = provider.GetItem(itemId);
+            var journal = item.StatusJournal.FirstOrDefault(x=>x.Description == value);
+            
+            Assert.That(journal, Is.Not.Null);
+            Assert.That(journal.PreviousStatus, Is.EqualTo(status));
+            Assert.That(journal.PreviousIsStatusTransient, Is.EqualTo(isTransient));
+        }
+
+        [Test(TestOf = typeof(MemoryStorageProvider))]
+        public void AppendStatusJournalFail()
+        {
+            var provider = new MemoryStorageProvider(_logger);
+            var itemId = provider.CreateItem(_owner, _ownerRef, _providerClass, _initialAttempts, _created);
+           // no further tests needed
+        }
+
+
+        [Test(TestOf=typeof(MemoryStorageProvider))]
+        public void QueryOk()
+        {
+            var provider = new MemoryStorageProvider(_logger);
+            var status1 = PsStatusEnum.DoneOk;
+            var status2 = PsStatusEnum.DoneFailed;
+            var itemId1 = provider.CreateItem(_owner+"1", _ownerRef+"1", _providerClass, _initialAttempts, _created);
+            var itemId2 = provider.CreateItem(_owner+"2", _ownerRef+"2", _providerClass, _initialAttempts, _created);
+            var itemId3 = provider.CreateItem(_owner+"2", _ownerRef+"3", _providerClass, _initialAttempts, _created);
+
+            provider.UpdateItemStatus(itemId1, status1, true);
+            provider.UpdateItemStatus(itemId2, status2, true);
+            provider.UpdateItemStatus(itemId3, status2, false);
+
+            var result = provider.Query(_owner+"1", null).ToList();
+            Assert.That(result.Count, Is.EqualTo(1));
+            result = provider.Query(_owner+"2", null).ToList();
+            Assert.That(result.Count, Is.EqualTo(2));
+            result = provider.Query(null, _ownerRef+"3").ToList();
+            Assert.That(result.Count, Is.EqualTo(1));
+            result = provider.Query(null, null, new Tuple<bool, PsStatusEnum>(true,status1), new Tuple<bool, PsStatusEnum>(true, status2)).ToList();
+            Assert.That(result.Count, Is.EqualTo(2));
+
+
+        }
+
+        [Test(TestOf=typeof(MemoryStorageProvider))]
+        public void DurabilityTest()
+        {
+            var provider = new MemoryStorageProvider(_logger);
+            var moshpit = new MoshPit<MoshPitContext>(new MoshPitContext(provider));
+            moshpit.AddAction((ctx) =>
+            {
+                var itemId = ctx.Provider.CreateItem(ctx.HashGenerator.NewId(), ctx.HashGenerator.NewId(), ctx.HashGenerator.NewId(), 10, DateTime.Now);
+                ctx.Provider.AppendLog(itemId, "log", 0, ErrorLevelEnum.Error);
+                ctx.Provider.AppendStatusJournal(itemId, PsStatusEnum.DoneOk, true, "journal");
+                ctx.Identities.Add(itemId);
+            });
+            moshpit.AddAction((ctx) =>
+            {
+                if (ctx.Identities.Count==0)
+                    return;
+
+                var itemId = ctx.Identities.GetRandom();
+                ctx.Identities.Remove(itemId);
+                ctx.Provider.DeleteItem(itemId);
+            });
+            moshpit.AddAction((ctx) =>
+            {
+                if (ctx.Identities.Count==0)
+                    return;
+
+                var itemId = ctx.Identities.GetRandom();
+                ctx.Identities.Remove(itemId);
+                ctx.Provider.DeleteItem(itemId);
+            });
+            moshpit.AddAction((ctx) =>
+            {
+                if (ctx.Identities.Count==0)
+                    return;
+
+                var itemId = ctx.Identities.GetRandom();
+                ctx.Provider.UpdateItemStatus(itemId, PsStatusEnum.DoneOk,false);
+            });
+            moshpit.Start(100, 10000);
+            TestContext.WriteLine($"Total duration: {moshpit.TotalDuration}");
+            TestContext.WriteLine($"Total iterations: {moshpit.Iterations}");
+            TestContext.WriteLine($"AVG iteration duration: {moshpit.AvgIterationDuration}");
+            TestContext.WriteLine($"AVG iterations per second: {moshpit.AvgIterationPerSecond}");
+        }
+
+        private class MoshPitContext
+        {
+            public MemoryStorageProvider Provider { get;}
+            public List<string> Identities { get; }
+            public TinyHash HashGenerator { get; }
+
+            public MoshPitContext(MemoryStorageProvider provider)
+            {
+                Provider = provider;
+                Identities = new List<string>();
+                HashGenerator = new TinyHash(5);
+            }
+        }
     }
 }

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

@@ -1,9 +1,6 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using qdr.fnd.core.pqueue.Enums;
 using qdr.fnd.core.pqueue.Storages;
+using Quadarax.Foundation.Core.Data;
 using Quadarax.Foundation.Core.Logging;
 
 namespace qdr.fnd.core.pqueue.test.Storages.Mocks
@@ -41,6 +38,75 @@ namespace qdr.fnd.core.pqueue.test.Storages.Mocks
         {
         }
 
+        /// <inheritdoc />
+        protected override void OnUpdateItemPriority(string itemId, int priority)
+        {
+        }
+
+        /// <inheritdoc />
+        protected override void OnUpdateItemValidity(string itemId, DateTime validForm, DateTime? validTo)
+        {
+        }
+
+        /// <inheritdoc />
+        protected override void OnUpdateItemStatus(string itemId, PsStatusEnum? status, bool isTransient)
+        {
+        }
+
+        /// <inheritdoc />
+        protected override void OnUpdateItemAttempts(string itemId, int attemptsLeft)
+        {
+        }
+
+        /// <inheritdoc />
+        protected override void OnUpdateItemStarted(string itemId, DateTime? started)
+        {
+        }
+
+        /// <inheritdoc />
+        protected override void OnUpdateItemFinished(string itemId, DateTime? finished)
+        {
+        }
+
+        /// <inheritdoc />
+        protected override void OnCreateItemAttribute(string itemId, string name, string? value, string valueTypeClass, bool isOutput)
+        {
+        }
+
+        /// <inheritdoc />
+        protected override void OnUpdateItemAttribute(string itemId, string name, string value)
+        {
+            throw new NotImplementedException();
+        }
+
+        /// <inheritdoc />
+        protected override void OnDeleteItemAttribute(string itemId, string name)
+        {
+            throw new NotImplementedException();
+        }
+
+        /// <inheritdoc />
+        protected override void OnAppendLog(string itemId, string message, int code, ErrorLevelEnum messageType)
+        {
+        }
+
+        /// <inheritdoc />
+        protected override void OnAppendStatusJournal(string itemId, PsStatusEnum status, bool isTransient, string message)
+        {
+        }
+
+        /// <inheritdoc />
+        protected override IQueryable<IPsQueueItem> OnQuery()
+        {
+            return new List<IPsQueueItem>().AsQueryable();
+        }
+
+        /// <inheritdoc />
+        protected override IPsQueueItem OnGetItem(string itemId)
+        {
+            return new PsQueueItem(itemId);
+        }
+
         /// <inheritdoc />
         public override bool ContainsItem(string itemId)
         {

+ 18 - 0
qdr.fnd.core.pqueue/EnumExts.cs

@@ -0,0 +1,18 @@
+using qdr.fnd.core.pqueue.Enums;
+
+namespace qdr.fnd.core.pqueue
+{
+    public static class EnumExt
+    {
+        private static readonly Random _random = new Random();
+        public static TEnumValue GetRandom<TEnumValue>(this Enum value) where TEnumValue : Enum
+        {
+            var values = Enum.GetValues(typeof(TEnumValue));
+            var result = values.GetValue(_random.Next(values.Length));
+            if (result is null)
+                return default!;
+            return (TEnumValue)result;
+
+        }
+    }
+}

+ 4 - 0
qdr.fnd.core.pqueue/Exceptions/PSStorageException.cs

@@ -18,6 +18,10 @@ namespace qdr.fnd.core.pqueue.Exceptions
             PsStorageItemNotFound = 6000,
             [ErrorMessage("Item with id={0} already exists in storage.")]
             PsStorageItemAlreadyExists = 6001,
+            [ErrorMessage("Argument name={1} on item id={0} not found in storage.")]
+            PsStorageItemArgumentNotFound = 6002,
+            [ErrorMessage("Argument name={1} on item id={0} already exists in storage.")]
+            PsStorageItemArgumentAlreadyExists = 6003,
         }
         #endregion
 

+ 65 - 0
qdr.fnd.core.pqueue/MoshPit.cs

@@ -0,0 +1,65 @@
+namespace qdr.fnd.core.pqueue
+{
+
+    public class MoshPit<TContext> where TContext : class
+    {
+        private readonly List<Action<TContext>> _actions;
+        private Timer? _timer;
+        private readonly Random _random;
+
+
+        public TContext Context { get; set; }
+
+        public long Iterations { get; private set; }
+        public TimeSpan AvgIterationDuration { get; private set; }
+        public TimeSpan TotalDuration { get; private set; }
+        public decimal AvgIterationPerSecond { get; private set; }
+        public MoshPit(TContext context)
+        {
+            Context = context;
+            _actions = new List<Action<TContext>>();
+            _random = new Random();
+        }
+
+        public void AddAction(Action<TContext> action)
+        {
+            _actions.Add(action);
+        }
+
+        public void Start(int iterationInterval, int totalDuration)
+        {
+            _timer = new Timer(ExecuteRandomAction, Context, 0, iterationInterval);
+
+            // Stop the _timer after the specified duration
+            _ = new Timer((e) => _timer.Dispose(), null, totalDuration, Timeout.Infinite);
+
+            Thread.Sleep(totalDuration);
+        }
+
+        private void ExecuteRandomAction(object? state)
+        {
+            if (state == null)
+                throw new ArgumentNullException(nameof(state));
+
+            var context = (TContext)state;
+
+            if (_actions.Count > 0)
+            {
+                Iterations++;
+                var index = _random.Next(_actions.Count);
+                var startIteration = DateTime.Now;
+
+                _actions[index](context);
+                
+                var durationIteration = DateTime.Now - startIteration;
+                TotalDuration = TotalDuration.Add(durationIteration);
+                AvgIterationDuration = TimeSpan.FromTicks(TotalDuration.Ticks / Iterations);
+                if (AvgIterationDuration==TimeSpan.Zero)
+                    AvgIterationPerSecond = 0;
+                else
+                    AvgIterationPerSecond = TimeSpan.FromSeconds(1).Ticks / (decimal)AvgIterationDuration.Ticks;
+            }
+        }
+    }
+
+}

+ 10 - 6
qdr.fnd.core.pqueue/PsStatusHistory.cs

@@ -1,9 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using qdr.fnd.core.pqueue.Enums;
+using qdr.fnd.core.pqueue.Enums;
 
 namespace qdr.fnd.core.pqueue
 {
@@ -16,6 +11,15 @@ namespace qdr.fnd.core.pqueue
         public string? Description { get; }
         #endregion
         #region *** Constructors ***
+
+        public PsStatusHistory(PsStatusEnum previousStatus, bool previousIsStatusTransient,
+            string? description, DateTime? created = null)
+        {
+            Created = created ?? DateTime.Now;
+            PreviousStatus = previousStatus;
+            PreviousIsStatusTransient = previousIsStatusTransient;
+            Description = description;
+        }
         #endregion
     }
 }

+ 156 - 15
qdr.fnd.core.pqueue/Storages/BaseStorageProvider.cs

@@ -4,6 +4,7 @@ using Quadarax.Foundation.Core.Data;
 using Quadarax.Foundation.Core.Logging;
 using Quadarax.Foundation.Core.Object;
 using Quadarax.Foundation.Core.Value.Generators;
+using System.Xml.Linq;
 
 namespace qdr.fnd.core.pqueue.Storages
 {
@@ -49,7 +50,7 @@ namespace qdr.fnd.core.pqueue.Storages
 
             var newId = OnCreateItem(id, owner, ownerRef, providerClass, initialAttempts, created.Value, id);
 
-            _log?.Log(LogSeverityEnum.Trace, $"Item [id={id}, owner={owner}, ownerRef{ownerRef}] created");
+            _log?.Log(LogSeverityEnum.Trace, $"Item [id={id}, owner={owner}, ownerRef{ownerRef}] created.");
             return newId;
         }
 
@@ -64,6 +65,8 @@ namespace qdr.fnd.core.pqueue.Storages
                 throw new PSStorageException(PSStorageException.ErrorCodes.PsStorageItemNotFound, itemId);
 
             OnDeleteItem(itemId);
+
+            _log?.Log(LogSeverityEnum.Trace, $"Item [id={itemId}] deleted.");
         }
 
         protected abstract void OnDeleteItem(string itemId);
@@ -71,81 +74,219 @@ namespace qdr.fnd.core.pqueue.Storages
         /// <inheritdoc />
         public void UpdateItemPriority(string itemId, int priority)
         {
-            throw new NotImplementedException();
+            if (string.IsNullOrWhiteSpace(itemId))
+                throw new ArgumentNullException(nameof(itemId));
+            if (!ContainsItem(itemId))
+                throw new PSStorageException(PSStorageException.ErrorCodes.PsStorageItemNotFound, itemId);
+
+            OnUpdateItemPriority(itemId, priority);
+
+            _log?.Log(LogSeverityEnum.Trace, $"Item [id={itemId}] priority[{priority}] updated.");
         }
+        protected abstract void OnUpdateItemPriority(string itemId, int priority);
 
         /// <inheritdoc />
         public void UpdateItemValidity(string itemId, DateTime validForm, DateTime? validTo)
         {
-            throw new NotImplementedException();
+            if (string.IsNullOrWhiteSpace(itemId))
+                throw new ArgumentNullException(nameof(itemId));
+            if (!ContainsItem(itemId))
+                throw new PSStorageException(PSStorageException.ErrorCodes.PsStorageItemNotFound, itemId);
+
+            OnUpdateItemValidity(itemId, validForm, validTo);
+
+            _log?.Log(LogSeverityEnum.Trace, $"Item [id={itemId}] validFrom[{validForm}], validTo[{(validTo == null ? "NULL" : validTo.ToString())}] updated.");
         }
 
+        protected abstract void OnUpdateItemValidity(string itemId, DateTime validForm, DateTime? validTo);
+
         /// <inheritdoc />
         public void UpdateItemStatus(string itemId, PsStatusEnum? status, bool isTransient)
         {
-            throw new NotImplementedException();
+            if (string.IsNullOrWhiteSpace(itemId))
+                throw new ArgumentNullException(nameof(itemId));
+            if (!ContainsItem(itemId))
+                throw new PSStorageException(PSStorageException.ErrorCodes.PsStorageItemNotFound, itemId);
+
+            OnUpdateItemStatus(itemId, status, isTransient);
+
+            _log?.Log(LogSeverityEnum.Trace, $"Item [id={itemId}] isTransient[{isTransient}], status[{(status == null ? "NULL" : status.ToString())}] updated.");
         }
 
+        protected abstract void OnUpdateItemStatus(string itemId, PsStatusEnum? status, bool isTransient);
+
         /// <inheritdoc />
         public void UpdateItemAttempts(string itemId, int attemptsLeft)
         {
-            throw new NotImplementedException();
+            if (string.IsNullOrWhiteSpace(itemId))
+                throw new ArgumentNullException(nameof(itemId));
+            if (!ContainsItem(itemId))
+                throw new PSStorageException(PSStorageException.ErrorCodes.PsStorageItemNotFound, itemId);
+
+            OnUpdateItemAttempts(itemId, attemptsLeft);
+
+            _log?.Log(LogSeverityEnum.Trace, $"Item [id={itemId}] attemptsLeft[{attemptsLeft}] updated.");
         }
 
+        protected abstract void OnUpdateItemAttempts(string itemId, int attemptsLeft);
+
         /// <inheritdoc />
         public void UpdateItemStarted(string itemId, DateTime? started)
         {
-            throw new NotImplementedException();
+            if (string.IsNullOrWhiteSpace(itemId))
+                throw new ArgumentNullException(nameof(itemId));
+            if (!ContainsItem(itemId))
+                throw new PSStorageException(PSStorageException.ErrorCodes.PsStorageItemNotFound, itemId);
+
+            OnUpdateItemStarted(itemId, started);
+
+            _log?.Log(LogSeverityEnum.Trace, $"Item [id={itemId}] started[{(started == null ? "NULL" : started.ToString())}] updated.");
         }
 
+        protected abstract void OnUpdateItemStarted(string itemId, DateTime? started);
+
         /// <inheritdoc />
         public void UpdateItemFinished(string itemId, DateTime? finished)
         {
-            throw new NotImplementedException();
+            if (string.IsNullOrWhiteSpace(itemId))
+                throw new ArgumentNullException(nameof(itemId));
+            if (!ContainsItem(itemId))
+                throw new PSStorageException(PSStorageException.ErrorCodes.PsStorageItemNotFound, itemId);
+
+            OnUpdateItemFinished(itemId, finished);
+
+            _log?.Log(LogSeverityEnum.Trace, $"Item [id={itemId}] finished[{(finished == null ? "NULL" : finished.ToString())}] updated.");
         }
 
+        protected abstract void OnUpdateItemFinished(string itemId, DateTime? finished);
+
         /// <inheritdoc />
         public void CreateItemAttribute(string itemId, string name, string? value, string valueTypeClass, bool isOutput)
         {
-            throw new NotImplementedException();
+            if (string.IsNullOrWhiteSpace(itemId))
+                throw new ArgumentNullException(nameof(itemId));
+           
+            var item = GetItem(itemId);
+            if (item.Arguments.Any(x=>string.Equals(x.Name, name, StringComparison.CurrentCultureIgnoreCase)))
+                throw new PSStorageException(PSStorageException.ErrorCodes.PsStorageItemArgumentAlreadyExists, itemId, name);
+
+            OnCreateItemAttribute(itemId, name, value, valueTypeClass, isOutput);
+
+            _log?.Log(LogSeverityEnum.Trace, $"Item [id={itemId}] argument name[{name}], value[{value}], valueType[{valueTypeClass}] updated.");
+        
         }
 
+        protected abstract void OnCreateItemAttribute(string itemId, string name, string? value, string valueTypeClass, bool isOutput);
+
         /// <inheritdoc />
         public void UpdateItemAttribute(string itemId, string name, string value)
         {
-            throw new NotImplementedException();
+            if (string.IsNullOrWhiteSpace(itemId))
+                throw new ArgumentNullException(nameof(itemId));
+            if (string.IsNullOrWhiteSpace(name))
+                throw new ArgumentNullException(nameof(name));
+           
+            var item = GetItem(itemId);
+            if (!item.Arguments.Any(x=>string.Equals(x.Name, name, StringComparison.CurrentCultureIgnoreCase)))
+                throw new PSStorageException(PSStorageException.ErrorCodes.PsStorageItemArgumentNotFound, itemId, name);
+
+            OnUpdateItemAttribute(itemId, name, value);
+
+            _log?.Log(LogSeverityEnum.Trace, $"Item [id={itemId}] argument name[{name}], value[{value}] updated.");
+
         }
 
+        protected abstract void OnUpdateItemAttribute(string itemId, string name, string value);
+
         /// <inheritdoc />
         public void DeleteItemAttribute(string itemId, string name)
         {
-            throw new NotImplementedException();
+            if (string.IsNullOrWhiteSpace(itemId))
+                throw new ArgumentNullException(nameof(itemId));
+            if (string.IsNullOrWhiteSpace(name))
+                throw new ArgumentNullException(nameof(name));
+           
+            var item = GetItem(itemId);
+            if (!item.Arguments.Any(x=>string.Equals(x.Name, name, StringComparison.CurrentCultureIgnoreCase)))
+                throw new PSStorageException(PSStorageException.ErrorCodes.PsStorageItemArgumentNotFound, itemId, name);
+
+            OnDeleteItemAttribute(itemId, name);
+
+            _log?.Log(LogSeverityEnum.Trace, $"Item [id={itemId}] argument name[{name}] deleted.");
+
         }
 
+
+        protected abstract void OnDeleteItemAttribute(string itemId, string name);
+
         /// <inheritdoc />
-        public void AppendLog(string transactionId, string itemId, string message, int code, ErrorLevelEnum messageType)
+        public void AppendLog(string itemId, string message, int code, ErrorLevelEnum messageType)
         {
-            throw new NotImplementedException();
+            if (string.IsNullOrWhiteSpace(itemId))
+                throw new ArgumentNullException(nameof(itemId));
+            if (string.IsNullOrWhiteSpace(message))
+                throw new ArgumentNullException(nameof(message));
+           
+            var item = GetItem(itemId);
+            
+            OnAppendLog(itemId, message, code, messageType);
+
+            _log?.Log(LogSeverityEnum.Trace, $"Item [id={itemId}] log message[{message}], code[{code}], messageType[{messageType}] appended.");
+
         }
 
+        protected abstract void OnAppendLog(string itemId, string message, int code, ErrorLevelEnum messageType);
+
         /// <inheritdoc />
         public void AppendStatusJournal(string itemId, PsStatusEnum status, bool isTransient, string message)
         {
-            throw new NotImplementedException();
+            if (string.IsNullOrWhiteSpace(itemId))
+                throw new ArgumentNullException(nameof(itemId));
+           
+            var item = GetItem(itemId);
+            
+            OnAppendStatusJournal(itemId, status, isTransient, message);
+
+            _log?.Log(LogSeverityEnum.Trace, $"Item [id={itemId}] log message[{message}], status[{status}], isTransient[{isTransient}] appended.");
+
         }
 
+        protected abstract void OnAppendStatusJournal(string itemId, PsStatusEnum status, bool isTransient, string message);
+
         /// <inheritdoc />
         public IQueryable<IPsQueueItem> Query(string? owner, string? ownerRef, params Tuple<bool, PsStatusEnum>[] status)
         {
-            throw new NotImplementedException();
+            var query = OnQuery();
+            if (status.Length>0)
+                query = query.Where(x => status.Any(s => s.Item1 == x.IsStatusTransient && s.Item2 == x.Status));
+            if (!string.IsNullOrWhiteSpace(owner))
+                query = query.Where(x => string.Equals(x.Owner, owner, StringComparison.InvariantCulture));
+            if (!string.IsNullOrWhiteSpace(ownerRef))
+                query = query.Where(x => string.Equals(x.OwnerRef, ownerRef, StringComparison.InvariantCulture));
+
+            owner = owner ?? "NULL";
+            ownerRef = ownerRef ?? "NULL";
+            var statuses = string.Join(",", status.Select(x => $"[IsTransient:{x.Item1},Status:{x.Item2}]"));
+            _log?.Log(LogSeverityEnum.Trace, $"Query [owner={owner}], ownerRef[{ownerRef}], statuses[{statuses}] executed.");
+
+            return query;
         }
 
+        protected abstract IQueryable<IPsQueueItem> OnQuery();
+
         /// <inheritdoc />
         public IPsQueueItem GetItem(string itemId)
         {
-            throw new NotImplementedException();
+            if (string.IsNullOrWhiteSpace(itemId))
+                throw new ArgumentNullException(nameof(itemId));
+            if (!ContainsItem(itemId))
+                throw new PSStorageException(PSStorageException.ErrorCodes.PsStorageItemNotFound, itemId);
+
+            return OnGetItem(itemId);
         }
 
+        protected abstract IPsQueueItem OnGetItem(string itemId);
+
         /// <inheritdoc />
         public abstract bool ContainsItem(string itemId);
 

+ 1 - 2
qdr.fnd.core.pqueue/Storages/IPsQueueStorage.cs

@@ -151,12 +151,11 @@ namespace qdr.fnd.core.pqueue.Storages
         /// If <paramref name="itemId"/> not exists, the method should throw an exception.
         /// </remarks>
         /// </summary>
-        /// <param name="transactionId">Transaction identifier generated by <see cref="CreateTransaction"/> operation.</param>
         /// <param name="itemId">Item identifier.</param>
         /// <param name="message">Log message.</param>
         /// <param name="code">Message code</param>
         /// <param name="messageType">Message type</param>
-        public void AppendLog(string transactionId, string itemId, string message, int code, ErrorLevelEnum messageType);
+        public void AppendLog(string itemId, string message, int code, ErrorLevelEnum messageType);
         /// <summary>
         /// Appends a new status journal record to the item specified by the <paramref name="itemId"/>.
         /// <remarks>

+ 138 - 7
qdr.fnd.core.pqueue/Storages/MemoryStorageProvider.cs

@@ -1,9 +1,7 @@
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+using System.Collections.Concurrent;
+using qdr.fnd.core.pqueue.Enums;
+using qdr.fnd.core.pqueue.Exceptions;
+using Quadarax.Foundation.Core.Data;
 using Quadarax.Foundation.Core.Logging;
 
 namespace qdr.fnd.core.pqueue.Storages
@@ -51,10 +49,143 @@ namespace qdr.fnd.core.pqueue.Storages
         /// <inheritdoc />
         protected override void OnDeleteItem(string itemId)
         {
-            if(_items.TryRemove(itemId, out _))
+            if(!_items.TryRemove(itemId, out _))
                 Log?.Log(LogSeverityEnum.Warn, $"Item id={itemId} wasn't delete from storage (not exists)");
         }
 
+        /// <inheritdoc />
+        protected override void OnUpdateItemPriority(string itemId, int priority)
+        {
+            var item = (PsQueueItem)GetItem(itemId);
+            if (item == null)
+                throw new PSStorageException(PSStorageException.ErrorCodes.PsStorageItemNotFound, itemId);
+            item.Priority = priority;
+        }
+
+        /// <inheritdoc />
+        protected override void OnUpdateItemValidity(string itemId, DateTime validForm, DateTime? validTo)
+        {
+            var item = (PsQueueItem)GetItem(itemId);
+            if (item == null)
+                throw new PSStorageException(PSStorageException.ErrorCodes.PsStorageItemNotFound, itemId);
+            item.ValidFrom = validForm;
+            item.ValidTo = validTo;
+        }
+
+        /// <inheritdoc />
+        protected override void OnUpdateItemStatus(string itemId, PsStatusEnum? status, bool isTransient)
+        {
+            var item = (PsQueueItem)GetItem(itemId);
+            if (item == null)
+                throw new PSStorageException(PSStorageException.ErrorCodes.PsStorageItemNotFound, itemId);
+            if (status!= null)
+                item.Status = status.Value;
+            item.IsStatusTransient = isTransient;
+        }
+
+        /// <inheritdoc />
+        protected override void OnUpdateItemAttempts(string itemId, int attemptsLeft)
+        {
+            var item = (PsQueueItem)GetItem(itemId);
+            if (item == null)
+                throw new PSStorageException(PSStorageException.ErrorCodes.PsStorageItemNotFound, itemId);
+            
+            item.AttemptsLeft = attemptsLeft;
+        }
+
+        /// <inheritdoc />
+        protected override void OnUpdateItemStarted(string itemId, DateTime? started)
+        {
+            var item = (PsQueueItem)GetItem(itemId);
+            if (item == null)
+                throw new PSStorageException(PSStorageException.ErrorCodes.PsStorageItemNotFound, itemId);
+            
+            item.Started = started;
+        }
+
+        /// <inheritdoc />
+        protected override void OnUpdateItemFinished(string itemId, DateTime? finished)
+        {
+            var item = (PsQueueItem)GetItem(itemId);
+            if (item == null)
+                throw new PSStorageException(PSStorageException.ErrorCodes.PsStorageItemNotFound, itemId);
+            
+            item.Finished = finished;
+        }
+
+        /// <inheritdoc />
+        protected override void OnCreateItemAttribute(string itemId, string name, string? value, string valueTypeClass, bool isOutput)
+        {
+            var item = (PsQueueItem)GetItem(itemId);
+            if (item == null)
+                throw new PSStorageException(PSStorageException.ErrorCodes.PsStorageItemNotFound, itemId);
+            var type = Type.GetType(valueTypeClass);
+
+            ((List<ITypedArgument>)item.Arguments).Add(new TypedArgument(name, value, type,isOutput));
+        }
+
+        /// <inheritdoc />
+        protected override void OnUpdateItemAttribute(string itemId, string name, string value)
+        {
+            var item = (PsQueueItem)GetItem(itemId);
+            if (item == null)
+                throw new PSStorageException(PSStorageException.ErrorCodes.PsStorageItemNotFound, itemId);
+            
+            var attr = item.Arguments.FirstOrDefault(a => string.Equals(a.Name , name,StringComparison.CurrentCultureIgnoreCase));
+            if(attr== null)
+                throw new PSStorageException(PSStorageException.ErrorCodes.PsStorageItemArgumentNotFound, itemId, name);
+            ((TypedArgument)attr).Value = value; 
+            
+        }
+
+        /// <inheritdoc />
+        protected override void OnDeleteItemAttribute(string itemId, string name)
+        {
+            var item = (PsQueueItem)GetItem(itemId);
+            if (item == null)
+                throw new PSStorageException(PSStorageException.ErrorCodes.PsStorageItemNotFound, itemId);
+            
+            var attr = item.Arguments.FirstOrDefault(a => string.Equals(a.Name , name,StringComparison.CurrentCultureIgnoreCase));
+            if(attr== null)
+                throw new PSStorageException(PSStorageException.ErrorCodes.PsStorageItemArgumentNotFound, itemId, name);
+            ((List<ITypedArgument>)item.Arguments).Remove(attr);
+        }
+
+        /// <inheritdoc />
+        protected override void OnAppendLog(string itemId, string message, int code, ErrorLevelEnum messageType)
+        {
+            var item = (PsQueueItem)GetItem(itemId);
+            if (item == null)
+                throw new PSStorageException(PSStorageException.ErrorCodes.PsStorageItemNotFound, itemId);
+
+            ((List<IError>)item.Log).Add(new Error(message, code, messageType, DateTime.Now));
+        }
+
+        /// <inheritdoc />
+        protected override void OnAppendStatusJournal(string itemId, PsStatusEnum status, bool isTransient, string message)
+        {
+            var item = (PsQueueItem)GetItem(itemId);
+            if (item == null)
+                throw new PSStorageException(PSStorageException.ErrorCodes.PsStorageItemNotFound, itemId);
+
+            ((List<PsStatusHistory>)item.StatusJournal).Add(new PsStatusHistory(status, isTransient,message));
+        }
+
+        /// <inheritdoc />
+        protected override IQueryable<IPsQueueItem> OnQuery()
+        {
+            return _items.Values.AsQueryable();
+        }
+
+        /// <inheritdoc />
+        protected override IPsQueueItem OnGetItem(string itemId)
+        {
+            _items.TryGetValue(itemId,out var item);
+            if (item== null)
+                throw new PSStorageException(PSStorageException.ErrorCodes.PsStorageItemNotFound, itemId);
+            return item;
+        }
+
         /// <inheritdoc />
         public override bool ContainsItem(string itemId)
         {