Represents an individual worker that dequeues jobs and performs work.
Inheritance: IDisposable
Example #1
0
        public void WorkerDequeue()
        {
            IJob job = new TestJob() { Id = Guid.NewGuid() };
            SignalsRecord signals = new SignalsRecord() { QueueNames = "*", WorkerSignal = WorkerSignal.None, WorkingSignal = WorkingSignal.None };

            QueueRecord queued = new QueueRecord()
            {
                Id = 12,
                ApplicationName = BlueCollarSection.Section.ApplicationName,
                Data = JsonConvert.SerializeObject(job),
                JobName = job.Name,
                JobType = JobSerializer.GetTypeName(job.GetType()),
                QueuedOn = DateTime.UtcNow,
                QueueName = "*",
                TryNumber = 1
            };

            var transaction = new Mock<IDbTransaction>();

            var repository = new Mock<IRepository>();
            repository.Setup(r => r.BeginTransaction()).Returns(transaction.Object);
            repository.Setup(r => r.BeginTransaction(It.IsAny<IsolationLevel>())).Returns(transaction.Object);
            repository.Setup(r => r.GetQueued(It.IsAny<string>(), It.IsAny<QueueNameFilters>(), It.IsAny<DateTime>(), It.IsAny<IDbTransaction>())).Returns(queued);
            repository.Setup(r => r.GetWorkingSignals(It.IsAny<long>(), It.IsAny<long?>(), It.IsAny<IDbTransaction>())).Returns(signals);

            var factory = new Mock<IRepositoryFactory>();
            factory.Setup(f => f.Create()).Returns(repository.Object);

            var logger = new Mock<ILogger>();

            using (Worker worker = new Worker(BlueCollarSection.Section.ApplicationName, 1, "Test Worker", null, 1, false, factory.Object, logger.Object))
            {
                worker.Start();
                Thread.Sleep(1500);
            }

            repository.Verify(r => r.GetQueued(BlueCollarSection.Section.ApplicationName, It.IsAny<QueueNameFilters>(), It.IsAny<DateTime>(), It.IsAny<IDbTransaction>()));
            repository.Verify(r => r.DeleteQueued(12, It.IsAny<IDbTransaction>()));
            repository.Verify(r => r.CreateWorking(It.Is<WorkingRecord>(w => w.ApplicationName == BlueCollarSection.Section.ApplicationName && w.WorkerId == 1), It.IsAny<IDbTransaction>()));
        }
Example #2
0
        internal void RefreshWorkers()
        {
            List<WorkerRecord> records;

            using (IRepository repository = this.repositoryFactory.Create())
            {
                records = repository.GetWorkers(this.applicationName, this.address, this.name, null).ToList();

                this.logger.Debug(
                    "Machine {0} ({1}) loaded {2} worker records from repository '{3}', using connection string '{4}'.",
                    this.name,
                    this.address,
                    records.Count,
                    repository.GetType().ToString(),
                    repository.ConnectionString);
            }

            lock (this)
            {
                List<Worker> newWorkers = new List<Worker>();
                List<Worker> removeWorkers = new List<Worker>();

                // Figure out which of the current workers get to stay alive.
                foreach (Worker worker in this.workers)
                {
                    WorkerRecord record = records.Where(r => r.Id == worker.Id).FirstOrDefault();

                    if (record != null)
                    {
                        newWorkers.Add(worker);
                        records.Remove(record);
                    }
                    else
                    {
                        removeWorkers.Add(worker);
                    }
                }

                // Prune orphaned current workers.
                foreach (Worker worker in removeWorkers)
                {
                    try
                    {
                        worker.Dispose();
                    }
                    catch (Exception ex)
                    {
                        this.logger.Error(ex);
                    }
                }

                // Create workers for all of the new records. Records corresponding
                // to existing workers where pruned earlier.
                foreach (WorkerRecord record in records)
                {
                    Worker worker = null;

                    try
                    {
                        worker = new Worker(
                            this.applicationName,
                            record.Id.Value,
                            record.Name,
                            QueueNameFilters.Parse(record.QueueNames),
                            this.workerHeartbeat,
                            this.schedulerEnabled,
                            this.repositoryFactory,
                            this.logger);

                        newWorkers.Add(worker);

                        if (record.Status == WorkerStatus.Working || record.Startup == WorkerStartupType.Automatic)
                        {
                            worker.Start();
                        }
                    }
                    catch (Exception ex)
                    {
                        if (worker != null)
                        {
                            newWorkers.Remove(worker);
                            worker.Dispose();
                        }

                        this.logger.Error(ex);
                    }
                }

                // Ensure a default worker if necessary.
                if (newWorkers.Count == 0 && this.ensureDefaultWorker)
                {
                    Worker worker = this.CreateDefaultWorker();
                    newWorkers.Add(worker);
                    worker.Start();
                }

                this.workers = newWorkers;
                this.logger.Debug("Machine {0} ({1}) refreshed its worker list and is now tracking {2} workers.", this.name, this.address, this.workers.Count);
            }
        }
Example #3
0
        public void WorkerDispose()
        {
            IJob job = new TestJob() { Id = Guid.NewGuid() };
            SignalsRecord signals = new SignalsRecord() { QueueNames = "*", WorkerSignal = WorkerSignal.None, WorkingSignal = WorkingSignal.None };

            QueueRecord queued = new QueueRecord()
            {
                Id = 12,
                ApplicationName = BlueCollarSection.Section.ApplicationName,
                Data = JsonConvert.SerializeObject(job),
                JobName = job.Name,
                JobType = JobSerializer.GetTypeName(job.GetType()),
                QueuedOn = DateTime.UtcNow,
                QueueName = "*",
                TryNumber = 1
            };

            var transaction = new Mock<IDbTransaction>();

            var repository = new Mock<IRepository>();
            repository.Setup(r => r.BeginTransaction()).Returns(transaction.Object);
            repository.Setup(r => r.BeginTransaction(It.IsAny<IsolationLevel>())).Returns(transaction.Object);
            repository.Setup(r => r.GetQueued(It.IsAny<string>(), It.IsAny<QueueNameFilters>(), It.IsAny<DateTime>(), It.IsAny<IDbTransaction>())).Returns(queued);
            repository.Setup(r => r.GetWorkingSignals(It.IsAny<long>(), It.IsAny<long?>(), It.IsAny<IDbTransaction>())).Returns(signals);

            var factory = new Mock<IRepositoryFactory>();
            factory.Setup(f => f.Create()).Returns(repository.Object);

            var logger = new Mock<ILogger>();
            Worker worker = null;

            try
            {
                worker = new Worker(BlueCollarSection.Section.ApplicationName, 1, "Test Worker", null, 1, false, factory.Object, logger.Object);
                worker.Start();
                Thread.Sleep(1500);
                worker.Stop(false);
                worker.Dispose();

                Assert.IsFalse(worker.LoopThreadsAreAlive);
                worker = null;
            }
            finally
            {
                if (worker != null)
                {
                    worker.Dispose();
                }
            }
        }
Example #4
0
        public void WorkerStop()
        {
            var transaction = new Mock<IDbTransaction>();
            var repository = new Mock<IRepository>();
            repository.Setup(r => r.BeginTransaction()).Returns(transaction.Object);
            repository.Setup(r => r.BeginTransaction(It.IsAny<IsolationLevel>())).Returns(transaction.Object);
            var factory = new Mock<IRepositoryFactory>();
            factory.Setup(f => f.Create()).Returns(repository.Object);
            var logger = new Mock<ILogger>();

            using (Worker worker = new Worker(BlueCollarSection.Section.ApplicationName, 1, "Test Worker", null, 1, false, factory.Object, logger.Object))
            {
                worker.Start();
                worker.Stop(false);
                Thread.Sleep(1);
                Assert.AreEqual(WorkerStatus.Stopped, worker.Status);
            }
        }
Example #5
0
        public void WorkerRefreshSchedulesWithSignal()
        {
            SignalsRecord signals = new SignalsRecord() { QueueNames = "*", WorkerSignal = WorkerSignal.None, WorkingSignal = WorkingSignal.None };

            var transaction = new Mock<IDbTransaction>();

            var repository = new Mock<IRepository>();
            repository.Setup(r => r.BeginTransaction()).Returns(transaction.Object);
            repository.Setup(r => r.BeginTransaction(It.IsAny<IsolationLevel>())).Returns(transaction.Object);
            repository.Setup(r => r.GetWorkingSignals(It.IsAny<long>(), It.IsAny<long?>(), It.IsAny<IDbTransaction>())).Returns(signals);

            var factory = new Mock<IRepositoryFactory>();
            factory.Setup(f => f.Create()).Returns(repository.Object);

            var logger = new Mock<ILogger>();
            var scheduler = new Mock<IScheduler>();

            using (Worker worker = new Worker(BlueCollarSection.Section.ApplicationName, 1, "Test Worker", null, 1, true, factory.Object, logger.Object, scheduler.Object))
            {
                worker.Start();
                signals.WorkerSignal = WorkerSignal.RefreshSchedules;
                Thread.Sleep(1500);
            }

            scheduler.Verify(s => s.RefreshSchedules(), Times.AtLeastOnce());
        }
Example #6
0
        public void WorkerExecuteTimeout()
        {
            IJob job = new TestJob() { SleepDuration = 100, Timeout = 10 };
            SignalsRecord signals = new SignalsRecord() { QueueNames = "*", WorkerSignal = WorkerSignal.None, WorkingSignal = WorkingSignal.None };

            QueueRecord queued = new QueueRecord()
            {
                Id = 12,
                ApplicationName = BlueCollarSection.Section.ApplicationName,
                Data = JsonConvert.SerializeObject(job),
                JobName = job.Name,
                JobType = JobSerializer.GetTypeName(job.GetType()),
                QueuedOn = DateTime.UtcNow,
                QueueName = "*",
                TryNumber = 1
            };

            WorkingRecord working = Worker.CreateWorking(queued, 1, null, DateTime.UtcNow);
            working.Id = 13;

            var transaction = new Mock<IDbTransaction>();

            var repository = new Mock<IRepository>();
            repository.Setup(r => r.BeginTransaction()).Returns(transaction.Object);
            repository.Setup(r => r.BeginTransaction(It.IsAny<IsolationLevel>())).Returns(transaction.Object);
            repository.Setup(r => r.CreateWorking(It.IsAny<WorkingRecord>(), It.IsAny<IDbTransaction>())).Returns(working);
            repository.Setup(r => r.GetQueued(It.IsAny<string>(), It.IsAny<QueueNameFilters>(), It.IsAny<DateTime>(), It.IsAny<IDbTransaction>())).Returns(queued);
            repository.Setup(r => r.GetWorkingSignals(It.IsAny<long>(), It.IsAny<long?>(), It.IsAny<IDbTransaction>())).Returns(signals);

            var factory = new Mock<IRepositoryFactory>();
            factory.Setup(f => f.Create()).Returns(repository.Object);

            var logger = new Mock<ILogger>();

            using (Worker worker = new Worker(BlueCollarSection.Section.ApplicationName, 1, "Test Worker", null, 1, false, factory.Object, logger.Object))
            {
                worker.Start();
                Thread.Sleep(1500);
            }

            repository.Verify(r => r.CreateHistory(It.Is<HistoryRecord>(h => h.Status == HistoryStatus.TimedOut), It.IsAny<IDbTransaction>()));
        }