Skip to content

Commit a583614

Browse files
author
John Simons
committed
Merge branch 'hotfix-4.5.2'
2 parents 960fc08 + 48eec98 commit a583614

22 files changed

+378
-85
lines changed

buildsupport/GitVersionTask/Build/GitVersionTask.targets

+24-21
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
<PropertyGroup>
44
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">$(MSBuildProjectDirectory)..\</SolutionDir>
55
</PropertyGroup>
6+
<PropertyGroup>
7+
<GitVersionAppendRevision Condition="$(GitVersionAppendRevision) == '' Or $(GitVersionAppendRevision) == '*Undefined*'">false</GitVersionAppendRevision>
8+
</PropertyGroup>
69

710
<UsingTask
811
TaskName="GitVersionTask.UpdateAssemblyInfo"
@@ -11,33 +14,33 @@
1114
TaskName="GitVersionTask.WriteVersionInfoToBuildLog"
1215
AssemblyFile="$(MSBuildThisFileDirectory)..\GitVersionTask.dll" />
1316

14-
<Target Name="UpdateAssemblyInfo"
15-
BeforeTargets="CoreCompile">
16-
<WriteVersionInfoToBuildLog
17-
SolutionDirectory="$(SolutionDir)"
17+
<Target Name="UpdateAssemblyInfo"
18+
BeforeTargets="CoreCompile">
19+
<WriteVersionInfoToBuildLog
20+
SolutionDirectory="$(SolutionDir)"
1821
/>
19-
<UpdateAssemblyInfo
20-
SolutionDirectory="$(SolutionDir)"
21-
AssemblyName="$(AssemblyName)"
22-
ProjectFile="$(ProjectPath)"
23-
SignAssembly="$(SignAssembly)"
24-
CompileFiles ="@(Compile)">
25-
<Output
26-
TaskParameter="AssemblyInfoTempFilePath"
27-
PropertyName="AssemblyInfoTempFilePath" />
28-
</UpdateAssemblyInfo>
29-
30-
<ItemGroup>
31-
<Compile Include="$(AssemblyInfoTempFilePath)" />
32-
</ItemGroup>
33-
</Target>
22+
<UpdateAssemblyInfo
23+
SolutionDirectory="$(SolutionDir)"
24+
ProjectFile="$(ProjectPath)"
25+
AppendRevision="$(GitVersionAppendRevision)"
26+
AssemblyVersioningScheme="MajorMinor"
27+
CompileFiles ="@(Compile)">
28+
<Output
29+
TaskParameter="AssemblyInfoTempFilePath"
30+
PropertyName="AssemblyInfoTempFilePath" />
31+
</UpdateAssemblyInfo>
32+
33+
<ItemGroup>
34+
<Compile Include="$(AssemblyInfoTempFilePath)" />
35+
</ItemGroup>
36+
</Target>
3437

3538
<!--Support for ncrunch-->
3639
<ItemGroup>
3740
<None Include="$(MSBuildThisFileDirectory)..\GitVersionTask.dll" />
3841
<None Include="$(MSBuildThisFileDirectory)..\GitVersionTask.pdb" />
39-
<None Include="$(MSBuildThisFileDirectory)..\GitVersion.exe" />
40-
<None Include="$(MSBuildThisFileDirectory)..\GitVersion.pdb" />
42+
<None Include="$(MSBuildThisFileDirectory)..\GitVersionCore.dll" />
43+
<None Include="$(MSBuildThisFileDirectory)..\GitVersionCore.pdb" />
4144
<None Include="$(MSBuildThisFileDirectory)..\LibGit2Sharp.dll" />
4245
<None Include="$(MSBuildThisFileDirectory)..\NativeBinaries\**\*" />
4346
</ItemGroup>
-57 KB
Binary file not shown.
69.5 KB
Binary file not shown.
512 Bytes
Binary file not shown.
11 KB
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
-623 KB
Binary file not shown.

buildsupport/PepitaPackage.dll

-14.5 KB
Binary file not shown.

buildsupport/RippleRestoreTask.dll

0 Bytes
Binary file not shown.

ripple.config

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0"?>
2-
<ripple xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
2+
<ripple xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
33
<Name>NServiceBus</Name>
44
<NugetSpecFolder>packaging/nuget</NugetSpecFolder>
55
<SourceFolder>src</SourceFolder>

src/NServiceBus.Core.Tests/Licensing/UserSidCheckerTests.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
namespace NServiceBus.Core.Tests.Licensing
22
{
3-
using NServiceBus.Licensing;
43
using NUnit.Framework;
4+
using Particular.Licensing;
55

66
[TestFixture]
77
public class UserSidCheckerTests

src/NServiceBus.Core.Tests/NServiceBus.Core.Tests.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@
252252
<Compile Include="Serializers\XML\SomeEnum.cs" />
253253
<Compile Include="Serializers\XML\Using_Infer_Type_With_Non_Nested_Class.cs" />
254254
<Compile Include="Timeout\FakeMessageSender.cs" />
255+
<Compile Include="Timeout\RavenTimeoutPersisterTests.cs" />
255256
<Compile Include="Timeout\When_fetching_timeouts_from_storage.cs" />
256257
<Compile Include="Timeout\When_pooling_timeouts.cs" />
257258
<Compile Include="Timeout\When_receiving_timeouts.cs" />
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
1+
namespace NServiceBus.Core.Tests.Timeout
2+
{
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Threading;
7+
using NServiceBus.Persistence.Raven;
8+
using NServiceBus.Persistence.Raven.TimeoutPersister;
9+
using NServiceBus.Timeout.Core;
10+
using NUnit.Framework;
11+
using Raven.Client;
12+
using Raven.Client.Document;
13+
14+
[TestFixture]
15+
public class RavenTimeoutPersisterTests
16+
{
17+
[TestCase, Repeat(200)]
18+
public void Should_not_skip_timeouts()
19+
{
20+
var db = Guid.NewGuid().ToString();
21+
documentStore = new DocumentStore
22+
{
23+
Url = "http://localhost:8080",
24+
DefaultDatabase = db,
25+
}.Initialize();
26+
persister = new RavenTimeoutPersistence(new StoreAccessor(documentStore))
27+
{
28+
TriggerCleanupEvery = TimeSpan.FromHours(1), // Make sure cleanup doesn't run automatically
29+
};
30+
31+
var startSlice = DateTime.UtcNow.AddYears(-10);
32+
// avoid cleanup from running during the test by making it register as being run
33+
Assert.AreEqual(0, persister.GetCleanupChunk(startSlice).Count());
34+
35+
var expected = new List<Tuple<string, DateTime>>();
36+
var lastExpectedTimeout = DateTime.UtcNow;
37+
var finishedAdding = false;
38+
39+
new Thread(() =>
40+
{
41+
var sagaId = Guid.NewGuid();
42+
for (var i = 0; i < 10000; i++)
43+
{
44+
var td = new TimeoutData
45+
{
46+
SagaId = sagaId,
47+
Destination = new Address("queue", "machine"),
48+
Time = DateTime.UtcNow.AddSeconds(RandomProvider.GetThreadRandom().Next(5, 20)),
49+
OwningTimeoutManager = string.Empty,
50+
};
51+
persister.Add(td);
52+
expected.Add(new Tuple<string, DateTime>(td.Id, td.Time));
53+
lastExpectedTimeout = (td.Time > lastExpectedTimeout) ? td.Time : lastExpectedTimeout;
54+
}
55+
finishedAdding = true;
56+
Console.WriteLine("*** Finished adding ***");
57+
}).Start();
58+
59+
// Mimic the behavior of the TimeoutPersister coordinator
60+
var found = 0;
61+
TimeoutData tempTd;
62+
while (!finishedAdding || startSlice < lastExpectedTimeout)
63+
{
64+
DateTime nextRetrieval;
65+
var timeoutDatas = persister.GetNextChunk(startSlice, out nextRetrieval);
66+
foreach (var timeoutData in timeoutDatas)
67+
{
68+
if (startSlice < timeoutData.Item2)
69+
{
70+
startSlice = timeoutData.Item2;
71+
}
72+
73+
Assert.IsTrue(persister.TryRemove(timeoutData.Item1, out tempTd));
74+
found++;
75+
}
76+
}
77+
78+
WaitForIndexing(documentStore);
79+
80+
// If the persister reports stale results have been seen at one point during its normal operation,
81+
// we need to perform manual cleaup.
82+
while (true)
83+
{
84+
var chunkToCleanup = persister.GetCleanupChunk(DateTime.UtcNow.AddDays(1)).ToArray();
85+
Console.WriteLine("Cleanup: got a chunk of size " + chunkToCleanup.Length);
86+
if (chunkToCleanup.Length == 0) break;
87+
88+
found += chunkToCleanup.Length;
89+
foreach (var tuple in chunkToCleanup)
90+
{
91+
Assert.IsTrue(persister.TryRemove(tuple.Item1, out tempTd));
92+
}
93+
94+
WaitForIndexing(documentStore);
95+
}
96+
97+
using (var session = documentStore.OpenSession())
98+
{
99+
var results = session.Query<TimeoutData>().ToList();
100+
Assert.AreEqual(0, results.Count);
101+
}
102+
103+
Assert.AreEqual(expected.Count, found);
104+
}
105+
106+
[TestCase, Repeat(200)]
107+
public void Should_not_skip_timeouts_also_with_multiple_clients_adding_timeouts()
108+
{
109+
var db = Guid.NewGuid().ToString();
110+
documentStore = new DocumentStore
111+
{
112+
Url = "http://localhost:8080",
113+
DefaultDatabase = db,
114+
}.Initialize();
115+
persister = new RavenTimeoutPersistence(new StoreAccessor(documentStore))
116+
{
117+
TriggerCleanupEvery = TimeSpan.FromDays(1), // Make sure cleanup doesn't run automatically
118+
};
119+
120+
var startSlice = DateTime.UtcNow.AddYears(-10);
121+
// avoid cleanup from running during the test by making it register as being run
122+
Assert.AreEqual(0, persister.GetCleanupChunk(startSlice).Count());
123+
124+
const int insertsPerThread = 10000;
125+
var expected1 = new List<Tuple<string, DateTime>>();
126+
var expected2 = new List<Tuple<string, DateTime>>();
127+
var lastExpectedTimeout = DateTime.UtcNow;
128+
var finishedAdding1 = false;
129+
var finishedAdding2 = false;
130+
131+
new Thread(() =>
132+
{
133+
var sagaId = Guid.NewGuid();
134+
for (var i = 0; i < insertsPerThread; i++)
135+
{
136+
var td = new TimeoutData
137+
{
138+
SagaId = sagaId,
139+
Destination = new Address("queue", "machine"),
140+
Time = DateTime.UtcNow.AddSeconds(RandomProvider.GetThreadRandom().Next(1, 20)),
141+
OwningTimeoutManager = string.Empty,
142+
};
143+
persister.Add(td);
144+
expected1.Add(new Tuple<string, DateTime>(td.Id, td.Time));
145+
lastExpectedTimeout = (td.Time > lastExpectedTimeout) ? td.Time : lastExpectedTimeout;
146+
}
147+
finishedAdding1 = true;
148+
Console.WriteLine("*** Finished adding ***");
149+
}).Start();
150+
151+
new Thread(() =>
152+
{
153+
using (var store = new DocumentStore
154+
{
155+
Url = "http://localhost:8080",
156+
DefaultDatabase = db,
157+
}.Initialize())
158+
{
159+
var persister2 = new RavenTimeoutPersistence(new StoreAccessor(store));
160+
161+
var sagaId = Guid.NewGuid();
162+
for (var i = 0; i < insertsPerThread; i++)
163+
{
164+
var td = new TimeoutData
165+
{
166+
SagaId = sagaId,
167+
Destination = new Address("queue", "machine"),
168+
Time = DateTime.UtcNow.AddSeconds(RandomProvider.GetThreadRandom().Next(1, 20)),
169+
OwningTimeoutManager = string.Empty,
170+
};
171+
persister2.Add(td);
172+
expected2.Add(new Tuple<string, DateTime>(td.Id, td.Time));
173+
lastExpectedTimeout = (td.Time > lastExpectedTimeout) ? td.Time : lastExpectedTimeout;
174+
}
175+
}
176+
finishedAdding2 = true;
177+
Console.WriteLine("*** Finished adding via a second client connection ***");
178+
}).Start();
179+
180+
// Mimic the behavior of the TimeoutPersister coordinator
181+
var found = 0;
182+
TimeoutData tempTd;
183+
while (!finishedAdding1 || !finishedAdding2 || startSlice < lastExpectedTimeout)
184+
{
185+
DateTime nextRetrieval;
186+
var timeoutDatas = persister.GetNextChunk(startSlice, out nextRetrieval);
187+
foreach (var timeoutData in timeoutDatas)
188+
{
189+
if (startSlice < timeoutData.Item2)
190+
{
191+
startSlice = timeoutData.Item2;
192+
}
193+
194+
Assert.IsTrue(persister.TryRemove(timeoutData.Item1, out tempTd)); // Raven returns duplicates, so we can't assert on this here
195+
found++;
196+
}
197+
}
198+
199+
WaitForIndexing(documentStore);
200+
201+
// If the persister reports stale results have been seen at one point during its normal operation,
202+
// we need to perform manual cleaup.
203+
while (true)
204+
{
205+
var chunkToCleanup = persister.GetCleanupChunk(DateTime.UtcNow.AddDays(1)).ToArray();
206+
Console.WriteLine("Cleanup: got a chunk of size " + chunkToCleanup.Length);
207+
if (chunkToCleanup.Length == 0) break;
208+
209+
found += chunkToCleanup.Length;
210+
foreach (var tuple in chunkToCleanup)
211+
{
212+
Assert.IsTrue(persister.TryRemove(tuple.Item1, out tempTd));
213+
}
214+
215+
WaitForIndexing(documentStore);
216+
}
217+
218+
using (var session = documentStore.OpenSession())
219+
{
220+
var results = session.Query<TimeoutData>().ToList();
221+
Assert.AreEqual(0, results.Count);
222+
}
223+
224+
Assert.AreEqual(expected1.Count + expected2.Count, found);
225+
}
226+
227+
IDocumentStore documentStore;
228+
RavenTimeoutPersistence persister;
229+
230+
[TearDown]
231+
public void TearDown()
232+
{
233+
if (documentStore != null)
234+
documentStore.Dispose();
235+
}
236+
237+
static void WaitForIndexing(IDocumentStore store, string db = null, TimeSpan? timeout = null)
238+
{
239+
var databaseCommands = store.DatabaseCommands;
240+
if (db != null)
241+
databaseCommands = databaseCommands.ForDatabase(db);
242+
var spinUntil = SpinWait.SpinUntil(() => databaseCommands.GetStatistics().StaleIndexes.Length == 0, timeout ?? TimeSpan.FromSeconds(20));
243+
Assert.True(spinUntil);
244+
}
245+
246+
static class RandomProvider
247+
{
248+
private static int seed = Environment.TickCount;
249+
250+
private static ThreadLocal<Random> randomWrapper = new ThreadLocal<Random>(() =>
251+
new Random(Interlocked.Increment(ref seed))
252+
);
253+
254+
public static Random GetThreadRandom()
255+
{
256+
return randomWrapper.Value;
257+
}
258+
}
259+
}
260+
}

0 commit comments

Comments
 (0)