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