diff --git a/buildsupport/FubuCore.dll b/buildsupport/FubuCore.dll index 19712e0f596..de611bc0143 100644 Binary files a/buildsupport/FubuCore.dll and b/buildsupport/FubuCore.dll differ diff --git a/buildsupport/FubuCore.pdb b/buildsupport/FubuCore.pdb deleted file mode 100644 index 05d9a6e0f81..00000000000 Binary files a/buildsupport/FubuCore.pdb and /dev/null differ diff --git a/buildsupport/GitFlowVersion/Build/GitFlowVersionTask.targets b/buildsupport/GitFlowVersion/Build/GitFlowVersionTask.targets deleted file mode 100644 index 368f84e44fb..00000000000 --- a/buildsupport/GitFlowVersion/Build/GitFlowVersionTask.targets +++ /dev/null @@ -1,45 +0,0 @@ - - - - $(MSBuildProjectDirectory)..\ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/buildsupport/GitFlowVersion/GitFlowVersion.exe b/buildsupport/GitFlowVersion/GitFlowVersion.exe deleted file mode 100644 index df38c906a41..00000000000 Binary files a/buildsupport/GitFlowVersion/GitFlowVersion.exe and /dev/null differ diff --git a/buildsupport/GitFlowVersion/GitFlowVersion.pdb b/buildsupport/GitFlowVersion/GitFlowVersion.pdb deleted file mode 100644 index 98047eb7413..00000000000 Binary files a/buildsupport/GitFlowVersion/GitFlowVersion.pdb and /dev/null differ diff --git a/buildsupport/GitFlowVersion/GitFlowVersionTask.dll b/buildsupport/GitFlowVersion/GitFlowVersionTask.dll deleted file mode 100644 index ac2dc5bbdf1..00000000000 Binary files a/buildsupport/GitFlowVersion/GitFlowVersionTask.dll and /dev/null differ diff --git a/buildsupport/GitFlowVersion/GitFlowVersionTask.pdb b/buildsupport/GitFlowVersion/GitFlowVersionTask.pdb deleted file mode 100644 index 34b0222bccb..00000000000 Binary files a/buildsupport/GitFlowVersion/GitFlowVersionTask.pdb and /dev/null differ diff --git a/buildsupport/GitFlowVersion/LibGit2Sharp.dll b/buildsupport/GitFlowVersion/LibGit2Sharp.dll deleted file mode 100644 index 93d322ed565..00000000000 Binary files a/buildsupport/GitFlowVersion/LibGit2Sharp.dll and /dev/null differ diff --git a/buildsupport/GitFlowVersion/NativeBinaries/amd64/git2-11f8336.dll b/buildsupport/GitFlowVersion/NativeBinaries/amd64/git2-11f8336.dll deleted file mode 100644 index d06ebea12ae..00000000000 Binary files a/buildsupport/GitFlowVersion/NativeBinaries/amd64/git2-11f8336.dll and /dev/null differ diff --git a/buildsupport/GitFlowVersion/NativeBinaries/x86/git2-11f8336.dll b/buildsupport/GitFlowVersion/NativeBinaries/x86/git2-11f8336.dll deleted file mode 100644 index 7d66ec11203..00000000000 Binary files a/buildsupport/GitFlowVersion/NativeBinaries/x86/git2-11f8336.dll and /dev/null differ diff --git a/buildsupport/GitVersionTask/Build/GitVersionTask.targets b/buildsupport/GitVersionTask/Build/GitVersionTask.targets new file mode 100644 index 00000000000..2b3fcc62b28 --- /dev/null +++ b/buildsupport/GitVersionTask/Build/GitVersionTask.targets @@ -0,0 +1,51 @@ + + + + $(MSBuildProjectDirectory)..\ + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/buildsupport/GitVersionTask/GitVersionCore.dll b/buildsupport/GitVersionTask/GitVersionCore.dll new file mode 100644 index 00000000000..a4342bd7da0 Binary files /dev/null and b/buildsupport/GitVersionTask/GitVersionCore.dll differ diff --git a/buildsupport/GitVersionTask/GitVersionTask.dll b/buildsupport/GitVersionTask/GitVersionTask.dll new file mode 100644 index 00000000000..079924a095c Binary files /dev/null and b/buildsupport/GitVersionTask/GitVersionTask.dll differ diff --git a/buildsupport/GitVersionTask/LibGit2Sharp.dll b/buildsupport/GitVersionTask/LibGit2Sharp.dll new file mode 100644 index 00000000000..e45661bd83e Binary files /dev/null and b/buildsupport/GitVersionTask/LibGit2Sharp.dll differ diff --git a/buildsupport/GitVersionTask/NativeBinaries/amd64/git2-06d772d.dll b/buildsupport/GitVersionTask/NativeBinaries/amd64/git2-06d772d.dll new file mode 100644 index 00000000000..639b55ef416 Binary files /dev/null and b/buildsupport/GitVersionTask/NativeBinaries/amd64/git2-06d772d.dll differ diff --git a/buildsupport/GitVersionTask/NativeBinaries/x86/git2-06d772d.dll b/buildsupport/GitVersionTask/NativeBinaries/x86/git2-06d772d.dll new file mode 100644 index 00000000000..1ceb3b2ec36 Binary files /dev/null and b/buildsupport/GitVersionTask/NativeBinaries/x86/git2-06d772d.dll differ diff --git a/buildsupport/NuGet.Core.dll b/buildsupport/NuGet.Core.dll index 390e4e025ac..a5787205f1f 100644 Binary files a/buildsupport/NuGet.Core.dll and b/buildsupport/NuGet.Core.dll differ diff --git a/buildsupport/RippleRestoreTask.dll b/buildsupport/RippleRestoreTask.dll index bb438ef2a8c..e84e8b68bf4 100644 Binary files a/buildsupport/RippleRestoreTask.dll and b/buildsupport/RippleRestoreTask.dll differ diff --git a/buildsupport/RippleRestoreTask.pdb b/buildsupport/RippleRestoreTask.pdb deleted file mode 100644 index ef5ffaf6e96..00000000000 Binary files a/buildsupport/RippleRestoreTask.pdb and /dev/null differ diff --git a/buildsupport/RippleRestoreTask.targets b/buildsupport/RippleRestoreTask.targets index 9f45f01134a..cb3f1b8399e 100644 --- a/buildsupport/RippleRestoreTask.targets +++ b/buildsupport/RippleRestoreTask.targets @@ -2,7 +2,7 @@ $(MSBuildProjectDirectory)\..\ - + RippleRestoreTarget; $(BuildDependsOn); diff --git a/buildsupport/Timestamp/Build/Timestamp.targets b/buildsupport/Timestamp/Build/Timestamp.targets deleted file mode 100644 index cebec66775c..00000000000 --- a/buildsupport/Timestamp/Build/Timestamp.targets +++ /dev/null @@ -1,35 +0,0 @@ - - - - $(MSBuildProjectDirectory)..\ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/buildsupport/Timestamp/Timestamp.dll b/buildsupport/Timestamp/Timestamp.dll deleted file mode 100644 index 4d0be4e1c26..00000000000 Binary files a/buildsupport/Timestamp/Timestamp.dll and /dev/null differ diff --git a/buildsupport/Timestamp/Timestamp.pdb b/buildsupport/Timestamp/Timestamp.pdb deleted file mode 100644 index b34f48cac78..00000000000 Binary files a/buildsupport/Timestamp/Timestamp.pdb and /dev/null differ diff --git a/buildsupport/ripple.exe b/buildsupport/ripple.exe index 7d6d4f7df94..5ed129f4cc6 100644 Binary files a/buildsupport/ripple.exe and b/buildsupport/ripple.exe differ diff --git a/buildsupport/ripple.pdb b/buildsupport/ripple.pdb deleted file mode 100644 index 4276c35908b..00000000000 Binary files a/buildsupport/ripple.pdb and /dev/null differ diff --git a/buildsupport/run-git.cmd b/buildsupport/run-git.cmd deleted file mode 100644 index f09175c0a4c..00000000000 --- a/buildsupport/run-git.cmd +++ /dev/null @@ -1 +0,0 @@ -git %* \ No newline at end of file diff --git a/src/NServiceBus.AcceptanceTesting/NServiceBus.AcceptanceTesting.csproj b/src/NServiceBus.AcceptanceTesting/NServiceBus.AcceptanceTesting.csproj index 91064ee4c76..14f4dc6a708 100644 --- a/src/NServiceBus.AcceptanceTesting/NServiceBus.AcceptanceTesting.csproj +++ b/src/NServiceBus.AcceptanceTesting/NServiceBus.AcceptanceTesting.csproj @@ -81,5 +81,5 @@ - + \ No newline at end of file diff --git a/src/NServiceBus.Core.Tests/NServiceBus.Core.Tests.csproj b/src/NServiceBus.Core.Tests/NServiceBus.Core.Tests.csproj index 807e51de2bc..3b6f3ad2cee 100644 --- a/src/NServiceBus.Core.Tests/NServiceBus.Core.Tests.csproj +++ b/src/NServiceBus.Core.Tests/NServiceBus.Core.Tests.csproj @@ -256,6 +256,7 @@ + diff --git a/src/NServiceBus.Core.Tests/Timeout/RavenTimeoutPersisterTests.cs b/src/NServiceBus.Core.Tests/Timeout/RavenTimeoutPersisterTests.cs new file mode 100644 index 00000000000..d92d5238706 --- /dev/null +++ b/src/NServiceBus.Core.Tests/Timeout/RavenTimeoutPersisterTests.cs @@ -0,0 +1,260 @@ +namespace NServiceBus.Core.Tests.Timeout +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading; + using NServiceBus.Persistence.Raven; + using NServiceBus.Persistence.Raven.TimeoutPersister; + using NServiceBus.Timeout.Core; + using NUnit.Framework; + using Raven.Client; + using Raven.Client.Document; + + [TestFixture] + public class RavenTimeoutPersisterTests + { + [TestCase, Repeat(200)] + public void Should_not_skip_timeouts() + { + var db = Guid.NewGuid().ToString(); + documentStore = new DocumentStore + { + Url = "http://localhost:8080", + DefaultDatabase = db, + }.Initialize(); + persister = new RavenTimeoutPersistence(new StoreAccessor(documentStore)) + { + TriggerCleanupEvery = TimeSpan.FromHours(1), // Make sure cleanup doesn't run automatically + }; + + var startSlice = DateTime.UtcNow.AddYears(-10); + // avoid cleanup from running during the test by making it register as being run + Assert.AreEqual(0, persister.GetCleanupChunk(startSlice).Count()); + + var expected = new List>(); + var lastExpectedTimeout = 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 = new Address("queue", "machine"), + Time = DateTime.UtcNow.AddSeconds(RandomProvider.GetThreadRandom().Next(5, 20)), + OwningTimeoutManager = string.Empty, + }; + persister.Add(td); + expected.Add(new Tuple(td.Id, td.Time)); + lastExpectedTimeout = (td.Time > lastExpectedTimeout) ? td.Time : lastExpectedTimeout; + } + finishedAdding = true; + Console.WriteLine("*** Finished adding ***"); + }).Start(); + + // Mimic the behavior of the TimeoutPersister coordinator + var found = 0; + TimeoutData tempTd; + while (!finishedAdding || startSlice < lastExpectedTimeout) + { + DateTime nextRetrieval; + var timeoutDatas = persister.GetNextChunk(startSlice, out nextRetrieval); + foreach (var timeoutData in timeoutDatas) + { + if (startSlice < timeoutData.Item2) + { + startSlice = timeoutData.Item2; + } + + Assert.IsTrue(persister.TryRemove(timeoutData.Item1, out tempTd)); + 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 = persister.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.IsTrue(persister.TryRemove(tuple.Item1, out tempTd)); + } + + WaitForIndexing(documentStore); + } + + using (var session = documentStore.OpenSession()) + { + var results = session.Query().ToList(); + Assert.AreEqual(0, results.Count); + } + + Assert.AreEqual(expected.Count, found); + } + + [TestCase, Repeat(200)] + public void Should_not_skip_timeouts_also_with_multiple_clients_adding_timeouts() + { + var db = Guid.NewGuid().ToString(); + documentStore = new DocumentStore + { + Url = "http://localhost:8080", + DefaultDatabase = db, + }.Initialize(); + persister = new RavenTimeoutPersistence(new StoreAccessor(documentStore)) + { + TriggerCleanupEvery = TimeSpan.FromDays(1), // Make sure cleanup doesn't run automatically + }; + + var startSlice = DateTime.UtcNow.AddYears(-10); + // avoid cleanup from running during the test by making it register as being run + Assert.AreEqual(0, persister.GetCleanupChunk(startSlice).Count()); + + const int insertsPerThread = 10000; + var expected1 = new List>(); + var expected2 = new List>(); + 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 = new Address("queue", "machine"), + Time = DateTime.UtcNow.AddSeconds(RandomProvider.GetThreadRandom().Next(1, 20)), + OwningTimeoutManager = string.Empty, + }; + persister.Add(td); + expected1.Add(new Tuple(td.Id, td.Time)); + lastExpectedTimeout = (td.Time > lastExpectedTimeout) ? td.Time : lastExpectedTimeout; + } + finishedAdding1 = true; + Console.WriteLine("*** Finished adding ***"); + }).Start(); + + new Thread(() => + { + using (var store = new DocumentStore + { + Url = "http://localhost:8080", + DefaultDatabase = db, + }.Initialize()) + { + var persister2 = new RavenTimeoutPersistence(new StoreAccessor(store)); + + var sagaId = Guid.NewGuid(); + for (var i = 0; i < insertsPerThread; i++) + { + var td = new TimeoutData + { + SagaId = sagaId, + Destination = new Address("queue", "machine"), + Time = DateTime.UtcNow.AddSeconds(RandomProvider.GetThreadRandom().Next(1, 20)), + OwningTimeoutManager = string.Empty, + }; + persister2.Add(td); + expected2.Add(new Tuple(td.Id, td.Time)); + 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; + TimeoutData tempTd; + while (!finishedAdding1 || !finishedAdding2 || startSlice < lastExpectedTimeout) + { + DateTime nextRetrieval; + var timeoutDatas = persister.GetNextChunk(startSlice, out nextRetrieval); + foreach (var timeoutData in timeoutDatas) + { + if (startSlice < timeoutData.Item2) + { + startSlice = timeoutData.Item2; + } + + Assert.IsTrue(persister.TryRemove(timeoutData.Item1, out tempTd)); // Raven returns duplicates, so we can't assert on this here + 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 = persister.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.IsTrue(persister.TryRemove(tuple.Item1, out tempTd)); + } + + WaitForIndexing(documentStore); + } + + using (var session = documentStore.OpenSession()) + { + var results = session.Query().ToList(); + Assert.AreEqual(0, results.Count); + } + + Assert.AreEqual(expected1.Count + expected2.Count, found); + } + + IDocumentStore documentStore; + RavenTimeoutPersistence persister; + + [TearDown] + public void TearDown() + { + if (documentStore != null) + documentStore.Dispose(); + } + + static void WaitForIndexing(IDocumentStore store, string db = null, TimeSpan? timeout = null) + { + var databaseCommands = store.DatabaseCommands; + if (db != null) + databaseCommands = databaseCommands.ForDatabase(db); + var spinUntil = SpinWait.SpinUntil(() => databaseCommands.GetStatistics().StaleIndexes.Length == 0, timeout ?? TimeSpan.FromSeconds(20)); + Assert.True(spinUntil); + } + + static class RandomProvider + { + private static int seed = Environment.TickCount; + + private static ThreadLocal randomWrapper = new ThreadLocal(() => + new Random(Interlocked.Increment(ref seed)) + ); + + public static Random GetThreadRandom() + { + return randomWrapper.Value; + } + } + } +} diff --git a/src/NServiceBus.Core.Tests/Timeout/When_pooling_timeouts.cs b/src/NServiceBus.Core.Tests/Timeout/When_pooling_timeouts.cs index 3cdb3b47cc2..5375c456b9d 100644 --- a/src/NServiceBus.Core.Tests/Timeout/When_pooling_timeouts.cs +++ b/src/NServiceBus.Core.Tests/Timeout/When_pooling_timeouts.cs @@ -16,7 +16,6 @@ namespace NServiceBus.Core.Tests.Timeout using Raven.Client.Embedded; [TestFixture] - [Explicit] public class When_pooling_timeouts_with_raven : When_pooling_timeouts { private IDocumentStore store; @@ -37,10 +36,21 @@ public void Cleanup() { store.Dispose(); } + + [Test] + public void Should_retrieve_all_timeout_messages_that_expired_even_if_it_needs_to_page() + { + expected = 1024 + 5; + + Enumerable.Range(1, expected).ToList().ForEach(i => persister.Add(CreateData(DateTime.UtcNow.AddSeconds(-5)))); + + StartAndStopReceiver(5); + + WaitForMessagesThenAssert(5); + } } [TestFixture] - [Explicit] public class When_pooling_timeouts_with_inMemory : When_pooling_timeouts { protected override IPersistTimeouts CreateTimeoutPersister() @@ -54,7 +64,7 @@ public abstract class When_pooling_timeouts private IManageTimeouts manager; private FakeMessageSender messageSender; readonly Random rand = new Random(); - private int expected; + protected int expected; protected IPersistTimeouts persister; protected TimeoutPersisterReceiver receiver; @@ -187,14 +197,14 @@ private void Push(int total, DateTime time) Enumerable.Range(1, total).ToList().ForEach(i => manager.PushTimeout(CreateData(time))); } - private void StartAndStopReceiver(int secondsToWaitBeforeCallingStop = 1) + protected void StartAndStopReceiver(int secondsToWaitBeforeCallingStop = 1) { receiver.Start(); Thread.Sleep(TimeSpan.FromSeconds(secondsToWaitBeforeCallingStop)); receiver.Stop(); } - private static TimeoutData CreateData(DateTime time) + protected static TimeoutData CreateData(DateTime time) { return new TimeoutData { @@ -204,7 +214,7 @@ private static TimeoutData CreateData(DateTime time) }; } - private void WaitForMessagesThenAssert(int maxSecondsToWait) + protected void WaitForMessagesThenAssert(int maxSecondsToWait) { var maxTime = DateTime.Now.AddSeconds(maxSecondsToWait); @@ -216,4 +226,4 @@ private void WaitForMessagesThenAssert(int maxSecondsToWait) Assert.AreEqual(expected, messageSender.MessagesSent); } } -} \ No newline at end of file +} diff --git a/src/NServiceBus.Core/GitFlowVersion.cs b/src/NServiceBus.Core/GitFlowVersion.cs index bcb3c026e07..477af7c728e 100644 --- a/src/NServiceBus.Core/GitFlowVersion.cs +++ b/src/NServiceBus.Core/GitFlowVersion.cs @@ -7,7 +7,7 @@ static class GitFlowVersion static GitFlowVersion() { var assembly = typeof(GitFlowVersion).Assembly; - var gitFlowVersionInformationType = assembly.GetType("NServiceBus.Core.GitFlowVersionInformation", true); + var gitFlowVersionInformationType = assembly.GetType("GitVersionInformation", true); var fieldInfo = gitFlowVersionInformationType.GetField("AssemblyFileVersion"); var assemblyFileVersion = Version.Parse((string)fieldInfo.GetValue(null)); MajorMinor = assemblyFileVersion.ToString(2); diff --git a/src/NServiceBus.Core/Licensing/TimestampReader.cs b/src/NServiceBus.Core/Licensing/TimestampReader.cs index bd16ed2cdbd..3d2e30cdc21 100644 --- a/src/NServiceBus.Core/Licensing/TimestampReader.cs +++ b/src/NServiceBus.Core/Licensing/TimestampReader.cs @@ -10,9 +10,9 @@ public static DateTime GetBuildTimestamp() { var attribute = (dynamic)Assembly.GetExecutingAssembly() .GetCustomAttributes(false) - .First(x => x.GetType().Name == "TimestampAttribute"); + .First(x => x.GetType().Name == "ReleaseDateAttribute"); - return UniversalDateParser.Parse((string)attribute.Timestamp); + return UniversalDateParser.Parse((string)attribute.OriginalDate); } } } \ No newline at end of file diff --git a/src/NServiceBus.Core/NServiceBus.Core.csproj b/src/NServiceBus.Core/NServiceBus.Core.csproj index 8285ea61427..fd8af0abd9d 100644 --- a/src/NServiceBus.Core/NServiceBus.Core.csproj +++ b/src/NServiceBus.Core/NServiceBus.Core.csproj @@ -655,6 +655,5 @@ - - + \ No newline at end of file diff --git a/src/NServiceBus.Core/Persistence/Raven/TimeoutPersister/RavenTimeoutPersistence.cs b/src/NServiceBus.Core/Persistence/Raven/TimeoutPersister/RavenTimeoutPersistence.cs index 87afe2a787e..a4a59fa43ea 100644 --- a/src/NServiceBus.Core/Persistence/Raven/TimeoutPersister/RavenTimeoutPersistence.cs +++ b/src/NServiceBus.Core/Persistence/Raven/TimeoutPersister/RavenTimeoutPersistence.cs @@ -14,9 +14,47 @@ public class RavenTimeoutPersistence : IPersistTimeouts { readonly IDocumentStore store; - public RavenTimeoutPersistence(StoreAccessor storeAccessor) + public TimeSpan CleanupGapFromTimeslice { get; set; } + public TimeSpan TriggerCleanupEvery { get; set; } + DateTime lastCleanupTime = DateTime.MinValue; + + public RavenTimeoutPersistence(StoreAccessor storeAccessor) { store = storeAccessor.Store; + TriggerCleanupEvery = TimeSpan.FromMinutes(2); + CleanupGapFromTimeslice = TimeSpan.FromMinutes(1); + } + + private static IRavenQueryable GetChunkQuery(IDocumentSession session) + { + session.Advanced.AllowNonAuthoritativeInformation = true; + return session.Query() + .OrderBy(t => t.Time) + .Where( + t => + t.OwningTimeoutManager == String.Empty || + t.OwningTimeoutManager == Configure.EndpointName); + } + + public IEnumerable> GetCleanupChunk(DateTime startSlice) + { + using (var session = OpenSession()) + { + var chunk = GetChunkQuery(session) + .Where(t => t.Time <= startSlice.Subtract(CleanupGapFromTimeslice)) + .Select(t => new + { + t.Id, + t.Time + }) + .Take(1024) + .ToList() + .Select(arg => new Tuple(arg.Id, arg.Time)); + + lastCleanupTime = DateTime.UtcNow; + + return chunk; + } } public List> GetNextChunk(DateTime startSlice, out DateTime nextTimeToRunQuery) @@ -24,28 +62,31 @@ public List> GetNextChunk(DateTime startSlice, out DateT try { var now = DateTime.UtcNow; - var skip = 0; var results = new List>(); + + // Allow for occasionally cleaning up old timeouts for edge cases where timeouts have been + // added after startSlice have been set to a later timout and we might have missed them + // because of stale indexes. + if (lastCleanupTime.Add(TriggerCleanupEvery) > now || lastCleanupTime == DateTime.MinValue) + { + results.AddRange(GetCleanupChunk(startSlice)); + } + + var skip = 0; var numberOfRequestsExecutedSoFar = 0; RavenQueryStatistics stats; - do { using (var session = OpenSession()) { session.Advanced.AllowNonAuthoritativeInformation = true; - var query = session.Query() + var query = GetChunkQuery(session) .Where( t => - t.OwningTimeoutManager == String.Empty || - t.OwningTimeoutManager == Configure.EndpointName) - .Where( - t => - t.Time > startSlice && + t.Time > startSlice && t.Time <= now) - .OrderBy(t => t.Time) - .Select(t => new {t.Id, t.Time}) + .Select(t => new { t.Id, t.Time }) .Statistics(out stats); do { @@ -61,33 +102,29 @@ public List> GetNextChunk(DateTime startSlice, out DateT } } while (skip < stats.TotalResults); - using (var session = OpenSession()) + // Set next execution to be now if we received stale results. + // Delay the next execution a bit if we results weren't stale and we got the full chunk. + if (stats.IsStale) { - session.Advanced.AllowNonAuthoritativeInformation = true; - - //Retrieve next time we need to run query - var startOfNextChunk = - session.Query() - .Where( - t => - t.OwningTimeoutManager == String.Empty || - t.OwningTimeoutManager == Configure.EndpointName) - .Where(t => t.Time > now) - .OrderBy(t => t.Time) - .Select(t => new {t.Id, t.Time}) - .FirstOrDefault(); - - if (startOfNextChunk != null) - { - nextTimeToRunQuery = startOfNextChunk.Time; - } - else + nextTimeToRunQuery = now; + } + else + { + using (var session = OpenSession()) { - nextTimeToRunQuery = DateTime.UtcNow.AddMinutes(10); + var beginningOfNextChunk = GetChunkQuery(session) + .Where(t => t.Time > now) + .Take(1) + .Select(t => t.Time) + .FirstOrDefault(); + + nextTimeToRunQuery = (beginningOfNextChunk == default(DateTime)) + ? DateTime.UtcNow.AddMinutes(10) + : beginningOfNextChunk.ToUniversalTime(); } - - return results; } + + return results; } catch (WebException ex) { @@ -114,9 +151,6 @@ public bool TryRemove(string timeoutId, out TimeoutData timeoutData) if (timeoutData == null) return false; - timeoutData.Time = DateTime.UtcNow.AddYears(-1); - session.SaveChanges(); - session.Delete(timeoutData); session.SaveChanges(); diff --git a/src/NServiceBus.Distributor.MSMQ/NServiceBus.Distributor.MSMQ.csproj b/src/NServiceBus.Distributor.MSMQ/NServiceBus.Distributor.MSMQ.csproj index b5a65bc63da..ab66c5e5b08 100644 --- a/src/NServiceBus.Distributor.MSMQ/NServiceBus.Distributor.MSMQ.csproj +++ b/src/NServiceBus.Distributor.MSMQ/NServiceBus.Distributor.MSMQ.csproj @@ -95,5 +95,5 @@ - + \ No newline at end of file diff --git a/src/NServiceBus.Hosting.Windows/NServiceBus.Hosting.Windows.csproj b/src/NServiceBus.Hosting.Windows/NServiceBus.Hosting.Windows.csproj index 2e142ffdde0..6eabba9a294 100644 --- a/src/NServiceBus.Hosting.Windows/NServiceBus.Hosting.Windows.csproj +++ b/src/NServiceBus.Hosting.Windows/NServiceBus.Hosting.Windows.csproj @@ -180,5 +180,5 @@ - + \ No newline at end of file diff --git a/src/NServiceBus.Serializers.XML.XsdGenerator/NServiceBus.Serializers.XML.XsdGenerator.csproj b/src/NServiceBus.Serializers.XML.XsdGenerator/NServiceBus.Serializers.XML.XsdGenerator.csproj index dcae3f3b1cd..57918d64760 100644 --- a/src/NServiceBus.Serializers.XML.XsdGenerator/NServiceBus.Serializers.XML.XsdGenerator.csproj +++ b/src/NServiceBus.Serializers.XML.XsdGenerator/NServiceBus.Serializers.XML.XsdGenerator.csproj @@ -88,5 +88,5 @@ - + \ No newline at end of file diff --git a/src/NServiceBus.Testing/NServiceBus.Testing.csproj b/src/NServiceBus.Testing/NServiceBus.Testing.csproj index a83f8f2a19e..235e7484092 100644 --- a/src/NServiceBus.Testing/NServiceBus.Testing.csproj +++ b/src/NServiceBus.Testing/NServiceBus.Testing.csproj @@ -98,5 +98,5 @@ - + \ No newline at end of file diff --git a/src/NServiceBus/NServiceBus.csproj b/src/NServiceBus/NServiceBus.csproj index 5042772d6d7..61e4fd6f2a6 100644 --- a/src/NServiceBus/NServiceBus.csproj +++ b/src/NServiceBus/NServiceBus.csproj @@ -131,5 +131,5 @@ - + \ No newline at end of file diff --git a/src/NServiceBus/NServiceBusVersion.cs b/src/NServiceBus/NServiceBusVersion.cs index 023e2522637..a26134182a1 100644 --- a/src/NServiceBus/NServiceBusVersion.cs +++ b/src/NServiceBus/NServiceBusVersion.cs @@ -10,7 +10,7 @@ public static class NServiceBusVersion static NServiceBusVersion() { var assembly = typeof(NServiceBusVersion).Assembly; - var gitFlowVersionInformationType = assembly.GetType("NServiceBus.GitFlowVersionInformation", true); + var gitFlowVersionInformationType = assembly.GetType("GitVersionInformation", true); var fieldInfo = gitFlowVersionInformationType.GetField("AssemblyFileVersion"); var assemblyFileVersion = System.Version.Parse((string)fieldInfo.GetValue(null)); Version = assemblyFileVersion.ToString(3); diff --git a/src/ObjectBuilder.Autofac/ObjectBuilder.Autofac.csproj b/src/ObjectBuilder.Autofac/ObjectBuilder.Autofac.csproj index 032b484c054..76f2ae8ff7e 100644 --- a/src/ObjectBuilder.Autofac/ObjectBuilder.Autofac.csproj +++ b/src/ObjectBuilder.Autofac/ObjectBuilder.Autofac.csproj @@ -103,5 +103,5 @@ - + \ No newline at end of file diff --git a/src/ObjectBuilder.CastleWindsor/ObjectBuilder.CastleWindsor.csproj b/src/ObjectBuilder.CastleWindsor/ObjectBuilder.CastleWindsor.csproj index 81668a8bd21..7974f540d08 100644 --- a/src/ObjectBuilder.CastleWindsor/ObjectBuilder.CastleWindsor.csproj +++ b/src/ObjectBuilder.CastleWindsor/ObjectBuilder.CastleWindsor.csproj @@ -109,5 +109,5 @@ - + \ No newline at end of file diff --git a/src/ObjectBuilder.Ninject/ObjectBuilder.Ninject.csproj b/src/ObjectBuilder.Ninject/ObjectBuilder.Ninject.csproj index f220990f50d..ee7c94d5792 100644 --- a/src/ObjectBuilder.Ninject/ObjectBuilder.Ninject.csproj +++ b/src/ObjectBuilder.Ninject/ObjectBuilder.Ninject.csproj @@ -93,5 +93,5 @@ - + \ No newline at end of file diff --git a/src/ObjectBuilder.Spring/ObjectBuilder.Spring.csproj b/src/ObjectBuilder.Spring/ObjectBuilder.Spring.csproj index 1ec3a76a819..a938f074c7f 100644 --- a/src/ObjectBuilder.Spring/ObjectBuilder.Spring.csproj +++ b/src/ObjectBuilder.Spring/ObjectBuilder.Spring.csproj @@ -87,5 +87,5 @@ - + \ No newline at end of file diff --git a/src/ObjectBuilder.StructureMap/ObjectBuilder.StructureMap.csproj b/src/ObjectBuilder.StructureMap/ObjectBuilder.StructureMap.csproj index 0c44623717f..6452fd62b37 100644 --- a/src/ObjectBuilder.StructureMap/ObjectBuilder.StructureMap.csproj +++ b/src/ObjectBuilder.StructureMap/ObjectBuilder.StructureMap.csproj @@ -102,5 +102,5 @@ - + \ No newline at end of file diff --git a/src/ObjectBuilder.Unity/ObjectBuilder.Unity.csproj b/src/ObjectBuilder.Unity/ObjectBuilder.Unity.csproj index df28e9ae9d7..73c465eb07b 100644 --- a/src/ObjectBuilder.Unity/ObjectBuilder.Unity.csproj +++ b/src/ObjectBuilder.Unity/ObjectBuilder.Unity.csproj @@ -99,5 +99,5 @@ - + \ No newline at end of file diff --git a/src/ReturnToSourceQueue/ReturnToSourceQueue.csproj b/src/ReturnToSourceQueue/ReturnToSourceQueue.csproj index e20567e08f9..4826e528f2d 100644 --- a/src/ReturnToSourceQueue/ReturnToSourceQueue.csproj +++ b/src/ReturnToSourceQueue/ReturnToSourceQueue.csproj @@ -90,5 +90,5 @@ - + \ No newline at end of file diff --git a/src/licenseinstaller/LicenseInstaller.csproj b/src/licenseinstaller/LicenseInstaller.csproj index eb966f9d263..e4f2d4cb02e 100644 --- a/src/licenseinstaller/LicenseInstaller.csproj +++ b/src/licenseinstaller/LicenseInstaller.csproj @@ -56,5 +56,5 @@ - + \ No newline at end of file