Beispiel #1
0
        public void ReleaseUnheldLock()
        {
            var redisTaskFunnel = CreateRedisTaskFunnel();
            var msgValue        = Guid.NewGuid().ToByteArray();
            var pipeInfo        = PipeInfo.Create("unheld", "a");

            redisTaskFunnel.DestroyChildPipe(pipeInfo);
            var redisPipeValue = new RedisPipeValue(pipeInfo, msgValue, "asdf", true);

            //indicating a success does nothing if the hash doesn't exist
            redisTaskFunnel.AfterExecute(redisPipeValue, true);
            var readMessage = redisTaskFunnel.TryReadMessageBatch(false, pipeInfo, TimeSpan.FromMinutes(1), 1);

            readMessage.RedisValues.Should().BeEmpty();

            //indicating a failure resubmits the message
            redisTaskFunnel.AfterExecute(redisPipeValue, false);
            readMessage = redisTaskFunnel.TryReadMessageBatch(false, pipeInfo, TimeSpan.FromMinutes(1), 1);
            readMessage.Should().NotBeNull();
            var mesg = readMessage.RedisPipeValues.FirstOrDefault();

            mesg?.Value.Should().BeEquivalentTo(msgValue);
            redisTaskFunnel.DestroyChildPipe(pipeInfo);
            redisTaskFunnel.AfterExecuteBatch(readMessage);
        }
Beispiel #2
0
        public void AfterExecute(RedisPipeValue value, bool success)
        {
            var db = _redis.GetDatabase();

            if (!success)
            {
                //this is a Nack
                //whether we peeked it or not, just push it back where it was
                db.ListLeftPush(value.PipeInfo.PipePath, value.RedisValue);
            }
            else
            {
                if (value.Peaked)
                {
                    //when we peeked it, we moved the record to a 'holding list'
                    //whether the invocation failed or succeeded we don't remove it from that list to minimize load on redis.
                    //This means that if the application crashes before the batch is destroyed the batch will be resubmitted
                    //So that makes the chance that this message will be re-executed twice: once from the re-push above
                    //and once from the batch re-submission

                    //later we can add a release strategy to do this: db.ListRemove(value.BatchHoldingList, value.RedisValue, 1);
                    //or perhaps we can use the NThen redis data that tracks individual messages
                }
                else
                {
                    //when we originally read the message we just removed it from the list, so we definitely dont need to do anything
                }
            }
        }
        private static void SendReadAndRelease(IRedisTaskFunnel redisTaskFunnel, string parentPipeName, string childPipeName)
        {
            var sent = redisTaskFunnel.TrySendMessage(parentPipeName, childPipeName, new byte[1] {
                (byte)'a'
            }, Int32.MaxValue,
                                                      TimeSpan.FromMinutes(1));

            sent.sent.Should().BeTrue();
            sent.clients.Should().BeFalse();

            var read = redisTaskFunnel.TryReadMessage <byte[]>(true, parentPipeName, childPipeName, TimeSpan.FromSeconds(1));

            read.Should().NotBeNull();
            read.LockValue.Should().NotBeNull();
            read.Value.Should().NotBeNull();

            //try to release the lock without the correct key
            var redisPipeValue = new RedisPipeValue <byte[]>(PipeInfo.Create(parentPipeName, childPipeName), "", Guid.NewGuid().ToString(), true);
            var badExtend      = redisTaskFunnel.LockExtend(redisPipeValue, TimeSpan.FromSeconds(1));

            badExtend.Should().BeFalse();
            Action badRelease = () => redisTaskFunnel.LockRelease(redisPipeValue, true);

            badRelease.Should().Throw <ApplicationException>();

            var extended = redisTaskFunnel.LockExtend(read, TimeSpan.FromSeconds(1));

            extended.Should().BeTrue();

            var released = redisTaskFunnel.LockRelease(read, true);

            released.Should().BeTrue();
        }
        public void ReleaseLockExtend()
        {
            var redisTaskFunnel = CreateRedisTaskFunnel();
            var lockKey         = Guid.NewGuid().ToString();
            var redisPipeValue  = new RedisPipeValue <byte[]>(PipeInfo.Create("lock", "a"), lockKey, "asdf", true);
            var extended        = redisTaskFunnel.LockExtend(redisPipeValue, TimeSpan.FromMinutes(1));

            extended.Should().BeFalse();
        }
        public void ReleaseUnheldLock()
        {
            var redisTaskFunnel = CreateRedisTaskFunnel();
            var lockKey         = Guid.NewGuid().ToString();
            var redisPipeValue  = new RedisPipeValue <byte[]>(PipeInfo.Create("unheld", "a"), lockKey, "asdf", true);

            Action act = () => redisTaskFunnel.LockRelease(redisPipeValue, true);

            act.Should().Throw <ApplicationException>();
        }
Beispiel #6
0
        public void ReleaseLockExtend()
        {
            var redisTaskFunnel = CreateRedisTaskFunnel();
            var lockKey         = Guid.NewGuid().ToString();
            var pipeInfo        = PipeInfo.Create("lock", "a");
            var redisPipeValue  = new RedisPipeValue(pipeInfo, lockKey, "asdf", true);
            var extended        = redisTaskFunnel.RetainHoldingList(redisPipeValue, TimeSpan.FromMinutes(1));

            extended.Should().BeFalse();
            redisTaskFunnel.DestroyChildPipe(pipeInfo);
        }
Beispiel #7
0
        private static void SendReadAndRelease(IRedisTaskFunnel redisTaskFunnel, string parentPipeName, string childPipeName)
        {
            //send a message
            var messageBody = "body";
            var sent        = redisTaskFunnel.TrySendMessage(parentPipeName, childPipeName, messageBody, Int32.MaxValue,
                                                             TimeSpan.FromMinutes(1));

            sent.sent.Should().BeTrue();
            //sent.clients.Should().BeFalse();

            //read the batch
            var read = redisTaskFunnel.TryReadMessageBatch(true, PipeInfo.Create(parentPipeName, childPipeName), TimeSpan.FromSeconds(1), 1);

            read.Should().NotBeNull();
            read.HoldingList.Should().NotBeNull();
            read.RedisValues.Should().NotBeEmpty();
            read.RedisValues.First().HasValue.Should().BeTrue();
            var actualRedisPipeValue = read.RedisPipeValues.First();

            actualRedisPipeValue.ValueString.Should().Be(messageBody);

            //try to release the lock without the wrong holdingListName
            var redisPipeValue = new RedisPipeValue(PipeInfo.Create(parentPipeName, childPipeName), "body", Guid.NewGuid().ToString(), true);
            var badExtend      = redisTaskFunnel.RetainHoldingList(redisPipeValue, TimeSpan.FromSeconds(1));

            badExtend.Should().BeFalse();
            redisTaskFunnel.AfterExecute(redisPipeValue, true);

            //retain with the correct name
            var extended = redisTaskFunnel.RetainHoldingList(read, TimeSpan.FromSeconds(1));

            extended.Should().BeTrue();

            //complete the message and the batch
            redisTaskFunnel.AfterExecute(actualRedisPipeValue, true);
            redisTaskFunnel.AfterExecuteBatch(read);

            //now check the holding list doesn't exist any more.
            extended = redisTaskFunnel.RetainHoldingList(read, TimeSpan.FromSeconds(1));
            extended.Should().BeFalse();
        }
Beispiel #8
0
 public bool RetainHoldingList(RedisPipeValue value, TimeSpan lockExpiry)
 {
     return(RetainHoldingList(value.BatchHoldingList, lockExpiry));
 }
Beispiel #9
0
 public Task ExecuteAsync(PipeInfo pipeInfo, RedisPipeValue value)
 {
     Execute(pipeInfo, value);
     return(Task.CompletedTask);
 }
Beispiel #10
0
        public void Execute(PipeInfo pipeInfo, RedisPipeValue value)
        {
            var valueAsString = value.ValueString;

            System.Diagnostics.Debug.WriteLine($"{pipeInfo.ParentPipeName}/{pipeInfo.ChildPipeName} : {valueAsString}");
        }