Skip to content

Commit fde133e

Browse files
author
John Simons
committed
Merge branch 'release-1.11'
2 parents fe32196 + 690652b commit fde133e

File tree

14 files changed

+159
-87
lines changed

14 files changed

+159
-87
lines changed

src/ServiceControl.AcceptanceTesting/Support/ScenarioRunner.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,7 @@ static void PerformScenarios(RunDescriptor runDescriptor, IEnumerable<ActiveRunn
253253
var startTime = DateTime.UtcNow;
254254
var maxTime = runDescriptor.TestExecutionTimeout;
255255

256-
Task.WaitAll(endpoints.Select(endpoint => Task.Factory.StartNew(() => SpinWait.SpinUntil(done, maxTime))).Cast<Task>().ToArray(), maxTime);
256+
Task.WaitAll(Task.Run(() => SpinWait.SpinUntil(done, maxTime)));
257257

258258
try
259259
{

src/ServiceControl.AcceptanceTests/Contexts/TransportIntegration/MsmqTransportIntegration.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ static void DeleteQueues(string name)
4141
if (messageQueue.QueueName.StartsWith(nameFilter, StringComparison.OrdinalIgnoreCase))
4242
{
4343
queuesToBeDeleted.Add(messageQueue.Path);
44+
Console.WriteLine("Deleted '{0}' queue", messageQueue.Path);
4445
}
4546
}
4647
}

src/ServiceControl/Bootstrapper.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ public Bootstrapper(ServiceBase host = null, HostArguments hostArguments = null,
6666
configuration.DisableFeature<Audit>();
6767
configuration.DisableFeature<AutoSubscribe>();
6868
configuration.DisableFeature<SecondLevelRetries>();
69+
configuration.DisableFeature<TimeoutManager>();
6970

7071
configuration.UseSerialization<JsonSerializer>();
7172

Lines changed: 81 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,28 @@
11
namespace ServiceControl.HeartbeatMonitoring
22
{
33
using System;
4-
using Contracts.HeartbeatMonitoring;
4+
using System.Linq;
55
using Contracts.Operations;
66
using Infrastructure;
77
using NServiceBus;
8-
using NServiceBus.Logging;
98
using Plugin.Heartbeat.Messages;
9+
using Raven.Abstractions.Data;
1010
using Raven.Client;
11+
using Raven.Json.Linq;
12+
using ServiceControl.Contracts.HeartbeatMonitoring;
1113

1214
class SaveHeartbeatHandler : IHandleMessages<EndpointHeartbeat>
1315
{
14-
public IDocumentSession Session { get; set; }
15-
public IBus Bus { get; set; }
16-
public HeartbeatStatusProvider HeartbeatStatusProvider { get; set; }
16+
private readonly IBus bus;
17+
private readonly HeartbeatStatusProvider statusProvider;
18+
private readonly IDocumentStore store;
19+
20+
public SaveHeartbeatHandler(IBus bus, HeartbeatStatusProvider statusProvider, IDocumentStore store)
21+
{
22+
this.bus = bus;
23+
this.statusProvider = statusProvider;
24+
this.store = store;
25+
}
1726

1827
public void Handle(EndpointHeartbeat message)
1928
{
@@ -31,69 +40,95 @@ public void Handle(EndpointHeartbeat message)
3140
{
3241
throw new Exception("Received an EndpointHeartbeat message without proper initialization of the HostId in the schema");
3342
}
34-
43+
3544

3645
var id = DeterministicGuid.MakeId(message.EndpointName, message.HostId.ToString());
46+
var key = store.Conventions.DefaultFindFullDocumentKeyFromNonStringIdentifier(id, typeof(Heartbeat), false);
3747

38-
var heartbeat = Session.Load<Heartbeat>(id);
39-
40-
if (heartbeat != null)
48+
var endpointDetails = new EndpointDetails
4149
{
42-
if (heartbeat.Disabled)
43-
{
44-
return;
45-
}
46-
}
50+
HostId = message.HostId,
51+
Host = message.Host,
52+
Name = message.EndpointName
53+
};
4754

48-
var isNew = false;
55+
var patchResult = store.DatabaseCommands.Patch(key, new ScriptedPatchRequest
56+
{
57+
Script = @"
58+
if(new Date(lastReported) <= new Date(this.LastReportAt)) {
59+
return;
60+
}
4961
50-
if (heartbeat == null)
62+
if(this.ReportedStatus === deadStatus) {
63+
output('wasDead');
64+
}
65+
this.LastReportAt = lastReported;
66+
this.ReportedStatus = reportedStatus;
67+
",
68+
Values =
69+
{
70+
{"lastReported", message.ExecutedAt},
71+
{"reportedStatus", (int) Status.Beating},
72+
{"deadStatus", (int) Status.Dead},
73+
}
74+
}, new ScriptedPatchRequest
5175
{
52-
isNew = true;
53-
heartbeat = new Heartbeat
76+
Script = @"
77+
this.LastReportAt = lastReported;
78+
this.ReportedStatus = reportedStatus;
79+
this.EndpointDetails = {
80+
'Host': endpointDetails_Host,
81+
'HostId': endpointDetails_HostId,
82+
'Name': endpointDetails_Name
83+
};
84+
this.Disabled = false;
85+
output('isNew');
86+
",
87+
Values =
5488
{
55-
Id = id,
56-
ReportedStatus = Status.Beating
57-
};
58-
Session.Store(heartbeat);
59-
}
89+
{"lastReported", message.ExecutedAt},
90+
{"reportedStatus", (int) Status.Beating},
91+
{"endpointDetails_Host", endpointDetails.Host},
92+
{"endpointDetails_HostId", endpointDetails.HostId.ToString()},
93+
{"endpointDetails_Name", endpointDetails.Name}
94+
}
95+
}, RavenJObject.Parse(String.Format(@"
96+
{{
97+
""Raven-Entity-Name"": ""{0}"",
98+
""Raven-Clr-Type"": ""{1}""
99+
}}",
100+
store.Conventions.GetTypeTagName(typeof(Heartbeat)),
101+
typeof(Heartbeat).AssemblyQualifiedName)));
60102

61-
if (message.ExecutedAt <= heartbeat.LastReportAt)
62-
{
63-
Logger.InfoFormat("Out of sync heartbeat received for endpoint {0}", message.EndpointName);
64-
return;
65-
}
103+
var debugStatements = patchResult.Value<RavenJArray>("Debug");
104+
var ravenJToken = debugStatements.SingleOrDefault();
105+
bool isNew = false, wasDead = false;
66106

67-
heartbeat.LastReportAt = message.ExecutedAt;
68-
heartbeat.EndpointDetails = new EndpointDetails
107+
if (ravenJToken != null)
69108
{
70-
HostId = message.HostId,
71-
Host = message.Host,
72-
Name = message.EndpointName
73-
};
109+
var result = ravenJToken.Value<string>();
110+
isNew = result == "isNew";
111+
wasDead = result == "wasDead";
112+
}
74113

75114
if (isNew) // New endpoint heartbeat
76115
{
77-
Bus.Publish(new HeartbeatingEndpointDetected
116+
bus.Publish(new HeartbeatingEndpointDetected
78117
{
79-
Endpoint = heartbeat.EndpointDetails,
80-
DetectedAt = heartbeat.LastReportAt,
118+
Endpoint = endpointDetails,
119+
DetectedAt = message.ExecutedAt
81120
});
82121
}
83-
84-
if (heartbeat.ReportedStatus == Status.Dead)
122+
else if (wasDead)
85123
{
86-
heartbeat.ReportedStatus = Status.Beating;
87-
Bus.Publish(new EndpointHeartbeatRestored
124+
bus.Publish(new EndpointHeartbeatRestored
88125
{
89-
Endpoint = heartbeat.EndpointDetails,
90-
RestoredAt = heartbeat.LastReportAt
126+
Endpoint = endpointDetails,
127+
RestoredAt = message.ExecutedAt
91128
});
92129
}
93130

94-
HeartbeatStatusProvider.RegisterHeartbeatingEndpoint(heartbeat.EndpointDetails, heartbeat.LastReportAt);
131+
statusProvider.RegisterHeartbeatingEndpoint(endpointDetails, message.ExecutedAt);
95132
}
96-
97-
static readonly ILog Logger = LogManager.GetLogger(typeof(SaveHeartbeatHandler));
98133
}
99134
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
namespace ServiceControl.Infrastructure.OWIN
2+
{
3+
using System.Threading.Tasks;
4+
using Microsoft.Owin;
5+
using NServiceBus.Logging;
6+
7+
class LogApiCalls : OwinMiddleware
8+
{
9+
public LogApiCalls(OwinMiddleware next) : base(next) { }
10+
11+
public override async Task Invoke(IOwinContext context)
12+
{
13+
log.DebugFormat("Begin {0}: {1}", context.Request.Method, context.Request.Uri.ToString());
14+
15+
await Next.Invoke(context);
16+
17+
log.DebugFormat("End {0}: {1}", context.Request.Method, context.Request.Uri.ToString());
18+
}
19+
20+
static ILog log = LogManager.GetLogger<LogApiCalls>();
21+
}
22+
}

src/ServiceControl/Infrastructure/OWIN/Startup.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using ServiceControl.Infrastructure.SignalR;
1212
using Autofac;
1313
using Microsoft.AspNet.SignalR.Json;
14+
using ServiceControl.Infrastructure.OWIN;
1415
using JsonNetSerializer = Microsoft.AspNet.SignalR.Json.JsonNetSerializer;
1516

1617
public class Startup
@@ -30,6 +31,8 @@ public void Configuration(IAppBuilder app)
3031
return func();
3132
});
3233

34+
app.Use<LogApiCalls>();
35+
3336
ConfigureSignalR(app);
3437
app.UseNancy(new NancyOptions { Bootstrapper = new NServiceBusContainerBootstrapper() });
3538
}

src/ServiceControl/Infrastructure/TimeKeeper.cs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,23 @@ public class TimeKeeper : IDisposable
1010
ConcurrentDictionary<Timer, object> timers = new ConcurrentDictionary<Timer, object>();
1111
private ILog log = LogManager.GetLogger<TimeKeeper>();
1212

13-
public Timer New(Action callback, TimeSpan dueTime, TimeSpan period)
13+
public Timer NewTimer(Func<bool> callback, TimeSpan dueTime, TimeSpan period)
1414
{
1515
Timer timer = null;
1616

1717
timer = new Timer(_ =>
1818
{
19+
var reschedule = false;
20+
1921
try
2022
{
21-
callback();
23+
reschedule = callback();
2224
}
2325
catch (Exception ex)
2426
{
2527
log.Error("Reoccurring timer task failed.", ex);
2628
}
27-
if (timers.ContainsKey(timer))
29+
if (reschedule && timers.ContainsKey(timer))
2830
{
2931
try
3032
{
@@ -41,6 +43,15 @@ public Timer New(Action callback, TimeSpan dueTime, TimeSpan period)
4143
return timer;
4244
}
4345

46+
public Timer New(Action callback, TimeSpan dueTime, TimeSpan period)
47+
{
48+
return NewTimer(() =>
49+
{
50+
callback();
51+
return true;
52+
}, dueTime, period);
53+
}
54+
4455
public void Release(Timer timer)
4556
{
4657
object _;

src/ServiceControl/Operations/SatelliteImportFailuresHandler.cs

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -36,31 +36,10 @@ public void ProcessingAlwaysFailsForMessage(TransportMessage message, Exception
3636
Handle(e, messageBuilder(message), logPath);
3737
}
3838

39-
public void FailedToReceive(Exception exception)
40-
{
41-
try
42-
{
43-
var id = Guid.NewGuid();
44-
45-
var filePath = Path.Combine(logPath, id + ".txt");
46-
File.WriteAllText(filePath, exception.ToFriendlyString());
47-
WriteEvent("A message import has failed. A log file has been written to " + filePath);
48-
}
49-
finally
50-
{
51-
failureCircuitBreaker.Increment(exception);
52-
}
53-
}
54-
5539
public void Init(Address address)
5640
{
5741
}
5842

59-
public void Log(TransportMessage message, Exception e)
60-
{
61-
DoLogging(e, messageBuilder(message), logPath);
62-
}
63-
6443
void Handle(Exception exception, dynamic failure, string logDirectory)
6544
{
6645
try

src/ServiceControl/Recoverability/Grouping/Archiving/ArchiveAllInGroupHandler.cs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,10 @@ namespace ServiceControl.Recoverability
66
using Raven.Abstractions.Data;
77
using Raven.Abstractions.Extensions;
88
using Raven.Client;
9-
using ServiceControl.Infrastructure;
109
using ServiceControl.MessageFailures;
1110

1211
public class ArchiveAllInGroupHandler : IHandleMessages<ArchiveAllInGroup>
1312
{
14-
private bool abort;
15-
16-
public ArchiveAllInGroupHandler(ShutdownNotifier notifier)
17-
{
18-
notifier.Register(() => { abort = true; });
19-
}
20-
2113
public void Handle(ArchiveAllInGroup message)
2214
{
2315
var result = Session.Advanced.DocumentStore.DatabaseCommands.UpdateByIndex(

src/ServiceControl/Recoverability/Grouping/Retries/RetryAllInGroupHandler.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ namespace ServiceControl.Recoverability
22
{
33
using System.Linq;
44
using NServiceBus;
5+
using NServiceBus.Logging;
56
using Raven.Client;
67

78
public class RetryAllInGroupHandler : IHandleMessages<RetryAllInGroup>
@@ -10,6 +11,7 @@ public void Handle(RetryAllInGroup message)
1011
{
1112
if (Retries == null)
1213
{
14+
log.WarnFormat("Attempt to retry a group ({0}) when retries are disabled", message.GroupId);
1315
return;
1416
}
1517

@@ -28,5 +30,7 @@ public void Handle(RetryAllInGroup message)
2830

2931
public RetriesGateway Retries { get; set; }
3032
public IDocumentSession Session { get; set; }
33+
34+
static ILog log = LogManager.GetLogger(typeof(RetryAllInGroupHandler));
3135
}
3236
}

0 commit comments

Comments
 (0)