Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,27 +1,35 @@
using Quartz.Plugins.RecentHistory;
using Quartz.Plugins.RecentHistory.Impl;
using TransactionProcessing.SchedulerService.Jobs.Jobs;

namespace TransactionProcessing.SchedulerService
{
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Jobs;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Data.SqlClient;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using NLog.Extensions.Logging;
using Quartz;
using Quartz.Impl;
using Quartz.Impl.AdoJobStore.Common;
using Quartz.Impl.Matchers;
using Quartz.Spi;
using Shared.Logger;
using SilkierQuartz;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.Common;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using ILogger = Microsoft.Extensions.Logging.ILogger;
using SetupBuilderExtensions = NLog.SetupBuilderExtensions;

Expand All @@ -42,9 +50,6 @@ public Startup(IWebHostEnvironment webHostEnvironment){

Startup.Configuration = builder.Build();
Startup.WebHostEnvironment = webHostEnvironment;

String connectionString = Startup.Configuration.GetConnectionString("SchedulerReadModel");
Startup.AddOrUpdateConnectionString("SchedulerReadModel", connectionString);
}

#endregion
Expand All @@ -59,27 +64,6 @@ public Startup(IWebHostEnvironment webHostEnvironment){

#region Methods

public static void AddOrUpdateConnectionString(String name,
String connectionString){
try{
Configuration configFile = System.Configuration.ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
ConnectionStringSettingsCollection settings = configFile.ConnectionStrings.ConnectionStrings;

if (settings[name] == null){
settings.Add(new ConnectionStringSettings(name, connectionString));
}
else{
settings[name].ConnectionString = connectionString;
}

configFile.Save(ConfigurationSaveMode.Modified);
System.Configuration.ConfigurationManager.RefreshSection(configFile.AppSettings.SectionInformation.Name);
}
catch(ConfigurationErrorsException){
Console.WriteLine("Error writing connection string");
}
}

public void Configure(IApplicationBuilder app,
IWebHostEnvironment env, ILoggerFactory loggerFactory)
{
Expand Down Expand Up @@ -110,28 +94,38 @@ public void Configure(IApplicationBuilder app,
app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); });
}



public void ConfigureServices(IServiceCollection services){
services.AddRazorPages();

this.RegisterJobs(services);

IScheduler scheduler = StdSchedulerFactory.GetDefaultScheduler().Result;
services.AddScheduler(Configuration);

var serviceProvider = services.BuildServiceProvider();
ISchedulerFactory schedulerFactory = serviceProvider.GetRequiredService<ISchedulerFactory>();

IScheduler scheduler = schedulerFactory.GetScheduler().Result;
IExecutionHistoryStore store = new InProcExecutionHistoryStore();
scheduler.Context.SetExecutionHistoryStore(store);

services.AddSilkierQuartz(s => {
s.VirtualPathRoot = "/quartz";
s.UseLocalTime = true;
s.DefaultDateFormat = "yyyy-MM-dd";
s.DefaultTimeFormat = "HH:mm:ss";
s.Scheduler = scheduler;
},

},
a => { a.AccessRequirement = SilkierQuartzAuthenticationOptions.SimpleAccessRequirement.AllowAnonymous; });
}

private void RegisterJobs(IServiceCollection services)
{
Type type = typeof(BaseJob);
IEnumerable<Type> jobs = AppDomain.CurrentDomain.GetAssemblies().SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p)
.Where(p => type.IsAssignableFrom(p)
&& p.IsInterface == false
&& p.IsAbstract == false);

Expand All @@ -143,4 +137,121 @@ private void RegisterJobs(IServiceCollection services)

#endregion
}

public class CustomSqlServerConnectionProvider : IDbProvider
{
private readonly ILogger<CustomSqlServerConnectionProvider> logger;
private readonly IConfiguration configuration;

public CustomSqlServerConnectionProvider(
ILogger<CustomSqlServerConnectionProvider> logger,
IConfiguration configuration)
{
this.logger = logger;
this.configuration = configuration;
Metadata = new DbMetadata
{
AssemblyName = typeof(SqlConnection).AssemblyQualifiedName,
BindByName = true,
CommandType = typeof(SqlCommand),
ConnectionType = typeof(SqlConnection),
DbBinaryTypeName = "VarBinary",
ExceptionType = typeof(SqlException),
ParameterDbType = typeof(SqlDbType),
ParameterDbTypePropertyName = "SqlDbType",
ParameterNamePrefix = "@",
ParameterType = typeof(SqlParameter),
UseParameterNamePrefixInParameterCollection = true
};
Metadata.Init();
}

public void Initialize()
{
logger.LogInformation("Initializing");
}

public DbCommand CreateCommand()
{
return new SqlCommand();
}

public DbConnection CreateConnection()
{
return new SqlConnection(ConnectionString);
}

public string ConnectionString
{
get => configuration.GetConnectionString("Quartz")!;
set => throw new NotImplementedException();
}

public DbMetadata Metadata { get; }

public void Shutdown()
{
logger.LogInformation("Shutting down");
}
}

public static class Extensions {
public static IServiceCollection AddScheduler(this IServiceCollection services, IConfiguration configuration)
{
// base configuration for DI, read from appSettings.json
services.Configure<QuartzOptions>(configuration.GetSection("Quartz"));

// if you are using persistent job store, you might want to alter some options
services.Configure<QuartzOptions>(options =>
{
options.Scheduling.IgnoreDuplicates = true; // default: false
options.Scheduling.OverWriteExistingData = true; // default: true
});

// custom connection provider
services.AddSingleton<IDbProvider, CustomSqlServerConnectionProvider>();

services.AddQuartz(q => {
// handy when part of cluster or you want to otherwise identify multiple schedulers
q.SchedulerId = "Scheduler-Core";

// you can control whether job interruption happens for running jobs when scheduler is shutting down
q.InterruptJobsOnShutdown = true;

// when QuartzHostedServiceOptions.WaitForJobsToComplete = true or scheduler.Shutdown(waitForJobsToComplete: true)
q.InterruptJobsOnShutdownWithWait = true;

// we can change from the default of 1
q.MaxBatchSize = 5;

// we take this from appsettings.json, just show it's possible
q.SchedulerName = "Txn Processing Scheduler";

// these are the defaults
q.UseSimpleTypeLoader();
q.UsePersistentStore(s => {
s.PerformSchemaValidation = false; // default
//s.UseProperties = true; // preferred, but not default
s.RetryInterval = TimeSpan.FromSeconds(15);
s.UseSqlServer(sqlServer =>
{
sqlServer.ConnectionString = configuration.GetConnectionString("Quartz");

// this is the default
sqlServer.TablePrefix = "QRTZ_";
});
s.UseNewtonsoftJsonSerializer();
});
q.UseDefaultThreadPool(maxConcurrency: 10);
q.UseTimeZoneConverter();

ExecutionHistoryPlugin p = new ExecutionHistoryPlugin();
p.StoreType = Type.GetType("Quartz.Plugins.RecentHistory.Impl.InProcExecutionHistoryStore,Quartz.Plugins.RecentHistory");
p.Name = "ExecutionHistoryPlugin";
q.AddJobListener<ExecutionHistoryPlugin>(p);
});

return services;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@
</ItemGroup>

<ItemGroup>
<Content Update="quartz.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="TransactionProcessing.SchedulerService.dll.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<connectionStrings>
<add name="SchedulerReadModel" connectionString="server=127.0.0.1;user id=sa;password=sp1ttal;database=Scheduler;Encrypt=false" />
<add name="X" connectionString="server=127.0.0.1;user id=sa;password=sp1ttal;database=Scheduler;Encrypt=false" />
</connectionStrings>
</configuration>
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
{
"ConnectionStrings": {
"SchedulerReadModel": "server=127.0.0.1;user id=sa;password=Sc0tland;database=Scheduler;Encrypt=True;TrustServerCertificate=True"
}
"Quartz": "server=127.0.0.1;user id=sa;password=Sc0tland;database=Scheduler;Encrypt=True;TrustServerCertificate=True"
},
//"Quartz": {
// "quartz.scheduler.instanceName": "Txn Processing Scheduler",
// "quartz.dataSource.JobStore.provider": "SqlServer",
// //"quartz.dataSource.JobStore.connectionStringName": "X",
// "quartz.jobStore.useProperties" :true,
// "quartz.jobStore.tablePrefix": "QRTZ_",
// //"quartz.jobStore.type": "Quartz.Impl.AdoJobStore.JobStoreTX,Quartz",
// "quartz.jobStore.performSchemaValidation":false,
// "quartz.serializer.type": "json",
// //"quartz.jobStore.dataSource": "JobStore",
// //"quartz.jobStore.driverDelegateType": "Quartz.Impl.AdoJobStore.SqlServerDelegate,Quartz",
// "quartz.plugin.recentHistory.type": "Quartz.Plugins.RecentHistory.ExecutionHistoryPlugin,Quartz.Plugins.RecentHistory",
// "quartz.plugin.recentHistory.storeType": "Quartz.Plugins.RecentHistory.Impl.InProcExecutionHistoryStore,Quartz.Plugins.RecentHistory",
// "quartz.plugin.timeZoneConverter.type": "Quartz.Plugin.TimeZoneConverter.TimeZoneConverterPlugin,Quartz.Plugins.TimeZoneConverter"
//}
}

This file was deleted.