Beispiel #1
0
        public async Task WorkItem_Throws_Exception_When_Logger_Is_Null_Should_Swallow_Exception()
        {
            //Arrange
            var settings = new BatchSettings
            {
                NumberOfParallelJobs = 1,
                PollingFrequency     = 50,
                HeartBeatFrequency   = 5000,
            };

            var job = CreateJobWithException();

            _store.AcquireJobAsync().Returns(Task.FromResult(job), Task.FromResult((JobDescription)null));

            //Act
            using (var engine = new BatchEngine(_store, _dependencyResolver, null, settings))
            {
                engine.Start();

                await Task.Delay(10);
            }

            //Assert

            AssertNoErrorsLogged();
        }
Beispiel #2
0
        public async Task Heart_Neat_Failed_Should_Log_Error()
        {
            //Arrange
            var settings = new BatchSettings
            {
                NumberOfParallelJobs = 1,
                PollingFrequency     = 500,
                HeartBeatFrequency   = 50,
            };

            _store.HeartBeatAsync(Environment.MachineName, 1, 500, 50)
            .Throws(x => new Exception("Some error"));

            //Act
            using (var engine = new BatchEngine(_store, _dependencyResolver, _logger, settings))
            {
                engine.Start();

                await Task.Delay(150);
            }

            //Assert
            await _store.Received().HeartBeatAsync(Environment.MachineName, 1, 500, 50);

            _logger.Received().Log(
                LogLevel.Error,
                Arg.Any <EventId>(),
                Arg.Is <object>(o => o.ToString().StartsWith("Error while sending heartbeat, System.Exception: Some error")),
                null,
                Arg.Any <Func <object, Exception, string> >());
        }
Beispiel #3
0
        public async Task Heart_Beat_Failed_When_Logger_Is_Null_Should_Swallow_Error()
        {
            //Arrange
            var settings = new BatchSettings
            {
                NumberOfParallelJobs = 1,
                PollingFrequency     = 500,
                HeartBeatFrequency   = 50,
            };

            _store.HeartBeatAsync(Environment.MachineName, 1, 500, 50)
            .Throws(x => new Exception("Some error"));

            //Act
            using (var engine = new BatchEngine(_store, _dependencyResolver, null, settings))
            {
                engine.Start();

                await Task.Delay(150);
            }

            //Assert
            await _store.Received().HeartBeatAsync(Environment.MachineName, 1, 500, 50);

            AssertNoErrorsLogged();
        }
Beispiel #4
0
        public async Task Semaphore_Released_After_Done_Executing()
        {
            //Arrange
            var settings = new BatchSettings
            {
                NumberOfParallelJobs = 1,
                PollingFrequency     = 50,
                HeartBeatFrequency   = 5000,
            };

            var job1 = Task.FromResult(CreateJob(1));
            var job2 = Task.FromResult(CreateJob(2));

            _store.AcquireJobAsync().Returns(job1, job2, Task.FromResult((JobDescription)null));

            var service = Substitute.For <ITestService>();

            _dependencyResolver.Resolve(typeof(ITestService), out _).Returns(x =>
            {
                x[1] = service;

                return(true);
            });

            //Act
            using (var engine = new BatchEngine(_store, _dependencyResolver, _logger, settings))
            {
                engine.Start();

                await Task.Delay(150);
            }

            //Assert
            Received.InOrder(() =>
            {
                service.DoSomethingAsync(1);
                service.DoSomethingAsync(2);
            });

            await _store.Received().AcquireJobAsync();

            await service.Received(2).DoSomethingAsync(Arg.Any <int>());

            AssertNoErrorsLogged();
        }
Beispiel #5
0
        public async Task Successful_Job_Should_Release_With_Given_Result()
        {
            //Arrange
            var settings = new BatchSettings
            {
                NumberOfParallelJobs = 1,
                PollingFrequency     = 50,
                HeartBeatFrequency   = 5000,
            };

            var data = new TestJobWithReturnData.TestData
            {
                State      = ExecutionState.Halted,
                StatusInfo = "info",
                DueTime    = new DateTime(2018, 1, 2, 3, 4, 5)
            };

            var job = CreateJobWithReturnData(data);

            job.Id = Guid.NewGuid();

            _store.AcquireJobAsync().Returns(Task.FromResult(job), Task.FromResult((JobDescription)null));

            JobResult result = null;

            await _store.ReleaseJobAsync(job.Id, Arg.Do <JobResult>(x => result = x));

            //Act
            using (var engine = new BatchEngine(_store, _dependencyResolver, _logger, settings))
            {
                engine.Start();

                await Task.Delay(10);
            }

            //Assert
            Assert.Equal(data.State, result.State);
            Assert.Equal(data.StatusInfo, result.StatusInfo);
            Assert.Equal(data.DueTime, result.DueTime);

            await _store.Received(1).ReleaseJobAsync(job.Id, result);

            AssertNoErrorsLogged();
        }
Beispiel #6
0
        static void Main(string[] args)
        {
            //Setup
            var     dateService = new UtcDateService();
            var     store       = new InMemoryStorage(dateService);
            var     resolver    = new SimpleResolver(dateService);
            ILogger logger      = null;
            var     settings    = new BatchSettings
            {
                HeartBeatFrequency   = 2000,
                NumberOfParallelJobs = 2,
                PollingFrequency     = 500
            };

            var scheduler = new JobScheduler(store, dateService);

            //Add a sequence of jobs
            var sequence = new Sequence();

            sequence.Add <SimpleJob>();
            sequence.Add <JobWithInput, JobWithInput.Input>(new JobWithInput.Input
            {
                Text = "this is awesome!"
            });

            //Queue the sequence
            scheduler.QueueAsync(sequence).Wait();

            //Add a single job
            scheduler.QueueAsync <RecurringJob>();

            //Start the engine
            using (var engine = new BatchEngine(store, resolver, logger, settings))
            {
                Console.WriteLine("Starting ...");

                engine.Start();

                Console.ReadKey();
            }
        }
Beispiel #7
0
        static void Main(string[] args)
        {
            //Setup
            var resolver = new SimpleResolver();

            MinionConfiguration.Configuration.UseDependencyResolver(resolver);
            MinionConfiguration.Configuration.UseInMemoryStorage();
            //MinionConfiguration.Configuration.UseSqlStorage("<ConnectionString>");

            MinionConfiguration.Configuration.HeartBeatFrequency   = 2000;
            MinionConfiguration.Configuration.NumberOfParallelJobs = 2;
            MinionConfiguration.Configuration.PollingFrequency     = 500;


            var scheduler = new JobScheduler();

            //Add a sequence of jobs
            var sequence = new Sequence();

            sequence.Add <SimpleJob>();
            sequence.Add <JobWithInput, JobWithInput.Input>(new JobWithInput.Input
            {
                Text = "this is awesome!"
            });

            //Queue the sequence
            scheduler.QueueAsync(sequence).Wait();

            //Add a single job
            scheduler.QueueAsync <RecurringJob>();

            //Start the engine
            using (var engine = new BatchEngine())
            {
                Console.WriteLine("Starting ...");

                engine.Start();

                Console.ReadKey();
            }
        }
Beispiel #8
0
        public void Start_Without_Store()
        {
            //Arrange
            var settings = new BatchSettings
            {
                NumberOfParallelJobs = 1,
                PollingFrequency     = 1000,
                HeartBeatFrequency   = 50,
            };

            InvalidOperationException ex;

            //Act
            using (var engine = new BatchEngine(null, null, null, settings))
            {
                ex = Assert.Throws <InvalidOperationException>(() => engine.Start());
            }

            //Assert
            Assert.Equal("Cannot start without storage.", ex.Message);
        }
Beispiel #9
0
        public async Task Job_Throws_Exception_Should_Release_With_Error_State()
        {
            //Arrange
            var settings = new BatchSettings
            {
                NumberOfParallelJobs = 1,
                PollingFrequency     = 50,
                HeartBeatFrequency   = 5000,
            };

            var job = CreateJobWithException();

            _store.AcquireJobAsync().Returns(Task.FromResult(job), Task.FromResult((JobDescription)null));

            JobResult result = null;

            await _store.ReleaseJobAsync(job.Id, Arg.Do <JobResult>(x => result = x));

            //Act
            using (var engine = new BatchEngine(_store, _dependencyResolver, _logger, settings))
            {
                engine.Start();

                await Task.Delay(10);
            }

            //Assert
            Assert.Equal(ExecutionState.Error, result.State);
            Assert.StartsWith("System.NotImplementedException: Method not implemented.", result.StatusInfo);
            Assert.Equal(job.DueTime, result.DueTime);

            await _store.Received(1).ReleaseJobAsync(job.Id, result);

            _logger.Received(1).Log(
                LogLevel.Error,
                Arg.Any <EventId>(),
                Arg.Is <object>(x => x.ToString().StartsWith("Error while processing work item, ")),
                null,
                Arg.Any <Func <object, Exception, string> >());
        }
Beispiel #10
0
        public async Task Batch_Engine_Should_Send_Heart_Beat()
        {
            //Arrange
            var settings = new BatchSettings
            {
                NumberOfParallelJobs = 1,
                PollingFrequency     = 1000,
                HeartBeatFrequency   = 50,
            };

            //Act
            using (var engine = new BatchEngine(_store, _dependencyResolver, _logger, settings))
            {
                engine.Start();

                await Task.Delay(150);
            }

            //Assert
            await _store.Received().HeartBeatAsync(Environment.MachineName, 1, 1000, 50);

            AssertNoErrorsLogged();
        }
Beispiel #11
0
        public async Task Polling_Frequency_Zero_Should_Release_Semaphore()
        {    //Arrange
            var settings = new BatchSettings
            {
                NumberOfParallelJobs = 1,
                PollingFrequency     = 0,
                HeartBeatFrequency   = 5000,
            };

            var data = new TestJobWithReturnData.TestData
            {
                State      = ExecutionState.Waiting,
                StatusInfo = "info",
                DueTime    = new DateTime(2018, 1, 2, 3, 4, 5)
            };

            var job = CreateJobWithReturnData(data);

            job.Id = Guid.NewGuid();

            _store.AcquireJobAsync().Returns(Task.FromResult(job), Task.FromResult((JobDescription)null), Task.FromResult(job), Task.FromResult((JobDescription)null));

            //Act
            using (var engine = new BatchEngine(_store, _dependencyResolver, _logger, settings))
            {
                engine.Start();

                await Task.Delay(200);
            }

            //Assert

            await _store.Received(2).ReleaseJobAsync(job.Id, Arg.Any <JobResult>());

            AssertNoErrorsLogged();
        }
Beispiel #12
0
        public async Task Should_Wait_For_Executing_Job_To_Finish_Before_Shut_Down()
        {
            //Arrange
            var settings = new BatchSettings
            {
                NumberOfParallelJobs = 1,
                PollingFrequency     = 50,
                HeartBeatFrequency   = 5000,
            };

            var job = Task.FromResult(CreateDelayedJob(300));

            _store.AcquireJobAsync().Returns(job, Task.FromResult((JobDescription)null));

            var service = Substitute.For <ITestService>();

            _dependencyResolver.Resolve(typeof(ITestService), out _).Returns(x =>
            {
                x[1] = service;

                return(true);
            });

            //Act
            using (var engine = new BatchEngine(_store, _dependencyResolver, _logger, settings))
            {
                engine.Start();

                await Task.Delay(10);
            }

            //Assert
            await service.Received(1).DoSomethingAsync(300);

            AssertNoErrorsLogged();
        }
Beispiel #13
0
        public async Task Invoke(HttpContext httpContext)
        {
            var path = httpContext.Request.Path.Value;

            if (!methodLookup.TryGetValue(path, out var methodInfo))
            {
                await next(httpContext);

                return;
            }

            // create args
            string[] args = null;
            try
            {
                if (httpContext.Request.HasFormContentType)
                {
                    args = new string[(httpContext.Request.Form.Count * 2) + 1];
                    {
                        var i = 0;
                        args[i++] = methodInfo.DeclaringType.Name + "." + methodInfo.Name;
                        foreach (var item in httpContext.Request.Form)
                        {
                            args[i++] = "-" + item.Key;
                            args[i++] = (item.Value.Count == 0) ? null
                                      : (item.Value.Count == 1) ? item.Value[0]
                                      : "[" + string.Join(", ", item.Value) + "]";
                        }
                    }
                }
                else
                {
                    args = new[] { methodInfo.DeclaringType.Name + "." + methodInfo.Name };
                }
            }
            catch (Exception ex)
            {
                httpContext.Response.ContentType = "text/plain";
                httpContext.Response.StatusCode  = (int)HttpStatusCode.InternalServerError;
                await httpContext.Response.WriteAsync(ex.ToString());

                return;
            }

            // run with collect statuses
            var hostingInterceptor = new WebHostingInterceptor(interceptor);
            var collectLogger      = new LogCollector(logger);

            var engine = new BatchEngine(collectLogger, provider, hostingInterceptor, httpContext.RequestAborted);
            await engine.RunAsync(methodInfo.DeclaringType, methodInfo, args);

            // out result
            if (hostingInterceptor.CompleteSuccessfully)
            {
                httpContext.Response.ContentType = "text/plain";
                httpContext.Response.StatusCode  = (int)HttpStatusCode.OK;
                await httpContext.Response.WriteAsync(collectLogger.ToString());
            }
            else
            {
                var errorMsg = ((hostingInterceptor.ErrorMessage != null) ? hostingInterceptor.ErrorMessage + Environment.NewLine : "")
                               + ((hostingInterceptor.Exception != null) ? hostingInterceptor.Exception.ToString() : "");
                httpContext.Response.ContentType = "text/plain";
                httpContext.Response.StatusCode  = (int)HttpStatusCode.InternalServerError;
                await httpContext.Response.WriteAsync(errorMsg);
            }
        }