public async Task Remove_WhenConcurrentDeletesUsingDtc_OnlyOneOperationShouldSucceed()
        {
            var persister = new TimeoutPersister(store);
            var timeoutData = new TimeoutData();
            await persister.Add(timeoutData, new ContextBag());

            var documentRemoved = new CountdownEvent(2);

            var t1 = Task.Run(async () =>
            {
                using (var tx = new TransactionScope(TransactionScopeOption.RequiresNew, TransactionScopeAsyncFlowOption.Enabled))
                {
                    var result = await persister.TryRemove(timeoutData.Id, new ContextBag());
                    documentRemoved.Signal(1);
                    documentRemoved.Wait();
                    tx.Complete();
                    return result;
                }
            });

            var t2 = Task.Run(async () =>
            {
                using (var tx = new TransactionScope(TransactionScopeOption.RequiresNew, TransactionScopeAsyncFlowOption.Enabled))
                {
                    var result = await persister.TryRemove(timeoutData.Id, new ContextBag());
                    documentRemoved.Signal(1);
                    documentRemoved.Wait();
                    tx.Complete();
                    return result;
                }
            });

            Assert.IsTrue(await t1 | await t2, "the document should be deleted");
            Assert.IsFalse(t1.Result && t2.Result, "only one operation should complete successfully");
        }
        public async Task Remove_WhenTimeoutRemoved_ShouldReturnTrue()
        {
            var persister   = new TimeoutPersister(store);
            var timeoutData = new TimeoutData();
            await persister.Add(timeoutData, new ContextBag());

            var result = await persister.TryRemove(timeoutData.Id, new ContextBag());

            Assert.IsTrue(result);
        }
        public async Task Remove_WhenTimeoutRemoved_ShouldReturnTrue()
        {
            var persister = new TimeoutPersister(store);
            var timeoutData = new TimeoutData();
            await persister.Add(timeoutData, new ContextBag());

            var result = await persister.TryRemove(timeoutData.Id, new ContextBag());

            Assert.IsTrue(result);
        }
        public async Task Add_WhenNoIdProvided_ShouldSetDbGeneratedTimeoutId()
        {
            var persister = new TimeoutPersister(store);
            var timeout = new TimeoutData { Id = null };

            await persister.Add(timeout, new ContextBag());
            Assert.IsNotNull(timeout.Id);

            var result = await persister.Peek(timeout.Id, new ContextBag());
            Assert.IsNotNull(result);
        }
        public async Task Add_WhenIdProvided_ShouldOverrideGivenId()
        {
            var persister = new TimeoutPersister(store);

            var timeoutId = Guid.NewGuid().ToString();
            var timeout = new TimeoutData { Id = timeoutId };

            await persister.Add(timeout, new ContextBag());
            Assert.AreNotEqual(timeoutId, timeout.Id);

            var result = await persister.Peek(timeoutId, new ContextBag());
            Assert.IsNull(result);
        }
        public async Task Add_WhenNoIdProvided_ShouldSetDbGeneratedTimeoutId()
        {
            var persister = new TimeoutPersister(store);
            var timeout   = new CoreTimeoutData {
                Id = null
            };

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

            Assert.IsNotNull(timeout.Id);

            var result = await persister.Peek(timeout.Id, new ContextBag());

            Assert.IsNotNull(result);
        }
        public async Task Add_WhenIdProvided_ShouldOverrideGivenId()
        {
            var persister = new TimeoutPersister(store);

            var timeoutId = Guid.NewGuid().ToString();
            var timeout   = new CoreTimeoutData {
                Id = timeoutId
            };

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

            Assert.AreNotEqual(timeoutId, timeout.Id);

            var result = await persister.Peek(timeoutId, new ContextBag());

            Assert.IsNull(result);
        }
        public async Task Add_ShouldStoreSchemaVersion()
        {
            var persister = new TimeoutPersister(store);

            var timeoutId = Guid.NewGuid().ToString();
            var timeout   = new CoreTimeoutData {
                Id = timeoutId
            };

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

            WaitForIndexing();

            using (var session = store.OpenAsyncSession())
            {
                var ravenDBTimeoutData = await session
                                         .Query <RavenDBTimeoutData>()
                                         .SingleOrDefaultAsync();

                var metadata = session.Advanced.GetMetadataFor(ravenDBTimeoutData);

                Assert.AreEqual(RavenDBTimeoutData.SchemaVersion, metadata[SchemaVersionExtensions.TimeoutDataSchemaVersionMetadataKey]);
            }
        }
        // This test makes sure that the conversion listener doesn't destroy new documents
        public async Task Should_allow_new_timeouts()
        {
            var headers = new Dictionary <string, string>
            {
                { "Bar", "34234" },
                { "Foo", "aString1" },
                { "Super", "aString2" }
            };

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

            var session = store.OpenAsyncSession();
            await session.StoreAsync(timeout);

            await session.SaveChangesAsync();

            var context = new ContextBag();

            var retreievedTimeout = await persister.Peek(timeout.Id, context);

            Assert.AreEqual(timeout.Destination, retreievedTimeout.Destination);
        }
        private async Task Prefill(IDocumentStore store, ConventionType seedType)
        {
            Console.WriteLine($"Filling database with timeout data, using {seedType} conventions");
            var timeout = new TimeoutData
            {
                Destination = EndpointName,
                Headers = new Dictionary<string, string>(),
                OwningTimeoutManager = EndpointName,
                Time = new DateTime(DateTime.UtcNow.Year, 1, 1)
            };

            var names = new Dictionary<ConventionType, string>
            {
                { ConventionType.RavenDefault, "TimeoutDatas" },
                { ConventionType.NSBDefault, "TimeoutData" },
                { ConventionType.Customer, "ataDtuoemiT" }
            };
            var name = names[seedType];

            for (var i = 1; i <= 10; i++)
            {
                await DirectStore(store, $"{name}/{i}", timeout, name);
            }

            await StoreHiLo(store, name);
        }
        public async Task Never_ever()
        {
            var db = Guid.NewGuid().ToString();

            using (var documentStore = new DocumentStore
            {
                Urls = TestConstants.RavenUrls,
                Database = db
            }.Initialize())
            {
                new TimeoutsIndex().Execute(documentStore);

                var query = new QueryTimeouts(documentStore, "foo")
                {
                    TriggerCleanupEvery = TimeSpan.FromHours(1) // Make sure cleanup doesn't run automatically
                };
                var persister = new TimeoutPersister(documentStore);
                var context   = new ContextBag();

                var startSlice = DateTime.UtcNow.AddYears(-10);
                // avoid cleanup from running during the test by making it register as being run
                Assert.AreEqual(0, (await query.GetCleanupChunk(startSlice)).Count());

                var expected       = new List <Tuple <string, DateTime> >();
                var lastTimeout    = DateTime.UtcNow;
                var finishedAdding = false;

                new Thread(() =>
                {
                    var sagaId = Guid.NewGuid();
                    for (var i = 0; i < 10000; i++)
                    {
                        var td = new TimeoutData
                        {
                            SagaId               = sagaId,
                            Destination          = "queue@machine",
                            Time                 = DateTime.UtcNow.AddSeconds(RandomProvider.GetThreadRandom().Next(1, 20)),
                            OwningTimeoutManager = string.Empty
                        };
                        persister.Add(td, context).Wait();
                        expected.Add(new Tuple <string, DateTime>(td.Id, td.Time));
                        lastTimeout = (td.Time > lastTimeout) ? td.Time : lastTimeout;
                    }
                    finishedAdding = true;
                    Trace.WriteLine("*** Finished adding ***");
                }).Start();

                // Mimic the behavior of the TimeoutPersister coordinator
                var found = 0;
                while (!finishedAdding || startSlice < lastTimeout)
                {
                    var timeoutData = await query.GetNextChunk(startSlice);

                    foreach (var timeout in timeoutData.DueTimeouts)
                    {
                        if (startSlice < timeout.DueTime)
                        {
                            startSlice = timeout.DueTime;
                        }

                        Assert.True(await persister.TryRemove(timeout.Id, context));
                        found++;
                    }
                }

                WaitForIndexing(documentStore);

                // If the persister reports stale results have been seen at one point during its normal operation,
                // we need to perform manual cleaup.
                while (true)
                {
                    var chunkToCleanup = (await query.GetCleanupChunk(DateTime.UtcNow.AddDays(1))).ToArray();
                    if (chunkToCleanup.Length == 0)
                    {
                        break;
                    }

                    found += chunkToCleanup.Length;
                    foreach (var tuple in chunkToCleanup)
                    {
                        Assert.True(await persister.TryRemove(tuple.Id, context));
                    }

                    WaitForIndexing(documentStore);
                }

                using (var session = documentStore.OpenAsyncSession())
                {
                    var results = await session.Query <TimeoutData>().ToListAsync();

                    Assert.AreEqual(0, results.Count);
                }

                Assert.AreEqual(expected.Count, found);
            }
        }
        public async Task Never_ever()
        {
            var db = Guid.NewGuid().ToString();
            using (var documentStore = new DocumentStore
            {
                Url = "http://*****:*****@machine",
                            Time = DateTime.UtcNow.AddSeconds(RandomProvider.GetThreadRandom().Next(1, 20)),
                            OwningTimeoutManager = string.Empty
                        };
                        persister.Add(td, context).Wait();
                        expected.Add(new Tuple<string, DateTime>(td.Id, td.Time));
                        lastTimeout = (td.Time > lastTimeout) ? td.Time : lastTimeout;
                    }
                    finishedAdding = true;
                    Trace.WriteLine("*** Finished adding ***");
                }).Start();

                // Mimic the behavior of the TimeoutPersister coordinator
                var found = 0;
                while (!finishedAdding || startSlice < lastTimeout)
                {
                    var timeoutData = await query.GetNextChunk(startSlice);
                    foreach (var timeout in timeoutData.DueTimeouts)
                    {
                        if (startSlice < timeout.DueTime)
                        {
                            startSlice = timeout.DueTime;
                        }

                        Assert.True(await persister.TryRemove(timeout.Id, context));
                        found++;
                    }
                }

                WaitForIndexing(documentStore);

                // If the persister reports stale results have been seen at one point during its normal operation,
                // we need to perform manual cleaup.
                while (true)
                {
                    var chunkToCleanup = (await query.GetCleanupChunk(DateTime.UtcNow.AddDays(1))).ToArray();
                    if (chunkToCleanup.Length == 0)
                    {
                        break;
                    }

                    found += chunkToCleanup.Length;
                    foreach (var tuple in chunkToCleanup)
                    {
                        Assert.True(await persister.TryRemove(tuple.Id, context));
                    }

                    WaitForIndexing(documentStore);
                }

                using (var session = documentStore.OpenAsyncSession())
                {
                    var results = await session.Query<TimeoutData>().ToListAsync();
                    Assert.AreEqual(0, results.Count);
                }

                Assert.AreEqual(expected.Count, found);
            }
        }
Пример #13
0
        public async Task Should_not_skip_timeouts_also_with_multiple_clients_adding_timeouts()
        {
            var db = Guid.NewGuid().ToString();

            using (var documentStore = new DocumentStore
            {
                Url = TestConstants.RavenUrl,
                DefaultDatabase = db,
                ApiKey = TestConstants.RavenApiKey
            }.Initialize())
            {
                new TimeoutsIndex().Execute(documentStore);

                var query = new QueryTimeouts(documentStore, "foo")
                {
                    TriggerCleanupEvery = TimeSpan.FromDays(1) // Make sure cleanup doesn't run automatically
                };
                var persister = new TimeoutPersister(documentStore);
                var context   = new ContextBag();

                var startSlice = DateTime.UtcNow.AddYears(-10);
                // avoid cleanup from running during the test by making it register as being run
                Assert.AreEqual(0, (await query.GetCleanupChunk(startSlice)).Count());

                const int insertsPerThread    = 1000;
                var       expected            = 0;
                var       lastExpectedTimeout = DateTime.UtcNow;
                var       finishedAdding1     = false;
                var       finishedAdding2     = false;

                new Thread(() =>
                {
                    var sagaId = Guid.NewGuid();
                    for (var i = 0; i < insertsPerThread; i++)
                    {
                        var td = new TimeoutData
                        {
                            SagaId               = sagaId,
                            Destination          = "queue@machine",
                            Time                 = DateTime.UtcNow.AddSeconds(RandomProvider.GetThreadRandom().Next(1, 20)),
                            OwningTimeoutManager = string.Empty
                        };
                        persister.Add(td, context).Wait();
                        Interlocked.Increment(ref expected);
                        lastExpectedTimeout = (td.Time > lastExpectedTimeout) ? td.Time : lastExpectedTimeout;
                    }
                    finishedAdding1 = true;
                    Console.WriteLine("*** Finished adding ***");
                }).Start();

                new Thread(() =>
                {
                    using (var store = new DocumentStore
                    {
                        Url = TestConstants.RavenUrl,
                        DefaultDatabase = db,
                        ApiKey = TestConstants.RavenApiKey
                    }.Initialize())
                    {
                        var persister2 = new TimeoutPersister(store);

                        var sagaId = Guid.NewGuid();
                        for (var i = 0; i < insertsPerThread; i++)
                        {
                            var td = new TimeoutData
                            {
                                SagaId               = sagaId,
                                Destination          = "queue@machine",
                                Time                 = DateTime.UtcNow.AddSeconds(RandomProvider.GetThreadRandom().Next(1, 20)),
                                OwningTimeoutManager = string.Empty
                            };
                            persister2.Add(td, context).Wait();
                            Interlocked.Increment(ref expected);
                            lastExpectedTimeout = (td.Time > lastExpectedTimeout) ? td.Time : lastExpectedTimeout;
                        }
                    }
                    finishedAdding2 = true;
                    Console.WriteLine("*** Finished adding via a second client connection ***");
                }).Start();

                // Mimic the behavior of the TimeoutPersister coordinator
                var found = 0;
                while (!finishedAdding1 || !finishedAdding2 || startSlice < lastExpectedTimeout)
                {
                    var timeoutDatas = await query.GetNextChunk(startSlice);

                    foreach (var timeoutData in timeoutDatas.DueTimeouts)
                    {
                        if (startSlice < timeoutData.DueTime)
                        {
                            startSlice = timeoutData.DueTime;
                        }

                        Assert.True(await persister.TryRemove(timeoutData.Id, context));
                        found++;
                    }
                }

                WaitForIndexing(documentStore);

                // If the persister reports stale results have been seen at one point during its normal operation,
                // we need to perform manual cleaup.
                while (true)
                {
                    var chunkToCleanup = (await query.GetCleanupChunk(DateTime.UtcNow.AddDays(1))).ToArray();
                    Console.WriteLine("Cleanup: got a chunk of size " + chunkToCleanup.Length);
                    if (chunkToCleanup.Length == 0)
                    {
                        break;
                    }

                    found += chunkToCleanup.Length;
                    foreach (var tuple in chunkToCleanup)
                    {
                        Assert.True(await persister.TryRemove(tuple.Id, context));
                    }

                    WaitForIndexing(documentStore);
                }

                using (var session = documentStore.OpenAsyncSession())
                {
                    var results = await session.Query <TimeoutData>().ToListAsync();

                    Assert.AreEqual(0, results.Count);
                }

                Assert.AreEqual(expected, found);
            }
        }
        // This test makes sure that the conversion listener doesn't destroy new documents
        public async Task Should_allow_new_timeouts()
        {
            var headers = new Dictionary<string, string>
            {
                {"Bar", "34234"},
                {"Foo", "aString1"},
                {"Super", "aString2"}
            };

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

            var session = store.OpenAsyncSession();
            await session.StoreAsync(timeout);
            await session.SaveChangesAsync();
            var context = new ContextBag();

            var retreievedTimeout = await persister.Peek(timeout.Id, context);

            Assert.AreEqual(timeout.Destination, retreievedTimeout.Destination);
        }