public void GetNextChunk()
    {
        var startSlice   = new DateTime(2000, 1, 1, 1, 1, 1, DateTimeKind.Utc);
        var timeout1Time = startSlice.AddSeconds(1);
        var timeout2Time = goodUtcNowValue.AddSeconds(10);
        var timeout1     = new TimeoutData
        {
            Destination = "theDestination",
            State       = new byte[] { 1 },
            Time        = timeout1Time,
            Headers     = new Dictionary <string, string>()
        };
        var timeout2 = new TimeoutData
        {
            Destination = "theDestination",
            State       = new byte[] { 1 },
            Time        = timeout2Time,
            Headers     = new Dictionary <string, string>()
        };
        var persister = Setup(schema);

        persister.Add(timeout1, null).Await();
        persister.Add(timeout2, null).Await();
        var nextChunk = persister.GetNextChunk(startSlice).Result;

        Assert.That(nextChunk.NextTimeToQuery, Is.EqualTo(timeout2Time).Within(TimeSpan.FromSeconds(1)));
        Assert.IsNotNull(nextChunk);
        Assert.AreEqual(DateTimeKind.Utc, nextChunk.NextTimeToQuery.Kind);
#if NET452
        ObjectApprover.VerifyWithJson(nextChunk, s => s.Replace(timeout1.Id, "theId"));
#endif
    }
        public bool TryRemove(string timeoutId, out TimeoutData timeoutData)
        {
            try
            {
                readerWriterLock.EnterWriteLock();

                for (var index = 0; index < storage.Count; index++)
                {
                    var data = storage[index];
                    if (data.Id == timeoutId)
                    {
                        timeoutData = data;
                        storage.RemoveAt(index);
                        return true;
                    }
                }

                timeoutData = null;
                return false;
            }
            finally
            {
                readerWriterLock.ExitWriteLock();
            }
        }
        public void Add(TimeoutData timeout)
        {
            var timeoutId = Guid.Empty;

            string messageId;

            if (timeout.Headers != null && timeout.Headers.TryGetValue(Headers.MessageId, out messageId))
            {
                Guid.TryParse(messageId, out timeoutId);
            }

            if (timeoutId == Guid.Empty)
            {
                timeoutId = CombGuidGenerator.Instance.NewCombGuid(Guid.NewGuid(), DateTime.UtcNow);
            }

            _collection.InsertOne(new TimeoutEntity
            {
                Id                   = timeoutId.ToString(),
                Destination          = timeout.Destination,
                SagaId               = timeout.SagaId,
                State                = timeout.State,
                Time                 = timeout.Time,
                Headers              = timeout.Headers,
                Endpoint             = timeout.OwningTimeoutManager,
                OwningTimeoutManager = timeout.OwningTimeoutManager
            });
        }
예제 #4
0
        public void Add(TimeoutData timeoutData)
        {
            try
            {
                timeoutData.Id = Guid.NewGuid().ToString();
                Logger.DebugFormat("Add timeoutData {0}", timeoutData.Id);
                var timeoutEntity = new TimeoutEntity
                {
                    Id          = timeoutData.Id,
                    Destination = timeoutData.Destination != null?timeoutData.Destination.ToString() : null,
                                      SagaId               = timeoutData.SagaId,
                                      State                = timeoutData.State,
                                      Time                 = timeoutData.Time,
                                      TimeString           = timeoutData.Time.ToString("O"),
                                      Headers              = timeoutData.Headers,
                                      CorrelationId        = timeoutData.CorrelationId,
                                      OwningTimeoutManager = timeoutData.OwningTimeoutManager
                };

                using (var redisClient = RedisClientsManager.GetClient())
                {
                    redisClient.As <TimeoutEntity>().AddItemToSortedSet(redisClient.As <TimeoutEntity>().SortedSets[EndpointName], timeoutEntity, timeoutEntity.Time.ToUnixTimeSeconds());
                    Logger.InfoFormat("Added timeoutEntity {0} with score {1} to sorted set {2}", timeoutEntity.Id, timeoutEntity.Time.ToUnixTimeSeconds(), redisClient.As <TimeoutEntity>().SortedSets[EndpointName].ToUrn());
                }
            }
            catch (Exception e)
            {
                Logger.Error(string.Format("ERROR Add {0}", timeoutData), e);
                throw;
            }
        }
예제 #5
0
        public void Add(TimeoutData timeout)
        {
            Logger.Debug("Adding timeout");

            if (timeout == null)
            {
                Logger.Debug("Timeout is null! Throwing");
                throw new ArgumentNullException("timeout");
            }

            Guid timeoutId = CombGuid.NewGuid();
            Logger.DebugFormat("Created new comb guid for timeout ID {0}", timeoutId);
            TimeoutDataEntity timeoutEntity = new TimeoutDataEntity
            {
                Destination = timeout.Destination.ToString(),
                Endpoint = timeout.OwningTimeoutManager,
                Headers = timeout.Headers.ToDictionaryString(),
                Id = timeoutId,
                SagaId = timeout.SagaId,
                State = timeout.State,
                Time = timeout.Time
            };

            using (ITimeoutDbContext dbc = _dbContextFactory.CreateTimeoutDbContext())
            {
                Logger.Debug("Saving timeout entity");
                dbc.Timeouts.Add(timeoutEntity);
                dbc.SaveChanges();
            }
        }
        public void Add(TimeoutData timeout)
        {
            timeout.Id = Guid.NewGuid().ToString("N");

            int score = ScoreDateTime(timeout.Time);

            if (_log.IsDebugEnabled)
            {
                _log.Debug("Adding timeout with ID " + timeout.Id + " " + timeout.Time.ToString() + " " + score);
            }

            using (var client = GetClient())
            {
                var nativeClient = client as RedisNativeClient;
                using (var tran = client.CreateTransaction())
                {
                    tran.QueueCommand(c => c.Lists[GetTimeoutIdsListName()].Add(timeout.Id));
                    tran.QueueCommand(c => c.Hashes[GetTimeoutDataHashName()].AddIfNotExists(new KeyValuePair <string, string>(timeout.Id, Serialize(timeout))));
                    tran.QueueCommand(c => ((RedisNativeClient)c).ZAdd(GetTimeoutTimesSortedSetName(), score, Encoding.UTF8.GetBytes(timeout.Id)));
                    if (timeout.SagaId != Guid.Empty)
                    {
                        tran.QueueCommand(c => c.Hashes[GetSagaIdMapHashName()].AddIfNotExists(new KeyValuePair <string, string>(timeout.SagaId.ToString("N"), timeout.Id)));
                    }
                    tran.Commit();
                }
            }
        }
예제 #7
0
        static TransportMessage MapToTransportMessage(TimeoutData timeoutData)
        {
            var transportMessage = new TransportMessage
            {
                ReplyToAddress = Address.Local,
                Headers        = new Dictionary <string, string>(),
                Recoverable    = true,
                MessageIntent  = MessageIntentEnum.Send,
                CorrelationId  = timeoutData.CorrelationId,
                Body           = timeoutData.State
            };

            if (timeoutData.Headers != null)
            {
                transportMessage.Headers = timeoutData.Headers;
            }
            else
            {
                //we do this to be backwards compatible, this can be removed when going to 3.1.X
                transportMessage.Headers[Headers.Expire] = timeoutData.Time.ToWireFormattedString();

                if (timeoutData.SagaId != Guid.Empty)
                {
                    transportMessage.Headers[Headers.SagaId] = timeoutData.SagaId.ToString();
                }
            }

            return(transportMessage);
        }
        public bool TryRemove(string timeoutId, out TimeoutData timeoutData)
        {
            using (var client = GetClient())
            {
                var timeoutString = client.Hashes[GetTimeoutDataHashName()][timeoutId];

                if (timeoutString != null)
                {
                    var timeout = Deserialize(timeoutString);
                    timeoutData = timeout;

                    using (var tran = client.CreateTransaction())
                    {
                        tran.QueueCommand(c => c.Lists[GetTimeoutIdsListName()].Remove(timeoutId));
                        tran.QueueCommand(c => c.Hashes[GetTimeoutDataHashName()].Remove(timeoutId));
                        tran.QueueCommand(c => c.SortedSets[GetTimeoutTimesSortedSetName()].Remove(timeoutId));
                        tran.QueueCommand(c => c.Hashes[GetSagaIdMapHashName()].Remove(timeout.SagaId.ToString("N")));
                        tran.Commit();
                    }

                    return(true);
                }
                else
                {
                    timeoutData = null;
                    return(false);
                }
            }
        }
예제 #9
0
        public void Should_remove_timeouts_by_id()
        {
            var t1 = new TimeoutData();

            persister.Add(t1);

            var t2 = new TimeoutData();

            persister.Add(t2);

            var t = persister.GetAll();

            foreach (var timeoutData in t)
            {
                using (var tx = new TransactionScope())
                {
                    //other tx stuff like pop a message from MSMQ

                    persister.Remove(timeoutData);

                    tx.Complete();
                }
            }

            using (var session = store.OpenSession())
            {
                session.Advanced.AllowNonAuthoritativeInformation = false;

                Assert.Null(session.Load<TimeoutData>(t1.Id));
                Assert.Null(session.Load<TimeoutData>(t2.Id));
            }
        }
    public void GetNextChunk_CleanupOnce()
    {
        var startSlice   = new DateTime(2000, 1, 1, 1, 1, 1, DateTimeKind.Utc);
        var timeout1Time = startSlice.AddYears(-10);
        var timeout1     = new TimeoutData
        {
            Destination = "theDestination",
            State       = new byte[] { 1 },
            Time        = timeout1Time,
            Headers     = new Dictionary <string, string>()
        };
        var persister = Setup(schema, TimeSpan.FromMinutes(2));

        persister.Add(timeout1, null).Await();

        //Call once triggering clean-up mode
        persister.GetNextChunk(startSlice).GetAwaiter().GetResult();

        //Call again to check if clean-up mode is now disabled -- expect no results
        var nextChunk = persister.GetNextChunk(startSlice).Result;

        Assert.IsNotNull(nextChunk);
#if NET452
        ObjectApprover.VerifyWithJson(nextChunk, s => s.Replace(timeout1.Id, "theId"));
#endif
    }
        public void Should_remove_timeouts_by_id()
        {
            var t1 = new TimeoutData {
                Time = DateTime.Now.AddYears(1), OwningTimeoutManager = Configure.EndpointName, Headers = new Dictionary <string, string> {
                    { "Header1", "Value1" }
                }
            };
            var t2 = new TimeoutData {
                Time = DateTime.Now.AddYears(1), OwningTimeoutManager = Configure.EndpointName, Headers = new Dictionary <string, string> {
                    { "Header1", "Value1" }
                }
            };

            persister.Add(t1);
            persister.Add(t2);

            var t = persister.GetAll();

            foreach (var timeoutData in t)
            {
                persister.Remove(timeoutData.Id);
            }

            using (var session = sessionFactory.OpenSession())
            {
                Assert.Null(session.Get <TimeoutEntity>(new Guid(t1.Id)));
                Assert.Null(session.Get <TimeoutEntity>(new Guid(t2.Id)));
            }
        }
        public async Task <InitiTimeoutsResult> InitTimeouts(int nrOfTimeouts, string endpointName, int startFromId)
        {
            var timeoutsPrefix  = "TimeoutDatas";
            var shortestTimeout = DateTime.MaxValue;
            var longestTimeout  = DateTime.MinValue;
            var daysToTrigger   = random.Next(2, 60); // randomize the Time property

            var commands      = new List <object>();
            var bulkInsertUrl = $"{ServerName}/databases/{DatabaseName}/bulk_docs";

            for (var i = 0; i < nrOfTimeouts; i++)
            {
                // Insert the timeout data
                var timeoutData = new TimeoutData
                {
                    Destination          = "WeDontCare.ThisShouldBeIgnored.BecauseItsJustForRouting",
                    SagaId               = Guid.NewGuid(),
                    OwningTimeoutManager = endpointName,
                    Time    = DateTime.Now.AddDays(daysToTrigger),
                    Headers = new Dictionary <string, string>(),
                    State   = Encoding.ASCII.GetBytes("This is my state")
                };

                commands.Add(new PutCommand
                {
                    Document     = timeoutData,
                    ChangeVector = null,
                    Type         = "PUT",
                    Id           = $"{timeoutsPrefix}/{startFromId + i}"
                });

                if (shortestTimeout > timeoutData.Time)
                {
                    shortestTimeout = timeoutData.Time;
                }

                if (longestTimeout < timeoutData.Time)
                {
                    longestTimeout = timeoutData.Time;
                }
            }

            var request = new
            {
                Commands = commands.ToArray()
            };

            var serializeObject = JsonConvert.SerializeObject(request);

            using var stringContent = new StringContent(serializeObject, Encoding.UTF8, "application/json");
            using var result        = await HttpClient.PostAsync(bulkInsertUrl, stringContent);

            Assert.That(result.StatusCode, Is.EqualTo(HttpStatusCode.Created));

            return(new InitiTimeoutsResult
            {
                ShortestTimeout = shortestTimeout,
                LongestTimeout = longestTimeout
            });
        }
        public async Task InitTimeouts(int nrOfTimeouts)
        {
            var commands       = new List <object>();
            var bulkInsertUrl  = $"{ServerName}/databases/{DatabaseName}/bulk_docs";
            var timeoutsPrefix = "TimeoutDatas";

            for (var i = 0; i < nrOfTimeouts; i++)
            {
                // Insert the timeout data
                var timeoutData = new TimeoutData
                {
                    Destination          = "WeDontCare.ThisShouldBeIgnored.BecauseItsJustForRouting",
                    SagaId               = Guid.NewGuid(),
                    OwningTimeoutManager = "A",
                    Time    = i < nrOfTimeouts / 2 ? DateTime.Now.AddDays(7) : DateTime.Now.AddDays(14),
                    Headers = new Dictionary <string, string>(),
                    State   = Encoding.ASCII.GetBytes("This is my state")
                };

                commands.Add(new
                {
                    Document = timeoutData,
                    Method   = "PUT",
                    Key      = $"{timeoutsPrefix}/{i}",
                    Metadata = new object()
                });
            }

            var serializeObject = JsonConvert.SerializeObject(commands);

            using var stringContent = new StringContent(serializeObject, Encoding.UTF8, "application/json");
            using var result        = await HttpClient.PostAsync(bulkInsertUrl, stringContent);

            Assert.That(result.StatusCode, Is.EqualTo(HttpStatusCode.OK));
        }
        public void Should_set_the_next_run()
        {
            const int numberOfTimeoutsToAdd = 50;

            for (var i = 0; i < numberOfTimeoutsToAdd; i++)
            {
                var d = new TimeoutData
                {
                    Time = DateTime.UtcNow.AddHours(-1),
                    OwningTimeoutManager = Configure.EndpointName
                };

                persister.Add(d);
            }

            var expected = DateTime.UtcNow.AddHours(1);
            persister.Add(new TimeoutData
            {
                Time = expected,
                OwningTimeoutManager = String.Empty,
            });

            DateTime nextTimeToRunQuery;
            persister.GetNextChunk(DateTime.UtcNow.AddYears(-3), out nextTimeToRunQuery);

            var totalMilliseconds = (expected - nextTimeToRunQuery).Duration().TotalMilliseconds;

            Assert.True(totalMilliseconds < 200);
        }
        public void Should_only_return_timeouts_for_this_specific_endpoint_and_any_ones_without_a_owner()
        {
            const int numberOfTimeoutsToAdd = 3;

            for (var i = 0; i < numberOfTimeoutsToAdd; i++)
            {
                var d = new TimeoutData
                {
                    Time = DateTime.UtcNow.AddHours(-1),
                    OwningTimeoutManager = Configure.EndpointName
                };

                persister.Add(d);
            }

            persister.Add(new TimeoutData
            {
                Time = DateTime.UtcNow.AddHours(-1),
                OwningTimeoutManager = "MyOtherTM"
            });

            persister.Add(new TimeoutData
            {
                Time = DateTime.UtcNow.AddHours(-1),
                OwningTimeoutManager = String.Empty,
            });

            Assert.AreEqual(numberOfTimeoutsToAdd + 1, GetNextChunk().Count);
        }
예제 #16
0
        public void Should_remove_timeouts_by_id()
        {
            var t1 = new TimeoutData();

            persister.Add(t1);

            var t2 = new TimeoutData();

            persister.Add(t2);

            var t = persister.GetAll();

            foreach (var timeoutData in t)
            {
                using (var tx = new TransactionScope())
                {
                    //other tx stuff like pop a message from MSMQ

                    persister.Remove(timeoutData.Id);

                    tx.Complete();
                }
            }

            using (var session = store.OpenSession())
            {
                session.Advanced.AllowNonAuthoritativeInformation = false;

                Assert.Null(session.Load <TimeoutData>(t1.Id));
                Assert.Null(session.Load <TimeoutData>(t2.Id));
            }
        }
        bool TryRemoveTimeoutEntity(Guid timeoutId, IDbConnection connection, out TimeoutData timeoutData)
        {
            bool found;

            using (var session = SessionFactory.OpenStatelessSessionEx(connection))
            {
                using (var tx = session.BeginAmbientTransactionAware(IsolationLevel.ReadCommitted))
                {
                    var te = session.Get <TimeoutEntity>(timeoutId);
                    timeoutData = MapToTimeoutData(te);

                    if (timeoutData == null)
                    {
                        tx.Commit();
                        return(false);
                    }

                    var queryString = string.Format("delete {0} where Id = :id", typeof(TimeoutEntity));

                    found = session.CreateQuery(queryString)
                            .SetParameter("id", timeoutId)
                            .ExecuteUpdate() > 0;

                    tx.Commit();
                }
            }

            if (!found)
            {
                timeoutData = null;
                return(false);
            }

            return(true);
        }
        public void Add(TimeoutData timeout)
        {
            timeout.Id = Guid.NewGuid().ToString();
            try
            {
                readerWriterLock.EnterWriteLock();

                using (ITransaction tx = _context.StateManager.CreateTransaction())
                {
                    var storage = storages.GetOrAddAsync(tx, EndpointName, type => new List<TimeoutData>()).Result;

                    storage.Add(timeout);

                    storages.AddOrUpdateAsync(tx, EndpointName, type => new List<TimeoutData>(), (t, o) => storage).Wait();

                    tx.CommitAsync().Wait();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                readerWriterLock.ExitWriteLock();
            }
        }
        public async Task Peek_should_return_timeout_with_id()
        {
            var uniqueId    = Guid.NewGuid().ToString();
            var timeoutData = new TimeoutData
            {
                Time        = DateTime.UtcNow.AddHours(-1),
                Destination = "timeouts",
                SagaId      = Guid.NewGuid(),
                State       = new byte[] { 0, 0, 133 },
                Headers     = new Dictionary <string, string>
                {
                    { "Bar", "34234" },
                    { "Foo", "aString1" },
                    { "Super", "aString2" },
                    { Headers.MessageId, uniqueId }
                },
                OwningTimeoutManager = "MyTestEndpoint"
            };
            await persister.Add(timeoutData, new ContextBag()).ConfigureAwait(false);

            var result = await persister.Peek(timeoutData.Id, new ContextBag()).ConfigureAwait(false);

            Assert.AreEqual(timeoutData.Id, result.Id);
            Assert.AreEqual(timeoutData.Time.ToString("G"), result.Time.ToString("G"));
            Assert.AreEqual(timeoutData.Destination, result.Destination);
            Assert.AreEqual(timeoutData.SagaId, result.SagaId);
            Assert.AreEqual(timeoutData.State, result.State);
            Assert.AreEqual(timeoutData.Headers, result.Headers);
        }
        public async Task When_in_transaction_scope_with_sql_connection_should_hook_up_to_that_connection()
        {
            var data = new TimeoutData
            {
                Time = DateTime.Now,
                OwningTimeoutManager = "MyTestEndpoint",
            };

            var contextBag = new ContextBag();

            using (var tx = new TransactionScope())
            {
                var connection = (SqlConnection)((SessionFactoryImpl)sessionFactory).ConnectionProvider.GetConnection();

                var transaction = new TransportTransaction();
                transaction.Set(Transaction.Current);
                transaction.Set(connection);
                contextBag.Set(transaction);
                await persister.Add(data, contextBag).ConfigureAwait(false);

                Assert.AreEqual(Guid.Empty, Transaction.Current.TransactionInformation.DistributedIdentifier);

                tx.Complete();
            }

            using (var session = sessionFactory.OpenSession())
            {
                Assert.NotNull(session.Get <TimeoutEntity>(new Guid(data.Id)));
            }
        }
    public void UseConfiguredSchema()
    {
        if (!SupportsSchemas())
        {
            Assert.Ignore();
        }

        var startSlice   = new DateTime(2000, 1, 1, 1, 1, 1, DateTimeKind.Utc);
        var timeout1Time = startSlice.AddSeconds(1);
        var timeout1     = new TimeoutData
        {
            Destination = "theDestination",
            State       = new byte[] { 1 },
            Time        = timeout1Time,
            Headers     = new Dictionary <string, string>()
        };
        var defaultSchemaPersister = Setup(null);
        var schemaPersister        = Setup(schema);

        defaultSchemaPersister.Add(timeout1, null).Await();

        var result = schemaPersister.Peek(timeout1.Id, null).Result;

        Assert.Null(result);
    }
        public async Task When_in_transaction_scope_add_should_commit_when_scope_is_complete()
        {
            var data = new TimeoutData
            {
                Time = DateTime.Now.AddYears(-1),
                OwningTimeoutManager = "MyTestEndpoint",
            };

            var contextBag = new ContextBag();

            using (var tx = new TransactionScope())
            {
                var transaction = new TransportTransaction();
                transaction.Set(Transaction.Current);
                contextBag.Set(transaction);
                await persister.Add(data, contextBag).ConfigureAwait(false);

                tx.Complete();
            }

            using (var session = sessionFactory.OpenSession())
            {
                Assert.NotNull(session.Get <TimeoutEntity>(new Guid(data.Id)));
            }
        }
예제 #23
0
        public void Should_remove_timeouts_by_id()
        {
            var t1 = new TimeoutData {
                Time = DateTime.Now.AddYears(-1), OwningTimeoutManager = Configure.EndpointName, Headers = new Dictionary <string, string> {
                    { "Header1", "Value1" }
                }
            };
            var t2 = new TimeoutData {
                Time = DateTime.Now.AddYears(-1), OwningTimeoutManager = Configure.EndpointName, Headers = new Dictionary <string, string> {
                    { "Header1", "Value1" }
                }
            };

            persister.Add(t1);
            persister.Add(t2);

            DateTime nextTimeToRunQuery;
            var      timeouts = persister.GetNextChunk(DateTime.UtcNow.AddYears(-3), out nextTimeToRunQuery);

            foreach (var timeout in timeouts)
            {
                TimeoutData timeoutData;
                persister.TryRemove(timeout.Item1, out timeoutData);
            }

            using (var session = sessionFactory.OpenSession())
            {
                Assert.Null(session.Get <TimeoutEntity>(new Guid(t1.Id)));
                Assert.Null(session.Get <TimeoutEntity>(new Guid(t2.Id)));
            }
        }
    public void FractionalSeconds()
    {
        var startSlice   = new DateTime(2000, 1, 1, 1, 1, 1, 42, DateTimeKind.Utc); // 42ms
        var timeout1Time = startSlice.AddSeconds(1);
        var timeout2Time = goodUtcNowValue.AddSeconds(10);
        var timeout1     = new TimeoutData
        {
            Destination = "theDestination",
            State       = new byte[] { 1 },
            Time        = timeout1Time,
            Headers     = new Dictionary <string, string>()
        };
        var timeout2 = new TimeoutData
        {
            Destination = "theDestination",
            State       = new byte[] { 1 },
            Time        = timeout2Time,
            Headers     = new Dictionary <string, string>()
        };
        var persister = Setup(schema);

        persister.Add(timeout1, null).Await();
        persister.Add(timeout2, null).Await();
        var nextChunk = persister.GetNextChunk(startSlice).Result;

        Assert.That(nextChunk.NextTimeToQuery, Is.EqualTo(timeout2Time).Within(TimeSpan.FromSeconds(1)));
        Assert.That(nextChunk.DueTimeouts.Length, Is.EqualTo(1));

        // MSSQL stores 42ms as .043 because it doesn't have millisecond precision. MySQL/Oracle store to nearest second.
        Assert.That(nextChunk.DueTimeouts[0].DueTime, Is.EqualTo(timeout1Time).Within(TimeSpan.FromMilliseconds(43)));
    }
        public void Should_only_return_timeouts_for_this_specific_endpoint_and_any_ones_without_a_owner()
        {
            const int numberOfTimeoutsToAdd = 3;

            for (var i = 0; i < numberOfTimeoutsToAdd; i++)
            {
                var d = new TimeoutData
                            {
                                Time = DateTime.UtcNow.AddHours(1),
                                OwningTimeoutManager = Configure.EndpointName
                            };

                persister.Add(d);
            }

            persister.Add(new TimeoutData
            {
                Time = DateTime.UtcNow.AddHours(1),
                OwningTimeoutManager = "MyOtherTM"
            });

            persister.Add(new TimeoutData
            {
                Time = DateTime.UtcNow.AddHours(1),
            });

            Assert.AreEqual(numberOfTimeoutsToAdd+1, persister.GetAll().Count());
        }
        public async Task Should_set_the_next_run()
        {
            const int numberOfTimeoutsToAdd = 50;

            for (var i = 0; i < numberOfTimeoutsToAdd; i++)
            {
                var d = new TimeoutData
                {
                    Time = DateTime.UtcNow.AddHours(-1),
                    OwningTimeoutManager = "MyEndpoint"
                };

                await persister.Add(d, new ContextBag());
            }

            var expected = DateTime.UtcNow.AddHours(1);
            await persister.Add(new TimeoutData
            {
                Time = expected,
                OwningTimeoutManager = string.Empty,
            }, new ContextBag());

            var nextChunk = await GetNextChunk();

            var totalMilliseconds = (expected - nextChunk.NextTimeToQuery).Duration().TotalMilliseconds;

            Assert.True(totalMilliseconds < 200);
        }
예제 #27
0
        public bool TryRemove(string timeoutId, out TimeoutData timeoutData)
        {
            try
            {
                readerWriterLock.EnterWriteLock();

                for (var index = 0; index < storage.Count; index++)
                {
                    var data = storage[index];
                    if (data.Id == timeoutId)
                    {
                        timeoutData = data;
                        storage.RemoveAt(index);
                        return(true);
                    }
                }

                timeoutData = null;
                return(false);
            }
            finally
            {
                readerWriterLock.ExitWriteLock();
            }
        }
예제 #28
0
        public void Add(TimeoutData timeout)
        {
            var context = new ServiceContext(account.CreateCloudTableClient());
            var hash    = Hash(timeout);
            TimeoutDataEntity timeoutDataEntity;

            if (TryGetTimeoutData(context, hash, string.Empty, out timeoutDataEntity))
            {
                return;
            }

            var stateAddress = Upload(timeout.State, hash);
            var headers      = Serialize(timeout.Headers);

            if (!TryGetTimeoutData(context, timeout.Time.ToString(PartitionKeyScope), stateAddress, out timeoutDataEntity))
            {
                context.AddObject(ServiceContext.TimeoutDataTableName,
                                  new TimeoutDataEntity(timeout.Time.ToString(PartitionKeyScope), stateAddress)
                {
                    Destination          = timeout.Destination.ToString(),
                    SagaId               = timeout.SagaId,
                    StateAddress         = stateAddress,
                    Time                 = timeout.Time,
                    CorrelationId        = timeout.CorrelationId,
                    OwningTimeoutManager = timeout.OwningTimeoutManager,
                    Headers              = headers
                });
            }

            timeout.Id = stateAddress;

            if (timeout.SagaId != default(Guid) && !TryGetTimeoutData(context, timeout.SagaId.ToString(), stateAddress, out timeoutDataEntity))
            {
                context.AddObject(ServiceContext.TimeoutDataTableName,
                                  new TimeoutDataEntity(timeout.SagaId.ToString(), stateAddress)
                {
                    Destination          = timeout.Destination.ToString(),
                    SagaId               = timeout.SagaId,
                    StateAddress         = stateAddress,
                    Time                 = timeout.Time,
                    CorrelationId        = timeout.CorrelationId,
                    OwningTimeoutManager = timeout.OwningTimeoutManager,
                    Headers              = headers
                });
            }

            context.AddObject(ServiceContext.TimeoutDataTableName,
                              new TimeoutDataEntity(stateAddress, string.Empty)
            {
                Destination          = timeout.Destination.ToString(),
                SagaId               = timeout.SagaId,
                StateAddress         = stateAddress,
                Time                 = timeout.Time,
                CorrelationId        = timeout.CorrelationId,
                OwningTimeoutManager = timeout.OwningTimeoutManager,
                Headers              = headers
            });

            context.SaveChanges();
        }
        public void Should_remove_timeouts_by_id()
        {
            var t1 = new TimeoutData();

            persister.Add(t1);

            var t2 = new TimeoutData();

            persister.Add(t2);

            var t = persister.GetAll();

            foreach (var timeoutData in t)
            {
                using (var tx = new TransactionScope())
                {
                    persister.Remove(timeoutData.Id);

                    tx.Complete();
                }
            }

            t = persister.GetAll();
            Assert.AreEqual(0, t.Count());
        }
예제 #30
0
        public bool TryRemove(string timeoutId, out TimeoutData timeoutData)
        {
            using (var session = SessionFactory.OpenSession())
                using (var tx = session.BeginTransaction(IsolationLevel.ReadCommitted))
                {
                    var te = session.Get <TimeoutEntity>(new Guid(timeoutId));

                    if (te == null)
                    {
                        timeoutData = null;
                        return(false);
                    }

                    timeoutData = new TimeoutData
                    {
                        CorrelationId = te.CorrelationId,
                        Destination   = te.Destination,
                        Id            = te.Id.ToString(),
                        SagaId        = te.SagaId,
                        State         = te.State,
                        Time          = te.Time,
                        Headers       = ConvertStringToDictionary(te.Headers),
                    };

                    session.Delete(te);
                    tx.Commit();

                    return(true);
                }
        }
        public void Should_set_the_next_run()
        {
            const int numberOfTimeoutsToAdd = 50;

            for (var i = 0; i < numberOfTimeoutsToAdd; i++)
            {
                var d = new TimeoutData
                {
                    Time = DateTime.UtcNow.AddHours(-1),
                    OwningTimeoutManager = Configure.EndpointName
                };

                persister.Add(d);
            }

            var expected = DateTime.UtcNow.AddHours(1);

            persister.Add(new TimeoutData
            {
                Time = expected,
                OwningTimeoutManager = String.Empty,
            });

            DateTime nextTimeToRunQuery;

            persister.GetNextChunk(DateTime.UtcNow.AddYears(-3), out nextTimeToRunQuery);

            var totalMilliseconds = (expected - nextTimeToRunQuery).Duration().TotalMilliseconds;

            Assert.True(totalMilliseconds < 200);
        }
        public bool TryRemove(string timeoutId, out TimeoutData timeoutData)
        {
            var query = Builders <TimeoutEntity> .Filter.Eq(t => t.Id, timeoutId);

            var entity = _collection.Find(query).FirstOrDefault();

            if (entity == null)
            {
                timeoutData = null;
                return(false);
            }

            timeoutData = new TimeoutData
            {
                Destination = entity.Destination,
                Id          = entity.Id,
                SagaId      = entity.SagaId,
                State       = entity.State,
                Time        = entity.Time,
                Headers     = entity.Headers,
            };

            if (_collection.DeleteOne(query).DeletedCount == 0)
            {
                timeoutData = null;
                return(false);
            }

            return(true);
        }
예제 #33
0
        public void Should_return_the_correct_headers()
        {
            var headers = new Dictionary <string, string>
            {
                { "Bar", "34234" },
                { "Foo", "aString1" },
                { "Super", "aString2" }
            };

            var timeout = new TimeoutData
            {
                Time                 = DateTime.UtcNow.AddHours(-1),
                Destination          = new Address("timeouts", RuntimeEnvironment.MachineName),
                SagaId               = Guid.NewGuid(),
                State                = new byte[] { 1, 1, 133, 200 },
                Headers              = headers,
                OwningTimeoutManager = "MyTestEndpoint",
            };

            persister.Add(timeout);

            TimeoutData timeoutData;

            persister.TryRemove(timeout.Id, out timeoutData);

            CollectionAssert.AreEqual(headers, timeoutData.Headers);
        }
        public async Task TryRemove_should_work_with_concurrent_transactions()
        {
            var timeout = new TimeoutData
            {
                Time = DateTime.Now
            };

            await persister.Add(timeout, new ContextBag()).ConfigureAwait(false);

            var t1EnteredTx = new AutoResetEvent(false);
            var t2EnteredTx = new AutoResetEvent(false);

            var task1 = Task.Run(() =>
            {
                t1EnteredTx.Set();
                t2EnteredTx.WaitOne();
                return(persister.TryRemove(timeout.Id, new ContextBag()));
            });

            var task2 = Task.Run(() =>
            {
                t2EnteredTx.Set();
                t1EnteredTx.WaitOne();
                return(persister.TryRemove(timeout.Id, new ContextBag()));
            });

            var results = await Task.WhenAll(task1, task2).ConfigureAwait(false);

            Assert.IsTrue(results.Single(x => x));
        }
예제 #35
0
        public void Should_remove_timeouts_by_sagaid()
        {
            var sagaId1 = Guid.NewGuid();
            var sagaId2 = Guid.NewGuid();
            var t1      = new TimeoutData {
                SagaId = sagaId1, Time = DateTime.Now.AddYears(1), OwningTimeoutManager = Configure.EndpointName, Headers = new Dictionary <string, string> {
                    { "Header1", "Value1" }
                }
            };
            var t2 = new TimeoutData {
                SagaId = sagaId2, Time = DateTime.Now.AddYears(1), OwningTimeoutManager = Configure.EndpointName, Headers = new Dictionary <string, string> {
                    { "Header1", "Value1" }
                }
            };

            persister.Add(t1);
            persister.Add(t2);


            persister.RemoveTimeoutBy(sagaId1);
            persister.RemoveTimeoutBy(sagaId2);

            using (var session = sessionFactory.OpenSession())
            {
                Assert.Null(session.Get <TimeoutEntity>(new Guid(t1.Id)));
                Assert.Null(session.Get <TimeoutEntity>(new Guid(t2.Id)));
            }
        }
예제 #36
0
        public void Peek_should_return_timeout_with_id()
        {
            var timeoutData = new TimeoutData
            {
                Time        = DateTime.UtcNow.AddHours(-1),
                Destination = new Address("timeouts", RuntimeEnvironment.MachineName),
                SagaId      = Guid.NewGuid(),
                State       = new byte[] { 0, 0, 133 },
                Headers     = new Dictionary <string, string> {
                    { "Bar", "34234" }, { "Foo", "aString1" }, { "Super", "aString2" }
                },
                OwningTimeoutManager = "MyTestEndpoint"
            };

            persister.Add(timeoutData);

            var result = persister.Peek(timeoutData.Id);

            Assert.AreEqual(timeoutData.Id, result.Id);
            Assert.AreEqual(timeoutData.Time.ToString("G"), result.Time.ToString("G"));
            Assert.AreEqual(timeoutData.Destination, result.Destination);
            Assert.AreEqual(timeoutData.SagaId, result.SagaId);
            Assert.AreEqual(timeoutData.State, result.State);
            Assert.AreEqual(timeoutData.Headers, result.Headers);
        }
 public void Add(TimeoutData timeout)
 {
     lock (storage)
     {
         timeout.Id = Guid.NewGuid().ToString();
         storage.Add(timeout);
     }
 }
예제 #38
0
 public void Remove(TimeoutData timeout)
 {
     using (var session = OpenSession())
     {
         session.Advanced.Defer(new DeleteCommandData { Key = timeout.Id });
         session.SaveChanges();
     }
 }
예제 #39
0
 public void Add(TimeoutData timeout)
 {
     using (var session = OpenSession())
     {
         session.Store(timeout);
         session.SaveChanges();
     }
 }
예제 #40
0
        public async Task Invoke(MessageContext context)
        {
            var sagaId = Guid.Empty;

            string sagaIdString;
            if (context.Headers.TryGetValue(Headers.SagaId, out sagaIdString))
            {
                sagaId = Guid.Parse(sagaIdString);
            }

            if (context.Headers.ContainsKey(TimeoutManagerHeaders.ClearTimeouts))
            {
                if (sagaId == Guid.Empty)
                {
                    throw new InvalidOperationException("Invalid saga id specified, clear timeouts is only supported for saga instances");
                }

                await persister.RemoveTimeoutBy(sagaId, context.Context).ConfigureAwait(false);
            }
            else
            {
                string expire;
                if (!context.Headers.TryGetValue(TimeoutManagerHeaders.Expire, out expire))
                {
                    throw new InvalidOperationException("Non timeout message arrived at the timeout manager, id:" + context.MessageId);
                }

                var destination = GetReplyToAddress(context);

                string routeExpiredTimeoutTo;
                if (context.Headers.TryGetValue(TimeoutManagerHeaders.RouteExpiredTimeoutTo, out routeExpiredTimeoutTo))
                {
                    destination = routeExpiredTimeoutTo;
                }

                var data = new TimeoutData
                {
                    Destination = destination,
                    SagaId = sagaId,
                    State = context.Body,
                    Time = DateTimeExtensions.ToUtcDateTime(expire),
                    Headers = context.Headers,
                    OwningTimeoutManager = owningTimeoutManager
                };

                if (data.Time.AddSeconds(-1) <= DateTime.UtcNow)
                {
                    var outgoingMessage = new OutgoingMessage(context.MessageId, data.Headers, data.State);
                    var transportOperation = new TransportOperation(outgoingMessage, new UnicastAddressTag(data.Destination));
                    await dispatcher.Dispatch(new TransportOperations(transportOperation), context.TransportTransaction, context.Context).ConfigureAwait(false);
                    return;
                }

                await persister.Add(data, context.Context).ConfigureAwait(false);

                poller.NewTimeoutRegistered(data.Time);
            }
        }
 public bool TryRemove(string timeoutId, out TimeoutData timeoutData)
 {
     lock (lockObject)
     {
         timeoutData = storage.SingleOrDefault(t => t.Id == timeoutId);
         
         return timeoutData != null && storage.Remove(timeoutData);
     }
 }
        public void Add(TimeoutData timeout)
        {
            var context = new ServiceContext(account.CreateCloudTableClient()){ IgnoreResourceNotFoundException = true};

            string identifier;
            timeout.Headers.TryGetValue(Headers.MessageId, out identifier);
            if (string.IsNullOrEmpty(identifier)) { identifier = Hash(timeout); }

            TimeoutDataEntity timeoutDataEntity;
            if (TryGetTimeoutData(context, identifier, string.Empty, out timeoutDataEntity)) return;

            var stateAddress = Upload(timeout.State, identifier);
            var headers = Serialize(timeout.Headers);

            if (!TryGetTimeoutData(context, timeout.Time.ToString(PartitionKeyScope), stateAddress, out timeoutDataEntity))
                context.AddObject(ServiceContext.TimeoutDataTableName,
                                      new TimeoutDataEntity(timeout.Time.ToString(PartitionKeyScope), stateAddress)
                                      {
                                          Destination = timeout.Destination.ToString(),
                                          SagaId = timeout.SagaId,
                                          StateAddress = stateAddress,
                                          Time = timeout.Time,
                                          CorrelationId = timeout.CorrelationId,
                                          OwningTimeoutManager = timeout.OwningTimeoutManager,
                                          Headers = headers
                                      });

            timeout.Id = stateAddress;

            if (timeout.SagaId != default(Guid) && !TryGetTimeoutData(context, timeout.SagaId.ToString(), stateAddress, out timeoutDataEntity))
                context.AddObject(ServiceContext.TimeoutDataTableName,
                                      new TimeoutDataEntity(timeout.SagaId.ToString(), stateAddress)
                                      {
                                          Destination = timeout.Destination.ToString(),
                                          SagaId = timeout.SagaId,
                                          StateAddress = stateAddress,
                                          Time = timeout.Time,
                                          CorrelationId = timeout.CorrelationId,
                                          OwningTimeoutManager = timeout.OwningTimeoutManager,
                                          Headers = headers
                                      });

            context.AddObject(ServiceContext.TimeoutDataTableName,
                                new TimeoutDataEntity(stateAddress, string.Empty)
                                {
                                    Destination = timeout.Destination.ToString(),
                                    SagaId = timeout.SagaId,
                                    StateAddress = stateAddress,
                                    Time = timeout.Time,
                                    CorrelationId = timeout.CorrelationId,
                                    OwningTimeoutManager = timeout.OwningTimeoutManager,
                                    Headers = headers
                                });

            context.SaveChanges();
        }
예제 #43
0
        public void Add(TimeoutData timeout)
        {
            var context = new ServiceContext(account.CreateCloudTableClient());
            var hash = Hash(timeout);
            TimeoutDataEntity timeoutDataEntity;
            if (TryGetTimeoutData(context, hash, string.Empty, out timeoutDataEntity)) return;

            var stateAddress = Upload(timeout.State, hash);
            var headers = Serialize(timeout.Headers);

            if (!TryGetTimeoutData(context, timeout.Time.ToString(PartitionKeyScope), stateAddress, out timeoutDataEntity))
                context.AddObject(ServiceContext.TimeoutDataTableName,
                                      new TimeoutDataEntity(timeout.Time.ToString(PartitionKeyScope), stateAddress)
                                      {
                                          Destination = timeout.Destination.ToString(),
                                          SagaId = timeout.SagaId,
                                          StateAddress = stateAddress,
                                          Time = timeout.Time,
                                          CorrelationId = timeout.CorrelationId,
                                          OwningTimeoutManager = timeout.OwningTimeoutManager,
                                          Headers = headers
                                      });

            timeout.Id = stateAddress;

            if (timeout.SagaId != default(Guid) && !TryGetTimeoutData(context, timeout.SagaId.ToString(), stateAddress, out timeoutDataEntity))
                context.AddObject(ServiceContext.TimeoutDataTableName,
                                      new TimeoutDataEntity(timeout.SagaId.ToString(), stateAddress)
                                      {
                                          Destination = timeout.Destination.ToString(),
                                          SagaId = timeout.SagaId,
                                          StateAddress = stateAddress,
                                          Time = timeout.Time,
                                          CorrelationId = timeout.CorrelationId,
                                          OwningTimeoutManager = timeout.OwningTimeoutManager,
                                          Headers = headers
                                      });

            context.AddObject(ServiceContext.TimeoutDataTableName,
                                new TimeoutDataEntity(stateAddress, string.Empty)
                                {
                                    Destination = timeout.Destination.ToString(),
                                    SagaId = timeout.SagaId,
                                    StateAddress = stateAddress,
                                    Time = timeout.Time,
                                    CorrelationId = timeout.CorrelationId,
                                    OwningTimeoutManager = timeout.OwningTimeoutManager,
                                    Headers = headers
                                });

            context.SaveChanges();
        }
예제 #44
0
        public bool CanSend(TimeoutData data)
        {
            var hash = Hash(data);
            TimeoutDataEntity timeoutDataEntity;
            if (!TryGetTimeoutData(hash, out timeoutDataEntity)) return false;

            var leaseBlob = container.GetBlockBlobReference(timeoutDataEntity.StateAddress);

            using (var lease = new AutoRenewLease(leaseBlob))
            {
                return lease.HasLease;
            }
        }
 public void Add(TimeoutData timeout)
 {
     timeout.Id = Guid.NewGuid().ToString();
     try
     {
         readerWriterLock.EnterWriteLock();
         storage.Add(timeout);
     }
     finally
     {
         readerWriterLock.ExitWriteLock();
     }
 }
예제 #46
0
        void IPersistTimeouts.Add(TimeoutData timeout)
        {
            var stateAddress = Serialize(timeout.State, Hash(timeout));

            context.AttachTo(ServiceContext.TimeoutDataEntityTableName,
                                  new TimeoutDataEntity("TimeoutData", stateAddress)
                                      {
                                          Destination = timeout.Destination.ToString(),
                                          SagaId = timeout.SagaId,
                                          StateAddress = stateAddress,
                                          Time = timeout.Time
                                      });
            context.SaveChanges(SaveChangesOptions.ReplaceOnUpdate);
        }
        public void Should_return_the_correct_headers()
        {
            var headers = new Dictionary<string, string> { { "Bar", "34234" }, { "Foo", "dasdsa" }, { "Super", "dsfsdf" } };

            var timeout = new TimeoutData
                {
                    Time = DateTime.UtcNow.AddHours(-1), CorrelationId = "boo", Destination = new Address("timeouts", Environment.MachineName), SagaId = Guid.NewGuid(), State = new byte[] {1, 1, 133, 200}, Headers = headers, OwningTimeoutManager = Configure.EndpointName,
                };
            persister.Add(timeout);

            TimeoutData timeoutData;
            persister.TryRemove(timeout.Id, out timeoutData);

            CollectionAssert.AreEqual(headers, timeoutData.Headers);
        }
        public Task Add(TimeoutData timeout, ContextBag context)
        {
            timeout.Id = Guid.NewGuid().ToString();
            try
            {
                readerWriterLock.EnterWriteLock();
                storage.Add(timeout);
            }
            finally
            {
                readerWriterLock.ExitWriteLock();
            }

            return TaskEx.CompletedTask;
        }
        void IPersistTimeouts.Add(TimeoutData timeout)
        {
            var stateAddress = Serialize(timeout.State, Hash(timeout));

            context.AddObject(ServiceContext.TimeoutDataEntityTableName,
                                  new TimeoutDataEntity("TimeoutData", stateAddress)
                                      {
                                          Destination = timeout.Destination.ToString(),
                                          SagaId = timeout.SagaId,
                                          StateAddress = stateAddress,
                                          Time = timeout.Time,
                                          CorrelationId = timeout.CorrelationId
                                      });

            context.SaveChanges();
        }
        public bool CanSend(TimeoutData data)
        {
            var hash = Hash(data);
            var result = (from c in context.TimeoutData
                          where c.RowKey == hash
                          select c).SingleOrDefault();

            if (result == null) return false;

            var leaseBlob = container.GetBlockBlobReference(result.StateAddress);

            using (var lease = new AutoRenewLease(leaseBlob))
            {
                return lease.HasLease;
            }
        }
        public void Should_remove_timeouts_by_id()
        {
            var t1 = new TimeoutData {Id = "1", Time = DateTime.UtcNow.AddHours(-1)};
            persister.Add(t1);

            var t2 = new TimeoutData {Id = "2", Time = DateTime.UtcNow.AddHours(-1)};
            persister.Add(t2);

            var timeouts = GetNextChunk();

            foreach (var timeout in timeouts)
            {
                TimeoutData timeoutData;
                persister.TryRemove(timeout.Item1, out timeoutData);
            }

            Assert.AreEqual(0, GetNextChunk().Count);
        }
        /// <summary>
        ///     Adds a new timeout.
        /// </summary>
        /// <param name="timeout">Timeout data.</param>
        public void Add(TimeoutData timeout)
        {
            var timeoutId = GenerateCombGuid();
            IDbConnection connection;

            if (TryGetConnection(out connection))
            {
                StoreTimeoutEntity(timeout, connection, timeoutId);
            }
            else
            {
                using (connection = SessionFactory.GetConnection())
                {
                    StoreTimeoutEntity(timeout, connection, timeoutId);
                }
            }

            timeout.Id = timeoutId.ToString();
        }
        public void Should_remove_timeouts_by_sagaid()
        {
            var sagaId1 = Guid.NewGuid();
            var sagaId2 = Guid.NewGuid();
            var t1 = new TimeoutData { SagaId = sagaId1, Time = DateTime.Now.AddYears(1), OwningTimeoutManager = Configure.EndpointName, Headers = new Dictionary<string, string> { { "Header1", "Value1" } } };
            var t2 = new TimeoutData { SagaId = sagaId2, Time = DateTime.Now.AddYears(1), OwningTimeoutManager = Configure.EndpointName, Headers = new Dictionary<string, string> { { "Header1", "Value1" } } };

            persister.Add(t1);
            persister.Add(t2);

            persister.RemoveTimeoutBy(sagaId1);
            persister.RemoveTimeoutBy(sagaId2);

            using (var session = sessionFactory.OpenSession())
            {
                Assert.Null(session.Get<TimeoutEntity>(new Guid(t1.Id)));
                Assert.Null(session.Get<TimeoutEntity>(new Guid(t2.Id)));
            }
        }
        public void Should_remove_timeouts_by_id()
        {
            var t1 = new TimeoutData { Time = DateTime.Now.AddYears(1), OwningTimeoutManager = Configure.EndpointName, Headers = new Dictionary<string, string> { { "Header1", "Value1" } } };
            var t2 = new TimeoutData { Time = DateTime.Now.AddYears(1), OwningTimeoutManager = Configure.EndpointName, Headers = new Dictionary<string, string> { { "Header1", "Value1" } } };

            persister.Add(t1);
            persister.Add(t2);

            var t = persister.GetAll();

            foreach (var timeoutData in t)
            {
                persister.Remove(timeoutData.Id);
            }

            using (var session = sessionFactory.OpenSession())
            {
                Assert.Null(session.Get<TimeoutEntity>(new Guid(t1.Id)));
                Assert.Null(session.Get<TimeoutEntity>(new Guid(t2.Id)));
            }
        }
        public void Peek_should_return_timeout_with_id()
        {
            var timeoutData = new TimeoutData
            {
                Time = DateTime.UtcNow.AddHours(-1),
                Destination = new Address("timeouts", RuntimeEnvironment.MachineName),
                SagaId = Guid.NewGuid(),
                State = new byte[] { 0, 0, 133 },
                Headers = new Dictionary<string, string> { { "Bar", "34234" }, { "Foo", "aString1" }, { "Super", "aString2" } },
                OwningTimeoutManager = "MyTestEndpoint"
            };
            persister.Add(timeoutData);

            var result = persister.Peek(timeoutData.Id);

            Assert.AreEqual(timeoutData.Id, result.Id);
            Assert.AreEqual(timeoutData.Time.ToString("G"), result.Time.ToString("G"));
            Assert.AreEqual(timeoutData.Destination, result.Destination);
            Assert.AreEqual(timeoutData.SagaId, result.SagaId);
            Assert.AreEqual(timeoutData.State, result.State);
            Assert.AreEqual(timeoutData.Headers, result.Headers);
        }
        public void Should_remove_timeouts_by_id()
        {
            var t1 = new TimeoutData
                     {
                         Time = DateTime.Now.AddYears(-1),
                         OwningTimeoutManager = Configure.EndpointName,
                         Headers = new Dictionary<string, string>
                                   {
                                       {"Header1", "Value1"}
                                   }
                     };
            var t2 = new TimeoutData
                     {
                         Time = DateTime.Now.AddYears(-1),
                         OwningTimeoutManager = Configure.EndpointName,
                         Headers = new Dictionary<string, string>
                                   {
                                       {"Header1", "Value1"}
                                   }
                     };

            persister.Add(t1);
            persister.Add(t2);

            DateTime nextTimeToRunQuery;
            var timeouts = persister.GetNextChunk(DateTime.UtcNow.AddYears(-3), out nextTimeToRunQuery);

            foreach (var timeout in timeouts)
            {
                TimeoutData timeoutData;
                persister.TryRemove(timeout.Item1, out timeoutData);
            }

            using (var session = sessionFactory.OpenSession())
            {
                Assert.Null(session.Get<TimeoutEntity>(new Guid(t1.Id)));
                Assert.Null(session.Get<TimeoutEntity>(new Guid(t2.Id)));
            }
        }
        public void Add(TimeoutData timeout)
        {
            var newId = Guid.NewGuid();

            using (var session = SessionFactory.OpenSession())
            using (var tx = session.BeginTransaction(IsolationLevel.ReadCommitted))
            {
                session.Save(new TimeoutEntity
                {
                    Id = newId,
                    CorrelationId = timeout.CorrelationId,
                    Destination = timeout.Destination,
                    SagaId = timeout.SagaId,
                    State = timeout.State,
                    Time = timeout.Time,
                    Headers = ConvertDictionaryToString(timeout.Headers),
                    Endpoint = timeout.OwningTimeoutManager,
                });

                tx.Commit();
            }

            timeout.Id = newId.ToString();
        }
        public bool TryRemove(string timeoutId, out TimeoutData timeoutData)
        {
            try
            {
                bool result = false;
                timeoutData = null;

                readerWriterLock.EnterWriteLock();

                using (ITransaction tx = _context.StateManager.CreateTransaction())
                {
                    var storage = storages.GetOrAddAsync(tx, EndpointName, type => new List<TimeoutData>()).Result;

                    for (var index = 0; index < storage.Count; index++)
                    {
                        var data = storage[index];
                        if (data.Id == timeoutId)
                        {
                            timeoutData = data;
                            storage.RemoveAt(index);
                            result = true;
                            break;
                        }
                    }

                    storages.AddOrUpdateAsync(tx, EndpointName, type => new List<TimeoutData>(), (t, o) => storage).Wait();

                    tx.CommitAsync().Wait();                    
                }
                
                return result;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                readerWriterLock.ExitWriteLock();
            }
        }
        private static string Hash(TimeoutData timeout)
        {
            var s = timeout.SagaId + timeout.Destination.ToString() + timeout.Time.Ticks;
            var sha1 = SHA1.Create();
            var bytes = sha1.ComputeHash(Encoding.UTF8.GetBytes(s));

            var hash = new StringBuilder();
            for (var i = 0; i < bytes.Length; i++)
            {
                hash.Append(bytes[i].ToString("X2"));
            }
            return hash.ToString();
        }
 private void TimeoutsManagerOnTimeoutPushed(object sender, TimeoutData timeoutData)
 {
     lock (lockObject)
     {
         if (nextRetrieval > timeoutData.Time)
         {
             nextRetrieval = timeoutData.Time;
         }
         timeoutPushed = true;
     }
 }