internal void SignalLoop()
{
while (true)
{
Thread.Sleep(this.heartbeat.Randomize());
try
{
// Prun any orphans that were abandoned for any reason.
this.PruneOrphans();
WorkerStatus status;
long? recordId = null;
lock (this.statusLocker)
{
status = this.Status;
lock (this.runLocker)
{
if (status == WorkerStatus.Working && this.currentRecord != null)
{
recordId = this.currentRecord.Id;
}
}
}
SignalsRecord signals;
// Load the current signals from the repository.
using (IRepository repository = this.repositoryFactory.Create())
{
using (IDbTransaction transaction = repository.BeginTransaction())
{
signals = repository.GetWorkingSignals(this.id, recordId, transaction);
if (signals != null
&& (signals.WorkerSignal != WorkerSignal.None
|| signals.WorkingSignal != WorkingSignal.None))
{
repository.ClearWorkingSignalPair(this.id, recordId, transaction);
}
transaction.Commit();
}
}
if (signals != null)
{
bool refreshQueues = false;
// Refresh the queues we're processing.
lock (this.runLocker)
{
QueueNameFilters filters = QueueNameFilters.Parse(signals.QueueNames);
if (!this.queueFilters.Equals(filters))
{
this.queueFilters = QueueNameFilters.Parse(signals.QueueNames);
refreshQueues = true;
}
}
// Perform the signalled operation, if applicable.
if (signals.WorkerSignal == WorkerSignal.Stop)
{
this.logger.Debug("Worker {0} ({1}) received a signal to stop.", this.name, this.id);
this.Stop(false);
}
else
{
if (signals.WorkingSignal == WorkingSignal.Cancel)
{
this.logger.Debug("Worker {0} ({1}) received a signal to cancel its current job.", this.name, this.id);
this.CancelCurrent();
}
if (signals.WorkerSignal == WorkerSignal.Start)
{
this.logger.Debug("Worker {0} ({1}) received a signal to start.", this.name, this.id);
this.Start();
}
lock (this.statusLocker)
{
status = this.Status;
}
if (status == WorkerStatus.Working)
{
if (this.SchedulerEnabled)
{
if (refreshQueues)
{
this.scheduler.QueueFilters = new QueueNameFilters(this.queueFilters.Include, this.queueFilters.Exclude);
}
if (signals.WorkerSignal == WorkerSignal.RefreshSchedules)
{
this.logger.Debug("Worker {0} ({1}) received a signal to refresh its schedules.", this.name, this.id);
this.scheduler.RefreshSchedules();
}
this.scheduler.EnqueueScheduledJobs();
}
}
}
}
else
{
// If no signals were returned, it means that this worker
// is orphaned.
this.Stop(false);
break;
}
}
catch (ThreadAbortException)
{
throw;
}
catch (Exception ex)
{
this.logger.Error(ex, "Exception thrown during the signal loop for worker {0} ({1}).", this.name, this.id);
}
}
}