From 0a8dde6683a3cc652f69700597a6b75b15edf41f Mon Sep 17 00:00:00 2001 From: Vladislav Ma-iu-shan Date: Tue, 3 Sep 2019 00:43:56 +0300 Subject: [PATCH 1/2] Hangfire added --- src/Tinkoff.ISA.API/Program.cs | 9 +- src/Tinkoff.ISA.API/Startup.cs | 44 +++++- src/Tinkoff.ISA.API/Tinkoff.ISA.API.csproj | 2 + .../Jobs/ConfluenceJob.cs | 2 +- .../MongoDb/IMongoContext.cs | 1 + .../MongoDb/MongoContext.cs | 2 + .../JobsActivator/JobsActivatorTests.cs | 140 ------------------ .../Scheduler/SchedulerTests.cs | 47 ------ .../Activators/IJobsActivator.cs | 7 - .../Activators/JobsActivator.cs | 75 ---------- src/Tinkoff.ISA.Scheduler/HangfireService.cs | 40 +++++ src/Tinkoff.ISA.Scheduler/Program.cs | 104 +++++++------ .../Schedule/IScheduler.cs | 9 -- .../Schedule/Scheduler.cs | 47 ------ .../Tinkoff.ISA.Scheduler.csproj | 3 + src/Tinkoff.ISA.SchedulerUI/Program.cs | 18 +++ .../Properties/launchSettings.json | 27 ++++ src/Tinkoff.ISA.SchedulerUI/Startup.cs | 81 ++++++++++ .../Tinkoff.ISA.SchedulerUI.csproj | 32 ++++ .../appsettings.DevDocker.json | 10 ++ .../appsettings.Prod.json | 10 ++ .../appsettings.QA.json | 10 ++ src/Tinkoff.ISA.SchedulerUI/appsettings.json | 10 ++ src/Tinkoff.ISA.sln | 6 + src/Tinkoff.ISA.sln.DotSettings | 3 + 25 files changed, 363 insertions(+), 376 deletions(-) delete mode 100644 src/Tinkoff.ISA.Scheduler.UnitTests/JobsActivator/JobsActivatorTests.cs delete mode 100644 src/Tinkoff.ISA.Scheduler.UnitTests/Scheduler/SchedulerTests.cs delete mode 100644 src/Tinkoff.ISA.Scheduler/Activators/IJobsActivator.cs delete mode 100644 src/Tinkoff.ISA.Scheduler/Activators/JobsActivator.cs create mode 100644 src/Tinkoff.ISA.Scheduler/HangfireService.cs delete mode 100644 src/Tinkoff.ISA.Scheduler/Schedule/IScheduler.cs delete mode 100644 src/Tinkoff.ISA.Scheduler/Schedule/Scheduler.cs create mode 100644 src/Tinkoff.ISA.SchedulerUI/Program.cs create mode 100644 src/Tinkoff.ISA.SchedulerUI/Properties/launchSettings.json create mode 100644 src/Tinkoff.ISA.SchedulerUI/Startup.cs create mode 100644 src/Tinkoff.ISA.SchedulerUI/Tinkoff.ISA.SchedulerUI.csproj create mode 100644 src/Tinkoff.ISA.SchedulerUI/appsettings.DevDocker.json create mode 100644 src/Tinkoff.ISA.SchedulerUI/appsettings.Prod.json create mode 100644 src/Tinkoff.ISA.SchedulerUI/appsettings.QA.json create mode 100644 src/Tinkoff.ISA.SchedulerUI/appsettings.json create mode 100644 src/Tinkoff.ISA.sln.DotSettings diff --git a/src/Tinkoff.ISA.API/Program.cs b/src/Tinkoff.ISA.API/Program.cs index f3ed088..49d93a9 100644 --- a/src/Tinkoff.ISA.API/Program.cs +++ b/src/Tinkoff.ISA.API/Program.cs @@ -1,16 +1,17 @@ -using Microsoft.AspNetCore; +using System.Threading.Tasks; +using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; namespace Tinkoff.ISA.API { public class Program { - public static void Main(string[] args) + public static Task Main(string[] args) { - CreateWebHostBuilder(args).UseUrls("http://*:5000").Build().Run(); + return CreateWebHostBuilder(args).UseUrls("http://*:5000").Build().RunAsync(); } - public static IWebHostBuilder CreateWebHostBuilder(string[] args) => + private static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .UseStartup(); } diff --git a/src/Tinkoff.ISA.API/Startup.cs b/src/Tinkoff.ISA.API/Startup.cs index a69c577..e3e3856 100644 --- a/src/Tinkoff.ISA.API/Startup.cs +++ b/src/Tinkoff.ISA.API/Startup.cs @@ -1,16 +1,21 @@ using System.IO; using AutoMapper; +using Hangfire; +using Hangfire.Common; +using Hangfire.Mongo; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Tinkoff.ISA.AppLayer; +using Tinkoff.ISA.AppLayer.Jobs; using Tinkoff.ISA.Infrastructure.Settings; using Tinkoff.ISA.DAL; using Tinkoff.ISA.DAL.Common; using Tinkoff.ISA.Infrastructure.Configuration; using Tinkoff.ISA.Infrastructure.Extensions; +using Tinkoff.ISA.Infrastructure.MongoDb; using IHostingEnvironment = Microsoft.AspNetCore.Hosting.IHostingEnvironment; namespace Tinkoff.ISA.API @@ -40,10 +45,31 @@ public void ConfigureServices(IServiceCollection services) services.AddAppDependencies(); services.AddMvc(); services.AddAutoMapper(); + services.AddHangfire((serviceProvider, config) => + { + var mongoContext = serviceProvider + .GetService(); + + config.UseMongoStorage( + mongoContext.MongoClient.Settings, + "Jobs", + new MongoStorageOptions + { + MigrationOptions = new MongoMigrationOptions + { + Strategy = MongoMigrationStrategy.Drop, + BackupStrategy = MongoBackupStrategy.Collections + } + }); + }); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) + public void Configure( + IApplicationBuilder app, + IHostingEnvironment env, + ILoggerFactory loggerFactory, + IRecurringJobManager recurringJobManager) { var logSettings = _configuration.GetSection("Logging").Get(); @@ -60,6 +86,22 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerF } app.UseMvc(); + + recurringJobManager.AddOrUpdate( + nameof(JiraJob), + job => job.StartJob(), + Cron.Minutely + ); + recurringJobManager.AddOrUpdate( + nameof(ConfluenceJob), + job => job.StartJob(), + Cron.Minutely + ); + recurringJobManager.AddOrUpdate( + nameof(MongoIndexingForElasticJob), + job => job.StartJob(), + Cron.Minutely + ); } } } diff --git a/src/Tinkoff.ISA.API/Tinkoff.ISA.API.csproj b/src/Tinkoff.ISA.API/Tinkoff.ISA.API.csproj index dc15a5c..28cd4cd 100644 --- a/src/Tinkoff.ISA.API/Tinkoff.ISA.API.csproj +++ b/src/Tinkoff.ISA.API/Tinkoff.ISA.API.csproj @@ -12,6 +12,8 @@ + + diff --git a/src/Tinkoff.ISA.AppLayer/Jobs/ConfluenceJob.cs b/src/Tinkoff.ISA.AppLayer/Jobs/ConfluenceJob.cs index 9721a91..b8378a6 100644 --- a/src/Tinkoff.ISA.AppLayer/Jobs/ConfluenceJob.cs +++ b/src/Tinkoff.ISA.AppLayer/Jobs/ConfluenceJob.cs @@ -16,7 +16,7 @@ namespace Tinkoff.ISA.AppLayer.Jobs { - internal class ConfluenceJob : IJob + public class ConfluenceJob : IJob { private readonly IConfluenceHttpClient _confluenceHttpClient; private readonly IElasticsearchClient _elasticsearchClient; diff --git a/src/Tinkoff.ISA.Infrastructure/MongoDb/IMongoContext.cs b/src/Tinkoff.ISA.Infrastructure/MongoDb/IMongoContext.cs index 7fd8a7b..8134a99 100644 --- a/src/Tinkoff.ISA.Infrastructure/MongoDb/IMongoContext.cs +++ b/src/Tinkoff.ISA.Infrastructure/MongoDb/IMongoContext.cs @@ -4,6 +4,7 @@ namespace Tinkoff.ISA.Infrastructure.MongoDb { public interface IMongoContext { + IMongoClient MongoClient { get; } IMongoCollection For(); } } diff --git a/src/Tinkoff.ISA.Infrastructure/MongoDb/MongoContext.cs b/src/Tinkoff.ISA.Infrastructure/MongoDb/MongoContext.cs index f6f4a7e..9a104b8 100644 --- a/src/Tinkoff.ISA.Infrastructure/MongoDb/MongoContext.cs +++ b/src/Tinkoff.ISA.Infrastructure/MongoDb/MongoContext.cs @@ -15,6 +15,8 @@ public class MongoContext : IMongoContext private readonly Lazy _isaMongoClient; private readonly string _isaDbName; + public IMongoClient MongoClient => _isaMongoClient.Value; + static MongoContext() { BsonDefaults.GuidRepresentation = GuidRepresentation.Standard; diff --git a/src/Tinkoff.ISA.Scheduler.UnitTests/JobsActivator/JobsActivatorTests.cs b/src/Tinkoff.ISA.Scheduler.UnitTests/JobsActivator/JobsActivatorTests.cs deleted file mode 100644 index 23ecec9..0000000 --- a/src/Tinkoff.ISA.Scheduler.UnitTests/JobsActivator/JobsActivatorTests.cs +++ /dev/null @@ -1,140 +0,0 @@ -using System; -using System.Threading.Tasks; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Moq; -using Tinkoff.ISA.AppLayer.Jobs; -using Tinkoff.ISA.Infrastructure.Settings; -using Xunit; - -namespace Tinkoff.ISA.Scheduler.UnitTests.JobsActivator -{ - public class JobsActivatorTests - { - private readonly Mock> _logger; - private readonly Mock> _settingOptionsMock; - - public JobsActivatorTests() - { - _logger = new Mock>(); - _settingOptionsMock = new Mock>(); - } - - public class JobA : IJob - { - public static bool WasInvoked { get; private set; } - - public Task StartJob() - { - WasInvoked = true; - return Task.CompletedTask; - } - } - public class JobB : IJob - { - public static bool WasInvoked { get; private set; } - - public Task StartJob() - { - WasInvoked = true; - return Task.CompletedTask; - } - } - - public class JobC : IJob - { - public static bool WasInvoked { get; private set; } - - public Task StartJob() - { - WasInvoked = true; - return Task.CompletedTask; - } - } - - public class JobError : IJob - { - public static int InvokedCount { get; private set; } - - public Task StartJob() - { - InvokedCount += 1; - throw new Exception(); - } - } - - [Fact] - public void StartJobs_JustInvoked_ShouldInvokedJobsAandBandnotInvokedC() - { - //arrange - var names = new[] - { - "JobA", - "JobB" - }; - - _settingOptionsMock - .SetupGet(m => m.Value) - .Returns(() => new SchedulerSettings() - { - JobNames = names, - LoopTimeMinutes = 1, - MaxRetries = 3 - }); - - var serviceProvider = new ServiceCollection() - .AddSingleton() - .AddSingleton() - .AddSingleton() - .BuildServiceProvider(); - - var job = new Activators.JobsActivator( - serviceProvider, - _settingOptionsMock.Object, - _logger.Object); - - //act - job.StartJobs(); - - //Assert - Assert.True(JobA.WasInvoked); - Assert.True(JobB.WasInvoked); - Assert.False(JobC.WasInvoked); - } - - [Fact] - public void StartJobs_JustInvoked_ShouldRestartJob() - { - //arrange - var names = new[] - { - "JobError" - }; - - _settingOptionsMock - .SetupGet(m => m.Value) - .Returns(() => new SchedulerSettings() - { - JobNames = names, - LoopTimeMinutes = 1, - MaxRetries = 2 - }); - - var serviceProvider = new ServiceCollection() - .AddSingleton() - .BuildServiceProvider(); - - var job = new Activators.JobsActivator( - serviceProvider, - _settingOptionsMock.Object, - _logger.Object); - - //act - job.StartJobs(); - - //Assert - Assert.Equal(2, JobError.InvokedCount); - } - } -} diff --git a/src/Tinkoff.ISA.Scheduler.UnitTests/Scheduler/SchedulerTests.cs b/src/Tinkoff.ISA.Scheduler.UnitTests/Scheduler/SchedulerTests.cs deleted file mode 100644 index b50ecc4..0000000 --- a/src/Tinkoff.ISA.Scheduler.UnitTests/Scheduler/SchedulerTests.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System.Threading.Tasks; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Moq; -using Tinkoff.ISA.Infrastructure.Settings; -using Tinkoff.ISA.Scheduler.Activators; -using Xunit; - -namespace Tinkoff.ISA.Scheduler.UnitTests.Scheduler -{ - public class SchedulerTests - { - private readonly Mock _jobsActivatorMock; - private readonly Mock> _logger; - private readonly Mock> _schedulerSettingOptionsMock; - - public SchedulerTests() - { - _jobsActivatorMock = new Mock(); - - _logger = new Mock>(); - - _schedulerSettingOptionsMock = new Mock>(); - _schedulerSettingOptionsMock - .SetupGet(m => m.Value) - .Returns(() => new SchedulerSettings() - { - LoopTimeMinutes = 1 - }); - } - - [Fact] - public async void StartJobs_JustInvoked_ShouldInvokeJobsActivatorStartJobs() - { - //act - var scheduler = new Schedule.Scheduler( - _logger.Object, - _schedulerSettingOptionsMock.Object, - _jobsActivatorMock.Object); - - await Task.Delay(1000); - - //assert - _jobsActivatorMock.Verify(m => m.StartJobs(), Times.AtLeastOnce); - } - } -} diff --git a/src/Tinkoff.ISA.Scheduler/Activators/IJobsActivator.cs b/src/Tinkoff.ISA.Scheduler/Activators/IJobsActivator.cs deleted file mode 100644 index e441210..0000000 --- a/src/Tinkoff.ISA.Scheduler/Activators/IJobsActivator.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Tinkoff.ISA.Scheduler.Activators -{ - public interface IJobsActivator - { - void StartJobs(); - } -} diff --git a/src/Tinkoff.ISA.Scheduler/Activators/JobsActivator.cs b/src/Tinkoff.ISA.Scheduler/Activators/JobsActivator.cs deleted file mode 100644 index 9edec1a..0000000 --- a/src/Tinkoff.ISA.Scheduler/Activators/JobsActivator.cs +++ /dev/null @@ -1,75 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Threading.Tasks; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Tinkoff.ISA.AppLayer.Jobs; -using Tinkoff.ISA.Infrastructure.Settings; - -namespace Tinkoff.ISA.Scheduler.Activators -{ - internal class JobsActivator : IJobsActivator - { - private static readonly Type JobsInterfaceType = typeof(IJob); - private static string[] _jobNames; - private readonly IServiceProvider _serviceProvider; - private readonly ILogger _logger; - private readonly IOptions _settings; - - public JobsActivator( - IServiceProvider serviceProvider, - IOptions settings, - ILogger logger) - { - _serviceProvider = serviceProvider; - _logger = logger; - _settings = settings; - _jobNames = _settings.Value.JobNames; - } - - public async void StartJobs() - { - var jobServices = _serviceProvider.GetServices(JobsInterfaceType).ToList(); - var jobTypes = GetJobsTypes(JobsInterfaceType); - var methods = JobsInterfaceType.GetMethods(BindingFlags.Public | BindingFlags.Instance); - - foreach (var jobType in jobTypes) - { - var job = jobServices.FirstOrDefault(o => o.GetType() == jobType); - - for (var i = 0; i < _settings.Value.MaxRetries; i++) - { - try - { - _logger.LogInformation("{JobName} started {LaunchDate}", jobType.Name, DateTime.Now); - await (Task)jobType.InvokeMember(methods.First().Name, BindingFlags.InvokeMethod, null, job, null); - _logger.LogInformation("{JobName} finished {FinishDate}", jobType.Name, DateTime.Now); - break; - } - catch (Exception e) - { - _logger.LogWarning("{JobName} exited with error: {exception}", jobType.Name, e.Message); - await Task.Delay(_settings.Value.RestartJobDelayMilliseconds); - _logger.LogInformation("{JobName} relaunch attempt № {tryNumber}", jobType.Name, i + 1); - } - } - } - } - - private static IEnumerable GetJobsTypes(Type interfaceType) - { - return AppDomain.CurrentDomain - .GetAssemblies() - .SelectMany(x => x.GetTypes()) - .Where(x => - interfaceType.IsAssignableFrom(x) && - _jobNames.Contains(x.Name) && - !x.IsInterface && - !x.IsAbstract) - .ToList(); - } - } -} diff --git a/src/Tinkoff.ISA.Scheduler/HangfireService.cs b/src/Tinkoff.ISA.Scheduler/HangfireService.cs new file mode 100644 index 0000000..48bd149 --- /dev/null +++ b/src/Tinkoff.ISA.Scheduler/HangfireService.cs @@ -0,0 +1,40 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Hangfire; +using Hangfire.Server; +using Microsoft.Extensions.Hosting; + +namespace Tinkoff.ISA.Scheduler +{ + public class HangfireService : IHostedService + { + private readonly IEnumerable _additionalProcesses; + private readonly BackgroundJobServerOptions _options; + private readonly JobStorage _storage; + private BackgroundJobServer _server; + + public HangfireService( + JobStorage storage, + IEnumerable options, + IEnumerable additionalProcesses) + { + _storage = storage; + _options = options.FirstOrDefault() ?? new BackgroundJobServerOptions(); + _additionalProcesses = additionalProcesses; + } + + public Task StartAsync(CancellationToken cancellationToken) + { + _server = new BackgroundJobServer(_options, _storage, _additionalProcesses); + return Task.CompletedTask; + } + + public Task StopAsync(CancellationToken cancellationToken) + { + _server.Dispose(); + return Task.CompletedTask; + } + } +} \ No newline at end of file diff --git a/src/Tinkoff.ISA.Scheduler/Program.cs b/src/Tinkoff.ISA.Scheduler/Program.cs index dc467cc..789bfc0 100644 --- a/src/Tinkoff.ISA.Scheduler/Program.cs +++ b/src/Tinkoff.ISA.Scheduler/Program.cs @@ -1,65 +1,79 @@ -using System; -using System.IO; -using System.Threading; +using System.Threading.Tasks; +using Hangfire; +using Hangfire.Mongo; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Hosting; using Serilog; using Tinkoff.ISA.AppLayer; using Tinkoff.ISA.AppLayer.Jobs; using Tinkoff.ISA.DAL; using Tinkoff.ISA.Infrastructure.Configuration; using Tinkoff.ISA.Infrastructure.Extensions; +using Tinkoff.ISA.Infrastructure.MongoDb; using Tinkoff.ISA.Infrastructure.Settings; -using Tinkoff.ISA.Scheduler.Activators; -using Tinkoff.ISA.Scheduler.Schedule; namespace Tinkoff.ISA.Scheduler { - internal class Program + internal static class Program { - private static readonly ManualResetEventSlim Shutdown = new ManualResetEventSlim(); - - private static void Main() + public static Task Main(string[] args) { - var environmentName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"); - var builder = new ConfigurationBuilder() - .SetBasePath(Directory.GetCurrentDirectory()) - .AddJsonFile(ConfigHelper.GetConfigByEnvironment(environmentName)); - - var configuration = builder.Build(); + var host = new HostBuilder() + .ConfigureAppConfiguration((hostingContext, config) => + { + var env = hostingContext.HostingEnvironment; + config + .SetBasePath(env.ContentRootPath) + .AddJsonFile(ConfigHelper.GetConfigByEnvironment(env.EnvironmentName)); + }) + .ConfigureServices((context, services) => + { + var configuration = context.Configuration; - var logSettings = configuration.GetSection("Logging").Get(); + services + .AddHangfire((serviceProvider, config) => + { + var mongoContext = serviceProvider + .GetService(); - //setup our DI - var serviceProvider = new ServiceCollection() - .AddSingleton(new LoggerFactory().AddSerilog(LogExtensions.CreateLogger(logSettings, "isa-.log"))) - .AddLogging() - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddAppDependencies() - .AddDalDependencies() - .AddInfrastructureDependencies() - .Configure(configuration.GetSection("Scheduler")) - .Configure(configuration.GetSection("JiraSettings")) - .Configure(configuration.GetSection("ConfluenceSettings")) - .Configure(configuration.GetSection("ElasticsearchSettings")) - .Configure(configuration.GetSection("ConnectionStrings")) - .BuildServiceProvider(); + config.UseMongoStorage( + mongoContext.MongoClient.Settings, + "Jobs", + new MongoStorageOptions + { + MigrationOptions = new MongoMigrationOptions + { + Strategy = MongoMigrationStrategy.Drop, + BackupStrategy = MongoBackupStrategy.Collections + } + }); + }) + .AddSingleton() + .AddAppDependencies() + .AddDalDependencies() + .AddInfrastructureDependencies() + .Configure(configuration.GetSection("ConnectionStrings")) + .Configure(configuration.GetSection("JiraSettings")) + .Configure(configuration.GetSection("ConfluenceSettings")) + .Configure(configuration.GetSection("ElasticsearchSettings")) + .AddSingleton() + .AddSingleton() + .AddSingleton(); + }) + .ConfigureLogging((hostingContext, logging) => + { + var logSettings = hostingContext.Configuration + .GetSection("Logging") + .Get(); + var logger = LogExtensions.CreateLogger(logSettings, "isa-.log"); + + logging.AddSerilog(logger); + }) + .UseConsoleLifetime() + .Build(); - var logger = serviceProvider.GetService() - .CreateLogger(); - - logger.LogDebug("Starting application"); - Console.WriteLine("Starting application"); - - using (serviceProvider.GetService()) - { - Shutdown.Wait(); - } + return host.RunAsync(); } } } \ No newline at end of file diff --git a/src/Tinkoff.ISA.Scheduler/Schedule/IScheduler.cs b/src/Tinkoff.ISA.Scheduler/Schedule/IScheduler.cs deleted file mode 100644 index c09420e..0000000 --- a/src/Tinkoff.ISA.Scheduler/Schedule/IScheduler.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System; - -namespace Tinkoff.ISA.Scheduler.Schedule -{ - public interface IScheduler : IDisposable - { - void StartJobs(object o); - } -} diff --git a/src/Tinkoff.ISA.Scheduler/Schedule/Scheduler.cs b/src/Tinkoff.ISA.Scheduler/Schedule/Scheduler.cs deleted file mode 100644 index 173f1ef..0000000 --- a/src/Tinkoff.ISA.Scheduler/Schedule/Scheduler.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System; -using System.Threading; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Tinkoff.ISA.Infrastructure.Settings; -using Tinkoff.ISA.Scheduler.Activators; - -namespace Tinkoff.ISA.Scheduler.Schedule -{ - internal class Scheduler : IScheduler - { - private readonly Timer _timer; - private readonly ILogger _logger; - private readonly IJobsActivator _jobsActivator; - - public Scheduler( - ILogger logger, - IOptions schedulerSettings, - IJobsActivator jobsActivator) - { - _logger = logger; - _jobsActivator = jobsActivator; - - var period = TimeSpan.FromMinutes(schedulerSettings.Value.LoopTimeMinutes); - _timer = new Timer(StartJobs, null, TimeSpan.Zero, period); - } - - public void StartJobs(object o) - { - try - { - _logger.LogInformation("{JobsLaunchDate} Jobs started", DateTime.Now); - _jobsActivator.StartJobs(); - _logger.LogInformation("{JobsFinishDate} Jobs finished", DateTime.Now); - } - catch (Exception e) - { - _logger.LogError("Scheduler exited with error: {exception}", e.Message); - } - } - - public void Dispose() - { - _timer?.Dispose(); - } - } -} diff --git a/src/Tinkoff.ISA.Scheduler/Tinkoff.ISA.Scheduler.csproj b/src/Tinkoff.ISA.Scheduler/Tinkoff.ISA.Scheduler.csproj index 2c9ae8b..f62143d 100644 --- a/src/Tinkoff.ISA.Scheduler/Tinkoff.ISA.Scheduler.csproj +++ b/src/Tinkoff.ISA.Scheduler/Tinkoff.ISA.Scheduler.csproj @@ -21,8 +21,11 @@ + + + diff --git a/src/Tinkoff.ISA.SchedulerUI/Program.cs b/src/Tinkoff.ISA.SchedulerUI/Program.cs new file mode 100644 index 0000000..881c197 --- /dev/null +++ b/src/Tinkoff.ISA.SchedulerUI/Program.cs @@ -0,0 +1,18 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore; +using Microsoft.AspNetCore.Hosting; + +namespace Tinkoff.ISA.SchedulerUI +{ + public static class Program + { + public static Task Main(string[] args) + { + return CreateWebHostBuilder(args).Build().RunAsync(); + } + + private static IWebHostBuilder CreateWebHostBuilder(string[] args) => + WebHost.CreateDefaultBuilder(args) + .UseStartup(); + } +} diff --git a/src/Tinkoff.ISA.SchedulerUI/Properties/launchSettings.json b/src/Tinkoff.ISA.SchedulerUI/Properties/launchSettings.json new file mode 100644 index 0000000..09ecd44 --- /dev/null +++ b/src/Tinkoff.ISA.SchedulerUI/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:5000", + "sslPort": 5001 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "Tinkoff.ISA.SchedulerUI": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:5001;http://localhost:5000" + } + } +} diff --git a/src/Tinkoff.ISA.SchedulerUI/Startup.cs b/src/Tinkoff.ISA.SchedulerUI/Startup.cs new file mode 100644 index 0000000..e20f4c4 --- /dev/null +++ b/src/Tinkoff.ISA.SchedulerUI/Startup.cs @@ -0,0 +1,81 @@ +using System.IO; +using System.Threading.Tasks; +using Hangfire; +using Hangfire.Mongo; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Tinkoff.ISA.DAL; +using Tinkoff.ISA.Infrastructure.Configuration; +using Tinkoff.ISA.Infrastructure.Extensions; +using Tinkoff.ISA.Infrastructure.MongoDb; +using Tinkoff.ISA.Infrastructure.Settings; + +namespace Tinkoff.ISA.SchedulerUI +{ + public class Startup + { + private readonly IConfigurationRoot _configuration; + + public Startup(IHostingEnvironment env) + { + var builder = new ConfigurationBuilder() + .SetBasePath(Directory.GetCurrentDirectory()) + .AddJsonFile(ConfigHelper.GetConfigByEnvironment(env.EnvironmentName), false, true); + + _configuration = builder.Build(); + } + + // This method gets called by the runtime. Use this method to add services to the container. + public void ConfigureServices(IServiceCollection services) + { + services.Configure(_configuration.GetSection("ConnectionStrings")); + services.AddInfrastructureDependencies(); + services.AddDalDependencies(); + services.AddHangfire((serviceProvider, config) => + { + var mongoContext = serviceProvider + .GetService(); + + config.UseMongoStorage( + mongoContext.MongoClient.Settings, + "Jobs", + new MongoStorageOptions + { + MigrationOptions = new MongoMigrationOptions + { + Strategy = MongoMigrationStrategy.Drop, + BackupStrategy = MongoBackupStrategy.Collections + } + }); + }); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) + { + var logSettings = _configuration.GetSection("Logging").Get(); + + app.UseSerilog(loggerFactory, logSettings, "isa-.log"); + app.UseLogException(); + + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + else + { + app.UseHsts(); + } + + app.UseHangfireDashboard(); + + app.Run(context => { + context.Response.Redirect("/hangfire"); + return Task.CompletedTask; + }); + } + } +} diff --git a/src/Tinkoff.ISA.SchedulerUI/Tinkoff.ISA.SchedulerUI.csproj b/src/Tinkoff.ISA.SchedulerUI/Tinkoff.ISA.SchedulerUI.csproj new file mode 100644 index 0000000..730acbf --- /dev/null +++ b/src/Tinkoff.ISA.SchedulerUI/Tinkoff.ISA.SchedulerUI.csproj @@ -0,0 +1,32 @@ + + + + netcoreapp2.2 + + + + + + + + + + + + + PreserveNewest + + + + + + + + + + + + + + + diff --git a/src/Tinkoff.ISA.SchedulerUI/appsettings.DevDocker.json b/src/Tinkoff.ISA.SchedulerUI/appsettings.DevDocker.json new file mode 100644 index 0000000..4f78d18 --- /dev/null +++ b/src/Tinkoff.ISA.SchedulerUI/appsettings.DevDocker.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "SerilogLogLevel": "Debug", + "SystemLogLevel": "Warning", + "LogsFolder": "./logs" + }, + "ConnectionStrings": { + "MongoDb": "mongodb://mongodb:27017/isa" + } +} diff --git a/src/Tinkoff.ISA.SchedulerUI/appsettings.Prod.json b/src/Tinkoff.ISA.SchedulerUI/appsettings.Prod.json new file mode 100644 index 0000000..d07ac45 --- /dev/null +++ b/src/Tinkoff.ISA.SchedulerUI/appsettings.Prod.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "SerilogLogLevel": "Information", + "SystemLogLevel": "Warning", + "LogsFolder": "../logs" + }, + "ConnectionStrings": { + "MongoDb": "" + } +} diff --git a/src/Tinkoff.ISA.SchedulerUI/appsettings.QA.json b/src/Tinkoff.ISA.SchedulerUI/appsettings.QA.json new file mode 100644 index 0000000..e148d5c --- /dev/null +++ b/src/Tinkoff.ISA.SchedulerUI/appsettings.QA.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "SerilogLogLevel": "Debug", + "SystemLogLevel": "Warning", + "LogsFolder": "./logs" + }, + "ConnectionStrings": { + "MongoDb": "" + } +} \ No newline at end of file diff --git a/src/Tinkoff.ISA.SchedulerUI/appsettings.json b/src/Tinkoff.ISA.SchedulerUI/appsettings.json new file mode 100644 index 0000000..114060e --- /dev/null +++ b/src/Tinkoff.ISA.SchedulerUI/appsettings.json @@ -0,0 +1,10 @@ +{ + "Logging": { + "SerilogLogLevel": "Debug", + "SystemLogLevel": "Warning", + "LogsFolder": "./logs" + }, + "ConnectionStrings": { + "MongoDb": "mongodb://localhost:27017/isa" + } +} diff --git a/src/Tinkoff.ISA.sln b/src/Tinkoff.ISA.sln index 8d0f48e..658e9b6 100644 --- a/src/Tinkoff.ISA.sln +++ b/src/Tinkoff.ISA.sln @@ -69,6 +69,8 @@ ProjectSection(SolutionItems) = preProject ..\README.md = ..\README.md EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tinkoff.ISA.SchedulerUI", "Tinkoff.ISA.SchedulerUI\Tinkoff.ISA.SchedulerUI.csproj", "{FD1C554F-4D10-49E4-9243-C727F42C18FF}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -111,6 +113,10 @@ Global {8E1466A2-F07A-4C04-82D3-7BD2FD1F8654}.Debug|Any CPU.Build.0 = Debug|Any CPU {8E1466A2-F07A-4C04-82D3-7BD2FD1F8654}.Release|Any CPU.ActiveCfg = Release|Any CPU {8E1466A2-F07A-4C04-82D3-7BD2FD1F8654}.Release|Any CPU.Build.0 = Release|Any CPU + {FD1C554F-4D10-49E4-9243-C727F42C18FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FD1C554F-4D10-49E4-9243-C727F42C18FF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FD1C554F-4D10-49E4-9243-C727F42C18FF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FD1C554F-4D10-49E4-9243-C727F42C18FF}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/Tinkoff.ISA.sln.DotSettings b/src/Tinkoff.ISA.sln.DotSettings new file mode 100644 index 0000000..2fb8ca1 --- /dev/null +++ b/src/Tinkoff.ISA.sln.DotSettings @@ -0,0 +1,3 @@ + + True + True \ No newline at end of file From 42d5b61353b1d7aa235aba56fe3d3658a5d61eed Mon Sep 17 00:00:00 2001 From: Vladislav Ma-iu-shan Date: Tue, 3 Sep 2019 01:02:35 +0300 Subject: [PATCH 2/2] C# upgraded to 7.1 to make async main work --- src/Tinkoff.ISA.API/Tinkoff.ISA.API.csproj | 1 + .../Tinkoff.ISA.AppLayer.UnitTests.csproj | 1 + src/Tinkoff.ISA.AppLayer/Tinkoff.ISA.AppLayer.csproj | 1 + src/Tinkoff.ISA.DAL.UnitTests/Tinkoff.ISA.DAL.UnitTests.csproj | 2 +- src/Tinkoff.ISA.DAL/Tinkoff.ISA.DAL.csproj | 1 + src/Tinkoff.ISA.Domain/Tinkoff.ISA.Domain.csproj | 1 + .../Tinkoff.ISA.Infrastructure.csproj | 1 + .../Tinkoff.ISA.Scheduler.UnitTests.csproj | 2 +- src/Tinkoff.ISA.Scheduler/Tinkoff.ISA.Scheduler.csproj | 1 + src/Tinkoff.ISA.SchedulerUI/Tinkoff.ISA.SchedulerUI.csproj | 1 + 10 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Tinkoff.ISA.API/Tinkoff.ISA.API.csproj b/src/Tinkoff.ISA.API/Tinkoff.ISA.API.csproj index 28cd4cd..57e00b7 100644 --- a/src/Tinkoff.ISA.API/Tinkoff.ISA.API.csproj +++ b/src/Tinkoff.ISA.API/Tinkoff.ISA.API.csproj @@ -2,6 +2,7 @@ netcoreapp2.2 + 7.1 Tinkoff.ISA.API diff --git a/src/Tinkoff.ISA.AppLayer.UnitTests/Tinkoff.ISA.AppLayer.UnitTests.csproj b/src/Tinkoff.ISA.AppLayer.UnitTests/Tinkoff.ISA.AppLayer.UnitTests.csproj index 94c20a4..ee09b2d 100644 --- a/src/Tinkoff.ISA.AppLayer.UnitTests/Tinkoff.ISA.AppLayer.UnitTests.csproj +++ b/src/Tinkoff.ISA.AppLayer.UnitTests/Tinkoff.ISA.AppLayer.UnitTests.csproj @@ -3,6 +3,7 @@ Exe netcoreapp2.2 + 7.1 Tinkoff.ISA.AppLayer.UnitTests diff --git a/src/Tinkoff.ISA.AppLayer/Tinkoff.ISA.AppLayer.csproj b/src/Tinkoff.ISA.AppLayer/Tinkoff.ISA.AppLayer.csproj index 3a7c956..e6d2970 100644 --- a/src/Tinkoff.ISA.AppLayer/Tinkoff.ISA.AppLayer.csproj +++ b/src/Tinkoff.ISA.AppLayer/Tinkoff.ISA.AppLayer.csproj @@ -2,6 +2,7 @@ netcoreapp2.2 + 7.1 Tinkoff.ISA.AppLayer diff --git a/src/Tinkoff.ISA.DAL.UnitTests/Tinkoff.ISA.DAL.UnitTests.csproj b/src/Tinkoff.ISA.DAL.UnitTests/Tinkoff.ISA.DAL.UnitTests.csproj index 2d7c6dc..11b7945 100644 --- a/src/Tinkoff.ISA.DAL.UnitTests/Tinkoff.ISA.DAL.UnitTests.csproj +++ b/src/Tinkoff.ISA.DAL.UnitTests/Tinkoff.ISA.DAL.UnitTests.csproj @@ -2,7 +2,7 @@ netcoreapp2.2 - + 7.1 false Tinkoff.ISA.DAL.UnitTests diff --git a/src/Tinkoff.ISA.DAL/Tinkoff.ISA.DAL.csproj b/src/Tinkoff.ISA.DAL/Tinkoff.ISA.DAL.csproj index 3cfb1d4..ff3550f 100644 --- a/src/Tinkoff.ISA.DAL/Tinkoff.ISA.DAL.csproj +++ b/src/Tinkoff.ISA.DAL/Tinkoff.ISA.DAL.csproj @@ -2,6 +2,7 @@ netcoreapp2.2 + 7.1 Tinkoff.ISA.DAL diff --git a/src/Tinkoff.ISA.Domain/Tinkoff.ISA.Domain.csproj b/src/Tinkoff.ISA.Domain/Tinkoff.ISA.Domain.csproj index 35e239f..00d72de 100644 --- a/src/Tinkoff.ISA.Domain/Tinkoff.ISA.Domain.csproj +++ b/src/Tinkoff.ISA.Domain/Tinkoff.ISA.Domain.csproj @@ -2,6 +2,7 @@ netcoreapp2.2 + 7.1 diff --git a/src/Tinkoff.ISA.Infrastructure/Tinkoff.ISA.Infrastructure.csproj b/src/Tinkoff.ISA.Infrastructure/Tinkoff.ISA.Infrastructure.csproj index f0a1a76..8be1bb2 100644 --- a/src/Tinkoff.ISA.Infrastructure/Tinkoff.ISA.Infrastructure.csproj +++ b/src/Tinkoff.ISA.Infrastructure/Tinkoff.ISA.Infrastructure.csproj @@ -2,6 +2,7 @@ netcoreapp2.2 + 7.1 Tinkoff.ISA.Infrastructure diff --git a/src/Tinkoff.ISA.Scheduler.UnitTests/Tinkoff.ISA.Scheduler.UnitTests.csproj b/src/Tinkoff.ISA.Scheduler.UnitTests/Tinkoff.ISA.Scheduler.UnitTests.csproj index 7864484..2447f9a 100644 --- a/src/Tinkoff.ISA.Scheduler.UnitTests/Tinkoff.ISA.Scheduler.UnitTests.csproj +++ b/src/Tinkoff.ISA.Scheduler.UnitTests/Tinkoff.ISA.Scheduler.UnitTests.csproj @@ -2,7 +2,7 @@ netcoreapp2.2 - + 7.1 false Tinkoff.ISA.Scheduler.UnitTests diff --git a/src/Tinkoff.ISA.Scheduler/Tinkoff.ISA.Scheduler.csproj b/src/Tinkoff.ISA.Scheduler/Tinkoff.ISA.Scheduler.csproj index f62143d..a228ba1 100644 --- a/src/Tinkoff.ISA.Scheduler/Tinkoff.ISA.Scheduler.csproj +++ b/src/Tinkoff.ISA.Scheduler/Tinkoff.ISA.Scheduler.csproj @@ -3,6 +3,7 @@ Exe netcoreapp2.2 + 7.1 Tinkoff.ISA.Scheduler diff --git a/src/Tinkoff.ISA.SchedulerUI/Tinkoff.ISA.SchedulerUI.csproj b/src/Tinkoff.ISA.SchedulerUI/Tinkoff.ISA.SchedulerUI.csproj index 730acbf..ca32307 100644 --- a/src/Tinkoff.ISA.SchedulerUI/Tinkoff.ISA.SchedulerUI.csproj +++ b/src/Tinkoff.ISA.SchedulerUI/Tinkoff.ISA.SchedulerUI.csproj @@ -2,6 +2,7 @@ netcoreapp2.2 + 7.1