private void RunLoop()
{
if (Interlocked.CompareExchange(ref status, Status.Started, Status.Starting) != Status.Starting) return;
Interlocked.Increment(ref timesStarted);
try
{
//RESET
while (Interlocked.CompareExchange(ref status, 0, 0) == Status.Started)
{
using (var redis = ClientsManager.GetReadOnlyClient())
{
masterClient = redis;
//Record that we had a good run...
Interlocked.CompareExchange(ref noOfContinuousErrors, 0, noOfContinuousErrors);
using (var subscription = redis.CreateSubscription())
{
subscription.OnUnSubscribe = HandleUnSubscribe;
subscription.OnMessage = (channel, msg) =>
{
if (string.IsNullOrEmpty(msg))
return;
var ctrlMsg = msg.SplitOnFirst(':');
if (ctrlMsg[0] == ControlCommand.Control)
{
var op = Interlocked.CompareExchange(ref doOperation, Operation.NoOp, doOperation);
var msgType = ctrlMsg.Length > 1
? ctrlMsg[1]
: null;
if (OnControlCommand != null)
OnControlCommand(msgType ?? Operation.GetName(op));
switch (op)
{
case Operation.Stop:
if (Log.IsDebugEnabled)
Log.Debug("Stop Command Issued");
Interlocked.CompareExchange(ref status, Status.Stopping, Status.Started);
try
{
if (Log.IsDebugEnabled)
Log.Debug("UnSubscribe From All Channels...");
subscription.UnSubscribeFromAllChannels(); //Un block thread.
}
finally
{
Interlocked.CompareExchange(ref status, Status.Stopped, Status.Stopping);
}
return;
case Operation.Reset:
subscription.UnSubscribeFromAllChannels(); //Un block thread.
return;
}
switch (msgType)
{
case ControlCommand.Pulse:
Pulse();
break;
}
}
else
{
OnMessage(channel, msg);
}
};
//blocks thread
if (ChannelsMatching != null && ChannelsMatching.Length > 0)
subscription.SubscribeToChannelsMatching(ChannelsMatching);
else
subscription.SubscribeToChannels(Channels);
masterClient = null;
}
}
}
if (OnStop != null)
OnStop();
}
catch (Exception ex)
{
lastExMsg = ex.Message;
Interlocked.Increment(ref noOfErrors);
Interlocked.Increment(ref noOfContinuousErrors);
if (Interlocked.CompareExchange(ref status, Status.Stopped, Status.Started) != Status.Started)
Interlocked.CompareExchange(ref status, Status.Stopped, Status.Stopping);
if (OnStop != null)
OnStop();
if (this.OnError != null)
this.OnError(ex);
}
if (AutoRestart && Interlocked.CompareExchange(ref status, 0, 0) != Status.Disposed)
{
if (WaitBeforeNextRestart != null)
TaskUtils.Sleep(WaitBeforeNextRestart.Value);
Start();
}
}