Commit 0221e022f5bf1a564df833e7bb8dcf1bc5d23c63
1 parent
88b98a18
Vrh.Web.Reporting v1.1.0.0
Vrh.iScheduler v3.3.0.0
Showing
6 changed files
with
399 additions
and
191 deletions
Show diff stats
Vrh.Web.Reporting/Global.asax.cs
@@ -16,20 +16,23 @@ using Hangfire; | @@ -16,20 +16,23 @@ using Hangfire; | ||
16 | using Microsoft.Web.Administration; | 16 | using Microsoft.Web.Administration; |
17 | using Vrh.iScheduler; | 17 | using Vrh.iScheduler; |
18 | using Vrh.Logger; | 18 | using Vrh.Logger; |
19 | -using Vrh.Web.HangfireBootstrapperNS; | 19 | +using Vrh.Web.WebServerHostedServiceStarterNS; |
20 | namespace Vrh.Web.Reporting | 20 | namespace Vrh.Web.Reporting |
21 | { | 21 | { |
22 | public class MvcApplication : System.Web.HttpApplication | 22 | public class MvcApplication : System.Web.HttpApplication |
23 | { | 23 | { |
24 | protected void Application_Start() | 24 | protected void Application_Start() |
25 | { | 25 | { |
26 | + Thread.Sleep(20000); | ||
26 | (new DCLogEntry(LogLevel.Information, $"{typeof(MvcApplication).FullName}.{System.Reflection.MethodBase.GetCurrentMethod().Name}")).Write(); | 27 | (new DCLogEntry(LogLevel.Information, $"{typeof(MvcApplication).FullName}.{System.Reflection.MethodBase.GetCurrentMethod().Name}")).Write(); |
27 | AreaRegistration.RegisterAllAreas(); | 28 | AreaRegistration.RegisterAllAreas(); |
28 | FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); | 29 | FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); |
29 | RouteConfig.RegisterRoutes(RouteTable.Routes); | 30 | RouteConfig.RegisterRoutes(RouteTable.Routes); |
30 | BundleConfig.RegisterBundles(BundleTable.Bundles); | 31 | BundleConfig.RegisterBundles(BundleTable.Bundles); |
31 | 32 | ||
32 | - HangfireBootstrapper.Init(Vrh.iScheduler.Monitor.InitHangfire); | 33 | + WebServerHostedServiceStarter.Init(typeof(Vrh.iScheduler.WAHostedMonitorHangfire)); |
34 | + //IISHostedServiceStarter.Init(Vrh.iScheduler.WAHostedMonitorHangfire.Start, Vrh.iScheduler.WAHostedMonitorHangfire.Stop); | ||
35 | + //IISHostedServiceStarter.Init(Vrh.iScheduler.WAHostedMonitor.Start, Vrh.iScheduler.WAHostedMonitor.Stop); | ||
33 | 36 | ||
34 | //Vrh.Web.Menu inicializáló beállításai | 37 | //Vrh.Web.Menu inicializáló beállításai |
35 | Vrh.Web.Menu.Global.CustomerLogo = "~/Content/Images/Menu_LearLogo.jpg"; | 38 | Vrh.Web.Menu.Global.CustomerLogo = "~/Content/Images/Menu_LearLogo.jpg"; |
@@ -39,7 +42,7 @@ namespace Vrh.Web.Reporting | @@ -39,7 +42,7 @@ namespace Vrh.Web.Reporting | ||
39 | protected void Application_End(object sender, EventArgs e) | 42 | protected void Application_End(object sender, EventArgs e) |
40 | { | 43 | { |
41 | (new DCLogEntry(LogLevel.Information, $"{typeof(MvcApplication).FullName}.{System.Reflection.MethodBase.GetCurrentMethod().Name}")).Write(); | 44 | (new DCLogEntry(LogLevel.Information, $"{typeof(MvcApplication).FullName}.{System.Reflection.MethodBase.GetCurrentMethod().Name}")).Write(); |
42 | - HangfireBootstrapper.Stop(); | 45 | + WebServerHostedServiceStarter.Stop(); |
43 | } | 46 | } |
44 | /// <summary> | 47 | /// <summary> |
45 | /// Ha "Internal Server Error 500" üzenetet kapsz, akkor ide érdemes a hívás előtt betenni egy break point-ot. | 48 | /// Ha "Internal Server Error 500" üzenetet kapsz, akkor ide érdemes a hívás előtt betenni egy break point-ot. |
Vrh.Web.Reporting/Properties/AssemblyInfo.cs
@@ -36,6 +36,6 @@ using System.Runtime.InteropServices; | @@ -36,6 +36,6 @@ using System.Runtime.InteropServices; | ||
36 | // You can specify all the values or you can default the Build and Revision Numbers | 36 | // You can specify all the values or you can default the Build and Revision Numbers |
37 | // by using the '*' as shown below: | 37 | // by using the '*' as shown below: |
38 | // [assembly: AssemblyVersion("1.0.*")] | 38 | // [assembly: AssemblyVersion("1.0.*")] |
39 | -[assembly: AssemblyVersion("1.0.0.0")] | ||
40 | -[assembly: AssemblyFileVersion("1.0.0.0")] | ||
41 | -[assembly: AssemblyInformationalVersion("1.0.0")] | 39 | +[assembly: AssemblyVersion("1.1.0.0")] |
40 | +[assembly: AssemblyFileVersion("1.1.0.0")] | ||
41 | +[assembly: AssemblyInformationalVersion("1.1.0")] |
Vrh.Web.Reporting/Vrh.Web.Reporting.csproj
@@ -344,7 +344,7 @@ | @@ -344,7 +344,7 @@ | ||
344 | <Compile Include="Global.asax.cs"> | 344 | <Compile Include="Global.asax.cs"> |
345 | <DependentUpon>Global.asax</DependentUpon> | 345 | <DependentUpon>Global.asax</DependentUpon> |
346 | </Compile> | 346 | </Compile> |
347 | - <Compile Include="HangfireBootstrapper.cs" /> | 347 | + <Compile Include="WebServerHostedServiceStarter.cs" /> |
348 | <Compile Include="Properties\AssemblyInfo.cs" /> | 348 | <Compile Include="Properties\AssemblyInfo.cs" /> |
349 | </ItemGroup> | 349 | </ItemGroup> |
350 | <ItemGroup> | 350 | <ItemGroup> |
Vrh.Web.Reporting/HangfireBootstrapper.cs renamed to Vrh.Web.Reporting/WebServerHostedServiceStarter.cs
@@ -17,68 +17,130 @@ using Hangfire; | @@ -17,68 +17,130 @@ using Hangfire; | ||
17 | using Microsoft.Web.Administration; | 17 | using Microsoft.Web.Administration; |
18 | using Vrh.Logger; | 18 | using Vrh.Logger; |
19 | using System.Configuration; | 19 | using System.Configuration; |
20 | +using System.Reflection; | ||
20 | 21 | ||
21 | -namespace Vrh.Web.HangfireBootstrapperNS | 22 | +namespace Vrh.Web.WebServerHostedServiceStarterNS |
22 | { | 23 | { |
23 | - public class HangfireBootstrapper : IRegisteredObject, IProcessHostPreloadClient | 24 | + /// <summary> |
25 | + /// TODO: ezt egy olyan helyre kellene rakni, ahol mindenhova referálható (az Vrh.Interfaces.dll egyre jobb ötletnek tűnik! Kár hogy nem hallgattam Antira!) | ||
26 | + /// </summary> | ||
27 | + public interface IWebServerHostedServiceStarter | ||
28 | + { | ||
29 | + void Start(); | ||
30 | + void Stop(); | ||
31 | + } | ||
32 | + public class WebServerHostedServiceStarter : IRegisteredObject, IProcessHostPreloadClient | ||
24 | { | 33 | { |
25 | /// <summary> | 34 | /// <summary> |
26 | - /// Egy külső iniciátort hregisztrálására szolgál, amelyben lehetőség van a | ||
27 | - /// paraméterként megkapott BackgroundJobServer-re ütemezett feladatokat definiálni. | 35 | + /// Egy hosted service elindítását, paraméterezését, konfigurálását és a külső iniciátor meghívást végzi. |
28 | /// </summary> | 36 | /// </summary> |
29 | - public static void InitConfig(Action<object> externalinitializer=null) | 37 | + /// <param name="tt"> |
38 | + /// az indító és leállító metódusokat tartalmazó osztály; | ||
39 | + /// IWebServerHostedServiceStarter interfészt meg kell valósítsa, bár ezt nem ellenőrzi, csak azt, | ||
40 | + /// hogy az ezt jelentő 'public static void Start();' és 'public static void Stop();' metódusok megvannak-e. | ||
41 | + /// </param> | ||
42 | + public static void Init(Type tt) | ||
30 | { | 43 | { |
31 | - if (externalinitializer == null) return; | ||
32 | - var le = new DCLogEntry(LogLevel.Information, $"{typeof(HangfireBootstrapper).FullName}.{System.Reflection.MethodBase.GetCurrentMethod().Name}"); | ||
33 | - try { _InitConfig(externalinitializer, le); } | ||
34 | - catch (Exception ex) { le.AddExceptionResult(ex);le.SetLogLevel(LogLevel.Error); } | 44 | + var le = new DCLogEntry(LogLevel.Information, $"{typeof(WebServerHostedServiceStarter).FullName}.{nameof(Init)}"); |
45 | + try | ||
46 | + { | ||
47 | + //if (!tt.GetInterfaces().Contains(typeof(IWebServerHostedServiceStarter))) throw new InterfaceErrorApplicationException(tt.FullName); | ||
48 | + | ||
49 | + _SetupAutoStart<WebServerHostedServiceStarter>(le: le); | ||
50 | + | ||
51 | + var startmethod = tt.GetMethod(nameof(IWebServerHostedServiceStarter .Start), BindingFlags.Public | BindingFlags.Static); | ||
52 | + var stopmethod = tt.GetMethod(nameof(IWebServerHostedServiceStarter .Stop), BindingFlags.Public | BindingFlags.Static); | ||
53 | + if (startmethod == null || startmethod.ReturnType != typeof(void) || startmethod.GetParameters().Count() > 0) throw new InterfaceErrorApplicationException(tt.FullName,nameof(IWebServerHostedServiceStarter .Start)); | ||
54 | + if (stopmethod == null || stopmethod.ReturnType != typeof(void) || stopmethod.GetParameters().Count() > 0) throw new InterfaceErrorApplicationException(tt.FullName, nameof(IWebServerHostedServiceStarter .Stop)); | ||
55 | + IISHostedServiceStarterInstance._RegisterExternalInitializer((Action)Delegate.CreateDelegate(typeof(Action), startmethod), (Action)Delegate.CreateDelegate(typeof(Action), stopmethod), le); | ||
56 | + | ||
57 | + IISHostedServiceStarterInstance._StartExternalInitializers(le); | ||
58 | + } | ||
59 | + catch (InterfaceErrorApplicationException ex) { le.AddExceptionResult(ex); le.SetLogLevel(LogLevel.Error); } | ||
60 | + catch (Exception ex) { le.AddExceptionResult(ex); le.SetLogLevel(LogLevel.Error); } | ||
35 | finally { le.Write(); } | 61 | finally { le.Write(); } |
36 | } | 62 | } |
37 | - private static void _InitConfig(Action<object> externalinitializer, DCLogEntry le) | 63 | + |
64 | + /// <summary> | ||
65 | + /// Egy hosted service elindítását, paraméterezését, konfigurálását és külső iniciátorok meghívást végzi. | ||
66 | + /// </summary> | ||
67 | + /// <param name="externalinitializerstartmethod">az indító metódus</param> | ||
68 | + /// <param name="externalinitializerstopmethod">a leállító metódus</param> | ||
69 | + public static void Init(List<Type> ttList) | ||
38 | { | 70 | { |
39 | - if (externalinitializer != null) | 71 | + var le = new DCLogEntry(LogLevel.Information, $"{typeof(WebServerHostedServiceStarter).FullName}.{nameof(Init)}"); |
72 | + try | ||
40 | { | 73 | { |
41 | - externalinitializerList.Add(externalinitializer); | ||
42 | - le.AddDataField("ADD external initializer", $"{externalinitializer.Method.DeclaringType.FullName}.{externalinitializer.Method.Name}()"); | 74 | + //if (!tt.GetInterfaces().Contains(typeof(IInterface))) throw new Exception ($"{tt.FullName} does not implement {nameof(IInterface)}!"); |
75 | + | ||
76 | + _SetupAutoStart<WebServerHostedServiceStarter>(le: le); | ||
77 | + foreach (var tt in ttList) | ||
78 | + { | ||
79 | + try | ||
80 | + { | ||
81 | + var startmethod = tt.GetMethod(nameof(IWebServerHostedServiceStarter .Start), BindingFlags.Public | BindingFlags.Static); | ||
82 | + var stopmethod = tt.GetMethod(nameof(IWebServerHostedServiceStarter .Stop), BindingFlags.Public | BindingFlags.Static); | ||
83 | + if (startmethod == null || startmethod.ReturnType != typeof(void) || startmethod.GetParameters().Count() > 0) throw new InterfaceErrorApplicationException(tt.FullName, nameof(IWebServerHostedServiceStarter .Start)); | ||
84 | + if (stopmethod == null || stopmethod.ReturnType != typeof(void) || stopmethod.GetParameters().Count() > 0) throw new InterfaceErrorApplicationException(tt.FullName, nameof(IWebServerHostedServiceStarter .Stop)); | ||
85 | + IISHostedServiceStarterInstance._RegisterExternalInitializer((Action)Delegate.CreateDelegate(typeof(Action), startmethod), (Action)Delegate.CreateDelegate(typeof(Action), stopmethod), le); | ||
86 | + } | ||
87 | + catch (InterfaceErrorApplicationException ex) { le.AddExceptionResult(ex); le.SetLogLevel(LogLevel.Error); } | ||
88 | + } | ||
89 | + IISHostedServiceStarterInstance._StartExternalInitializers(le); | ||
43 | } | 90 | } |
91 | + catch (Exception ex) { le.AddExceptionResult(ex); le.SetLogLevel(LogLevel.Error); } | ||
92 | + finally { le.Write(); } | ||
93 | + } | ||
94 | + | ||
95 | + private class InterfaceErrorApplicationException : ApplicationException | ||
96 | + { | ||
97 | + public InterfaceErrorApplicationException(string typename, string methodname) : base($"Class '{typename}' does not implement 'public static void {methodname}()' action!") { } | ||
98 | + public InterfaceErrorApplicationException(string typename) : base($"Class '{typename}' does not implement '{nameof(IWebServerHostedServiceStarter)}' interface!") { } | ||
44 | } | 99 | } |
45 | /// <summary> | 100 | /// <summary> |
46 | - /// A Hangfire rendszer elindítását, paraméterezését, konfigurálását és a külső iniciátorok meghívást végzi. | 101 | + /// Egy hosted service elindítását, paraméterezését, konfigurálását és a külső iniciátor meghívást végzi. |
47 | /// </summary> | 102 | /// </summary> |
48 | - const string HANGFIRE = "HangfireBootstrapper:"; | ||
49 | - const string HANGFIREDISABLEAUTOSTART = HANGFIRE + "disableautostart"; | ||
50 | - const bool DISABLEAUTOSTARTDEFAULT = false; | ||
51 | - const string HANGFIREDBCONNECTIONSTRING = HANGFIRE + "dbconnectionstring"; | ||
52 | - const string HANGFIRESQLDBCONNECTIONSTRINGNAMEDEFAULT = "HANGFIRESQLDB"; | ||
53 | - public static void Init(Action<object> externalinitializer=null) | 103 | + /// <param name="externalinitializerstartmethod">az indító metódus</param> |
104 | + /// <param name="externalinitializerstopmethod">a leállító metódus</param> | ||
105 | + public static void Init(Action externalinitializerstartmethod, Action externalinitializerstopmethod) | ||
54 | { | 106 | { |
55 | - var le = new DCLogEntry(LogLevel.Information, $"{typeof(HangfireBootstrapper).FullName}.{System.Reflection.MethodBase.GetCurrentMethod().Name}"); | 107 | + var le = new DCLogEntry(LogLevel.Information, $"{typeof(WebServerHostedServiceStarter).FullName}.{nameof(Init)}"); |
56 | try | 108 | try |
57 | { | 109 | { |
58 | - bool DisablAautoStart; | ||
59 | - string disableautostartstring = ConfigurationManager.AppSettings[HANGFIREDISABLEAUTOSTART]; | ||
60 | - if (string.IsNullOrWhiteSpace(disableautostartstring)) DisablAautoStart = DISABLEAUTOSTARTDEFAULT; | ||
61 | - else if (disableautostartstring.ToLower() == bool.TrueString.ToLower()) DisablAautoStart = true; | ||
62 | - else if (disableautostartstring.ToLower() != bool.FalseString.ToLower()) DisablAautoStart = false; | ||
63 | - else DisablAautoStart = DISABLEAUTOSTARTDEFAULT; | 110 | + _SetupAutoStart<WebServerHostedServiceStarter>(le: le); |
111 | + IISHostedServiceStarterInstance._RegisterExternalInitializer(externalinitializerstartmethod, externalinitializerstopmethod, le); | ||
112 | + IISHostedServiceStarterInstance._StartExternalInitializers(le); | ||
113 | + } | ||
114 | + catch (Exception ex) { le.AddExceptionResult(ex); le.SetLogLevel(LogLevel.Error); } | ||
115 | + finally { le.Write(); } | ||
116 | + } | ||
64 | 117 | ||
65 | - le.AddDataField("DisablAautoStart", DisablAautoStart); | ||
66 | - _InitConfig(externalinitializer, le); | ||
67 | - HangfireBootstrapper.Instance._InstanceInitialize(DisablAautoStart,le); | ||
68 | - ExecuteExternalInitializers(le); | 118 | + /// <summary> |
119 | + /// Több hosted service elindítását, paraméterezését, konfigurálását és a külső iniciátorok meghívást végzi. | ||
120 | + /// </summary> | ||
121 | + public static void Init(List<Tuple<Action, Action>> externalinitializerList) | ||
122 | + { | ||
123 | + var le = new DCLogEntry(LogLevel.Information, $"{typeof(WebServerHostedServiceStarter).FullName}.{nameof(Init)}"); | ||
124 | + try | ||
125 | + { | ||
126 | + _SetupAutoStart<WebServerHostedServiceStarter>(le: le); | ||
127 | + foreach (var ei in externalinitializerList) IISHostedServiceStarterInstance._RegisterExternalInitializer(ei.Item1, ei.Item2, le); | ||
128 | + IISHostedServiceStarterInstance._StartExternalInitializers(le); | ||
69 | } | 129 | } |
70 | catch (Exception ex) { le.AddExceptionResult(ex); le.SetLogLevel(LogLevel.Error); } | 130 | catch (Exception ex) { le.AddExceptionResult(ex); le.SetLogLevel(LogLevel.Error); } |
71 | finally { le.Write(); } | 131 | finally { le.Write(); } |
72 | } | 132 | } |
73 | 133 | ||
74 | /// <summary> | 134 | /// <summary> |
75 | - /// A Hangfire rendszeer leállítását végzi; | 135 | + /// A hosted serviceek leállítását végzi; |
76 | /// Ezt a metódust meg kell hívni a IProcessHostPreloadClient működéséhez! | 136 | /// Ezt a metódust meg kell hívni a IProcessHostPreloadClient működéséhez! |
77 | /// </summary> | 137 | /// </summary> |
78 | public static void Stop() | 138 | public static void Stop() |
79 | { | 139 | { |
80 | - (new DCLogEntry(LogLevel.Information, $"{typeof(HangfireBootstrapper).FullName}.{System.Reflection.MethodBase.GetCurrentMethod().Name}")).Write(); | ||
81 | - HangfireBootstrapper.Instance._Stop(); | 140 | + var le = new DCLogEntry(LogLevel.Information, $"{typeof(WebServerHostedServiceStarter).FullName}.{System.Reflection.MethodBase.GetCurrentMethod().Name}"); |
141 | + try { IISHostedServiceStarterInstance._StopExternalInitializers(le); } | ||
142 | + catch (Exception ex) { le.AddExceptionResult(ex); le.SetLogLevel(LogLevel.Error); } | ||
143 | + finally { le.Write(); } | ||
82 | } | 144 | } |
83 | 145 | ||
84 | /// <summary> | 146 | /// <summary> |
@@ -87,11 +149,11 @@ namespace Vrh.Web.HangfireBootstrapperNS | @@ -87,11 +149,11 @@ namespace Vrh.Web.HangfireBootstrapperNS | ||
87 | /// <param name="parameters"></param> | 149 | /// <param name="parameters"></param> |
88 | public void Preload(string[] parameters) | 150 | public void Preload(string[] parameters) |
89 | { | 151 | { |
90 | - var le = new DCLogEntry(LogLevel.Information, $"{typeof(HangfireBootstrapper).FullName}.{System.Reflection.MethodBase.GetCurrentMethod().Name}"); | 152 | + var le = new DCLogEntry(LogLevel.Information, $"{typeof(WebServerHostedServiceStarter).FullName}.{System.Reflection.MethodBase.GetCurrentMethod().Name}"); |
91 | try | 153 | try |
92 | { | 154 | { |
93 | - _InstanceInitialize(le:le); | ||
94 | - ExecuteExternalInitializers(le); | 155 | + _SetupAutoStart<WebServerHostedServiceStarter>(disablemode: false, le: le); |
156 | + _StartExternalInitializers(le); | ||
95 | le.AddSuccessResult("SUCCESS"); | 157 | le.AddSuccessResult("SUCCESS"); |
96 | } | 158 | } |
97 | catch (Exception ex) { le.AddExceptionResult(ex);le.SetLogLevel(LogLevel.Error); } | 159 | catch (Exception ex) { le.AddExceptionResult(ex);le.SetLogLevel(LogLevel.Error); } |
@@ -101,77 +163,83 @@ namespace Vrh.Web.HangfireBootstrapperNS | @@ -101,77 +163,83 @@ namespace Vrh.Web.HangfireBootstrapperNS | ||
101 | /// <summary> | 163 | /// <summary> |
102 | /// Kell legyen egy publikus paraméter nélküli konstruktor a webapp preload funkcióhoz!!! | 164 | /// Kell legyen egy publikus paraméter nélküli konstruktor a webapp preload funkcióhoz!!! |
103 | /// </summary> | 165 | /// </summary> |
104 | - public HangfireBootstrapper() { } | 166 | + public WebServerHostedServiceStarter() { } |
167 | + | ||
105 | 168 | ||
106 | #region private members | 169 | #region private members |
107 | - private static void ExecuteExternalInitializers(DCLogEntry le) | 170 | + void IRegisteredObject.Stop(bool immediate) { Stop(); } |
171 | + private void _RegisterExternalInitializer(Action externalinitializerstartmethod, Action externalinitializerstopmethod, DCLogEntry le) | ||
108 | { | 172 | { |
109 | - int numofall = externalinitializerList.Count(); | ||
110 | - int counter = externalinitializerList.Count(); | ||
111 | - if (numofall==0) | 173 | + if (externalinitializerstartmethod != null) |
112 | { | 174 | { |
113 | - le.AddDebugField("External initializer","Nothing to initialize!"); | 175 | + externalinitializerList.Add(Tuple.Create(externalinitializerstartmethod, externalinitializerstopmethod)); |
176 | + le?.AddDataField("ADD external initializer START", $"{externalinitializerstartmethod.Method.DeclaringType.FullName}.{externalinitializerstartmethod.Method.Name}()"); | ||
177 | + le?.AddDataField("ADD external initializer STOP", $"{externalinitializerstopmethod.Method.DeclaringType.FullName}.{externalinitializerstopmethod.Method.Name}()"); | ||
114 | } | 178 | } |
115 | - else | 179 | + } |
180 | + private void _StartExternalInitializers(DCLogEntry le) | ||
181 | + { | ||
182 | + lock (ExternalInitializerStarStopLocker) | ||
116 | { | 183 | { |
184 | + int numofall = externalinitializerList.Count(); | ||
185 | + int counter = externalinitializerList.Count(); | ||
186 | + if (numofall == 0) { le.AddDebugField(nameof(_StartExternalInitializers), NOEXTERNALINITIALIZERSAREREGISTERED); return; } | ||
187 | + | ||
188 | + HostingEnvironment.RegisterObject(IISHostedServiceStarterInstance); | ||
117 | foreach (var ei in externalinitializerList) | 189 | foreach (var ei in externalinitializerList) |
118 | { | 190 | { |
119 | - var externalinitializername = $"External initializer: {ei.Method.DeclaringType.FullName}.{ei.Method.Name}()"; | ||
120 | - try { ei.Invoke(HangfireBootstrapper.Instance._backgroundJobServer); le.AddDataField($"{externalinitializername} SUCCESS",$"{counter}of{numofall}"); } | ||
121 | - catch (Exception ex) { le.AddDataField($"{externalinitializername} EXCEPTION", ex.Message); } | 191 | + var externalinitializername = $"External initializer: {ei.Item1.Method.DeclaringType.FullName}.{ei.Item1.Method.Name}()"; |
192 | + try { ei.Item1.Invoke(); le.AddDataField($"{externalinitializername} START SUCCESS", $"{counter}of{numofall}"); } | ||
193 | + catch (Exception ex) { le.AddDataField($"{externalinitializername} START EXCEPTION", ex.Message); } | ||
122 | counter++; | 194 | counter++; |
123 | } | 195 | } |
124 | } | 196 | } |
125 | } | 197 | } |
126 | - | ||
127 | - private void _InstanceInitialize(bool autostartsetupdisable =false,DCLogEntry le=null) | ||
128 | - { | ||
129 | - string HangfireSqlDBConnectionString = ConfigurationManager.AppSettings[HANGFIREDBCONNECTIONSTRING]; | ||
130 | - if (string.IsNullOrWhiteSpace(HangfireSqlDBConnectionString)) HangfireSqlDBConnectionString = HANGFIRESQLDBCONNECTIONSTRINGNAMEDEFAULT; | ||
131 | - le?.AddDataField("HangfireSqlDBConnectionString", HangfireSqlDBConnectionString); | ||
132 | - SetupAutoStart(typeof(HangfireBootstrapper),disablemode:autostartsetupdisable,le:le); | ||
133 | - HangfireBootstrapper.Instance.SqlDBconnectionstring = Vrh.XmlProcessing.ConnectionStringStore.GetSQL(HangfireSqlDBConnectionString); | ||
134 | - HangfireBootstrapper.Instance._Start(); | ||
135 | - } | ||
136 | - | ||
137 | - private static List<Action<object>> externalinitializerList = new List<Action<object>>(); | ||
138 | - private static readonly HangfireBootstrapper Instance = new HangfireBootstrapper(); | ||
139 | - private BackgroundJobServer _backgroundJobServer { get; set; } | ||
140 | - private string SqlDBconnectionstring { get; set; } = null; | ||
141 | - private readonly object _lockObject = new object(); | ||
142 | - private bool _started; | ||
143 | - | ||
144 | - | ||
145 | - private void _Start() | 198 | + private void _StopExternalInitializers(DCLogEntry le) |
146 | { | 199 | { |
147 | - lock (_lockObject) | 200 | + lock (ExternalInitializerStarStopLocker) |
148 | { | 201 | { |
149 | - if (_started) return; | ||
150 | - _started = true; | 202 | + int numofall = externalinitializerList.Count(); |
203 | + int counter = externalinitializerList.Count(); | ||
204 | + if (numofall == 0) { le.AddDebugField(nameof(_StopExternalInitializers), NOEXTERNALINITIALIZERSAREREGISTERED); return; } | ||
151 | 205 | ||
152 | - HostingEnvironment.RegisterObject(this); | ||
153 | - GlobalConfiguration.Configuration | ||
154 | - .UseSqlServerStorage(SqlDBconnectionstring) | ||
155 | - // Specify other options here | ||
156 | - ; | ||
157 | - | ||
158 | - _backgroundJobServer = new BackgroundJobServer(); | 206 | + foreach (var ei in externalinitializerList) |
207 | + { | ||
208 | + var externalinitializername = $"External initializer: {ei.Item2.Method.DeclaringType.FullName}.{ei.Item2.Method.Name}()"; | ||
209 | + try { ei.Item2.Invoke(); le.AddDataField($"{externalinitializername} STOP SUCCESS", $"{counter}of{numofall}"); } | ||
210 | + catch (Exception ex) { le.AddDataField($"{externalinitializername} STOP EXCEPTION", ex.Message); } | ||
211 | + counter++; | ||
212 | + } | ||
213 | + HostingEnvironment.UnregisterObject(IISHostedServiceStarterInstance); | ||
159 | } | 214 | } |
160 | } | 215 | } |
161 | 216 | ||
162 | - private void _Stop() | 217 | + private object ExternalInitializerStarStopLocker = new object(); |
218 | + private static readonly WebServerHostedServiceStarter IISHostedServiceStarterInstance = new WebServerHostedServiceStarter(); | ||
219 | + private static List<Tuple<Action, Action>> externalinitializerList = new List<Tuple<Action, Action>>(); | ||
220 | + private static bool Config_DisablAutoStart | ||
163 | { | 221 | { |
164 | - lock (_lockObject) | 222 | + get |
165 | { | 223 | { |
166 | - if (_backgroundJobServer != null) { _backgroundJobServer.Dispose(); } | ||
167 | - HostingEnvironment.UnregisterObject(this); | 224 | + if (!config_disablautostart.HasValue) |
225 | + { | ||
226 | + string disableautostartstring = ConfigurationManager.AppSettings[DISABLEAUTOSTART]; | ||
227 | + if (string.IsNullOrWhiteSpace(disableautostartstring)) config_disablautostart = DISABLEAUTOSTARTDEFAULT; | ||
228 | + else if (disableautostartstring.ToLower() == bool.TrueString.ToLower()) config_disablautostart = true; | ||
229 | + else if (disableautostartstring.ToLower() != bool.FalseString.ToLower()) config_disablautostart = false; | ||
230 | + else config_disablautostart = DISABLEAUTOSTARTDEFAULT; | ||
231 | + } | ||
232 | + return config_disablautostart.Value; | ||
168 | } | 233 | } |
169 | } | 234 | } |
170 | - | ||
171 | - void IRegisteredObject.Stop(bool immediate) { _Stop(); } | 235 | + private static bool? config_disablautostart = null; |
236 | + private const string IISHOSTEDSERVICESTARTER = "IISHostedServiceStarter:"; | ||
237 | + private const string DISABLEAUTOSTART = IISHOSTEDSERVICESTARTER + "disableautostart"; | ||
238 | + private const bool DISABLEAUTOSTARTDEFAULT = false; | ||
239 | + private const string NOEXTERNALINITIALIZERSAREREGISTERED = "No external initializers are registered!"; | ||
172 | #endregion private members | 240 | #endregion private members |
173 | 241 | ||
174 | - #region private method - SetupAutoStart | 242 | + #region private method - _SetupAutoStart |
175 | /// <summary> | 243 | /// <summary> |
176 | /// Beállítja az autostart és alwaysrunning és a preload paramétereket a megadott websitra, | 244 | /// Beállítja az autostart és alwaysrunning és a preload paramétereket a megadott websitra, |
177 | /// web alkalmazásra és application pool-ra vonatkozóan. | 245 | /// web alkalmazásra és application pool-ra vonatkozóan. |
@@ -204,14 +272,16 @@ namespace Vrh.Web.HangfireBootstrapperNS | @@ -204,14 +272,16 @@ namespace Vrh.Web.HangfireBootstrapperNS | ||
204 | /// <param name="webapplicationname">a web app neve; alapértelmezés:a tartalmazó web app</param> | 272 | /// <param name="webapplicationname">a web app neve; alapértelmezés:a tartalmazó web app</param> |
205 | /// <param name="applicationpoolname">az app pool neve; alapértelmezés:a tartalmazó pool</param> | 273 | /// <param name="applicationpoolname">az app pool neve; alapértelmezés:a tartalmazó pool</param> |
206 | /// <returns></returns> | 274 | /// <returns></returns> |
207 | - private static void SetupAutoStart(Type serviceAutoStartProviderType, string websitename = null, string webapplicationname = null, string applicationpoolname = null, bool disablemode = false, DCLogEntry le = null) | 275 | + private static void _SetupAutoStart<T>(string websitename = null, string webapplicationname = null, string applicationpoolname = null, bool? disablemode = null, DCLogEntry le = null) |
276 | + where T: IProcessHostPreloadClient | ||
208 | { | 277 | { |
278 | + Type serviceAutoStartProviderType = typeof(T); | ||
209 | const string CONFIGFILEDIRECTORY = @"inetsrv\config"; | 279 | const string CONFIGFILEDIRECTORY = @"inetsrv\config"; |
210 | const string CONFIGFILENAME = @"applicationHost.config"; | 280 | const string CONFIGFILENAME = @"applicationHost.config"; |
211 | //const string FILEPATH = @"C:\temp\applicationHost.config"; | 281 | //const string FILEPATH = @"C:\temp\applicationHost.config"; |
212 | - | 282 | + Thread.Sleep(20000); |
213 | bool writele = le == null; | 283 | bool writele = le == null; |
214 | - if (le == null) { le = new DCLogEntry(LogLevel.Information, $"{typeof(HangfireBootstrapper).FullName}.{System.Reflection.MethodBase.GetCurrentMethod().Name}"); }; | 284 | + if (le == null) { le = new DCLogEntry(LogLevel.Information, $"{typeof(WebServerHostedServiceStarter).FullName}.{System.Reflection.MethodBase.GetCurrentMethod().Name}"); }; |
215 | try | 285 | try |
216 | { | 286 | { |
217 | websitename = websitename ?? HostingEnvironment.SiteName; //websitename = System.Web.Hosting.HostingEnvironment.ApplicationHost.GetSiteName(); | 287 | websitename = websitename ?? HostingEnvironment.SiteName; //websitename = System.Web.Hosting.HostingEnvironment.ApplicationHost.GetSiteName(); |
@@ -231,6 +301,9 @@ namespace Vrh.Web.HangfireBootstrapperNS | @@ -231,6 +301,9 @@ namespace Vrh.Web.HangfireBootstrapperNS | ||
231 | le.AddDataField("SetupAutoStart serviceAutoStartProviderTypeFullName", serviceAutoStartProviderTypeFullName); | 301 | le.AddDataField("SetupAutoStart serviceAutoStartProviderTypeFullName", serviceAutoStartProviderTypeFullName); |
232 | le.AddDataField("SetupAutoStart serviceAutoStartProviderAssassemblyName", serviceAutoStartProviderAssassemblyName); | 302 | le.AddDataField("SetupAutoStart serviceAutoStartProviderAssassemblyName", serviceAutoStartProviderAssassemblyName); |
233 | 303 | ||
304 | + if (!disablemode.HasValue) disablemode = Config_DisablAutoStart; | ||
305 | + le.AddDataField("DisablAautoStart", disablemode.Value); | ||
306 | + | ||
234 | string filecontent; | 307 | string filecontent; |
235 | bool configchanged; | 308 | bool configchanged; |
236 | lock (lockerFile) | 309 | lock (lockerFile) |
@@ -253,7 +326,7 @@ namespace Vrh.Web.HangfireBootstrapperNS | @@ -253,7 +326,7 @@ namespace Vrh.Web.HangfireBootstrapperNS | ||
253 | } | 326 | } |
254 | 327 | ||
255 | reader = new StreamReader(file, Encoding.ASCII); | 328 | reader = new StreamReader(file, Encoding.ASCII); |
256 | - filecontent = ProcessFileContent(le, reader.ReadToEnd(), applicationpoolname, websitename, webapplicationname, autostartprovidername, serviceAutoStartProviderAssassemblyName, serviceAutoStartProviderTypeFullName, disablemode); | 329 | + filecontent = ProcessFileContent(le, reader.ReadToEnd(), applicationpoolname, websitename, webapplicationname, autostartprovidername, serviceAutoStartProviderAssassemblyName, serviceAutoStartProviderTypeFullName, disablemode.Value); |
257 | configchanged = filecontent != null; | 330 | configchanged = filecontent != null; |
258 | if (configchanged) | 331 | if (configchanged) |
259 | { | 332 | { |
@@ -265,12 +338,12 @@ namespace Vrh.Web.HangfireBootstrapperNS | @@ -265,12 +338,12 @@ namespace Vrh.Web.HangfireBootstrapperNS | ||
265 | } | 338 | } |
266 | else | 339 | else |
267 | { | 340 | { |
268 | - filecontent = ProcessFileContent(le, System.IO.File.ReadAllText(configfilepath), applicationpoolname, websitename, webapplicationname, autostartprovidername, serviceAutoStartProviderAssassemblyName, serviceAutoStartProviderTypeFullName, disablemode); | 341 | + filecontent = ProcessFileContent(le, System.IO.File.ReadAllText(configfilepath), applicationpoolname, websitename, webapplicationname, autostartprovidername, serviceAutoStartProviderAssassemblyName, serviceAutoStartProviderTypeFullName, disablemode.Value); |
269 | configchanged = filecontent != null; | 342 | configchanged = filecontent != null; |
270 | if (configchanged) System.IO.File.WriteAllText(configfilepath, filecontent); | 343 | if (configchanged) System.IO.File.WriteAllText(configfilepath, filecontent); |
271 | } | 344 | } |
272 | } | 345 | } |
273 | - string modetxt = disablemode ? "DISABLED" : "ENABLED"; | 346 | + string modetxt = disablemode.Value ? "DISABLED" : "ENABLED"; |
274 | le.AddDataField("SetupAutoStart SUCCESS RESULT",configchanged ? modetxt : $"NO CHANGE, ALREADY {modetxt}"); | 347 | le.AddDataField("SetupAutoStart SUCCESS RESULT",configchanged ? modetxt : $"NO CHANGE, ALREADY {modetxt}"); |
275 | } | 348 | } |
276 | catch (Exception ex) { le.AddDataField("SetupAutoStart EXCEPTION",ex.Message); le.SetLogLevel(LogLevel.Error); return; } | 349 | catch (Exception ex) { le.AddDataField("SetupAutoStart EXCEPTION",ex.Message); le.SetLogLevel(LogLevel.Error); return; } |
@@ -405,6 +478,6 @@ namespace Vrh.Web.HangfireBootstrapperNS | @@ -405,6 +478,6 @@ namespace Vrh.Web.HangfireBootstrapperNS | ||
405 | .FirstOrDefault(app => app.Path == HttpRuntime.AppDomainAppVirtualPath)? | 478 | .FirstOrDefault(app => app.Path == HttpRuntime.AppDomainAppVirtualPath)? |
406 | .ApplicationPoolName; | 479 | .ApplicationPoolName; |
407 | } | 480 | } |
408 | - #endregion private method - SetupAutoStart | 481 | + #endregion private method - _SetupAutoStart |
409 | } | 482 | } |
410 | } | 483 | } |
Vrh.iScheduler/Monitor .cs
@@ -16,107 +16,237 @@ using System.Data.SqlClient; | @@ -16,107 +16,237 @@ using System.Data.SqlClient; | ||
16 | using System.Xml.Linq; | 16 | using System.Xml.Linq; |
17 | using Hangfire; | 17 | using Hangfire; |
18 | using Hangfire.Storage; | 18 | using Hangfire.Storage; |
19 | +using System.Web.Hosting; | ||
20 | +using System.Configuration; | ||
21 | + | ||
19 | namespace Vrh.iScheduler | 22 | namespace Vrh.iScheduler |
20 | { | 23 | { |
21 | - | ||
22 | - public class Monitor : IDisposable | 24 | + public class WAHostedMonitorHangfire |
23 | { | 25 | { |
24 | - public static void InitHangfire(object parameters) | 26 | + /// <summary> |
27 | + /// A Hangfire alrendszer inicializálását+indítását, vagy a leállítását végzi | ||
28 | + /// </summary> | ||
29 | + /// <param name="start">true:inicalizálás/indítás; false:leállítás</param> | ||
30 | + public static void Start() | ||
25 | { | 31 | { |
26 | - string ischedulerMonitorXml = "config=ALMiSchedulerMonitor";//TODO:hogy lehet ezt paraméterben átadni?????? | ||
27 | - string ischedulerXml = ""; // vagy "config=ALMiScheduler;"; | ||
28 | - var m_xmlp = new iSchedulerXMLProcessor(ischedulerMonitorXml, ischedulerXml); | ||
29 | - Monitor.SetiSchedulerCommonXMLProcessor(m_xmlp); | ||
30 | - if (m_xmlp.EnableWebAppExecution && m_xmlp.CheckInterval > 0) | 32 | + var le = new DCLogEntry(LogLevel.Information, $"{typeof(WAHostedMonitorHangfire).FullName}.{System.Reflection.MethodBase.GetCurrentMethod().Name}"); |
33 | + try | ||
31 | { | 34 | { |
35 | + _MonitorHangfireInstance._StartHangfire(le); | ||
36 | + string ischedulerMonitorXml = "config=ALMiSchedulerMonitor";//TODO:hogy lehet ezt paraméterben átadni?????? | ||
37 | + string ischedulerXml = ""; // vagy "config=ALMiScheduler;"; | ||
38 | + var m_xmlp = new iSchedulerXMLProcessor(ischedulerMonitorXml, ischedulerXml); | ||
39 | + Monitor.SetiSchedulerCommonXMLProcessor(m_xmlp); | ||
40 | + if (m_xmlp.EnableWebAppExecution && m_xmlp.CheckInterval > 0) | ||
41 | + { | ||
42 | + IntervalCronExpression = Cron.MinuteInterval((int)(m_xmlp.CheckInterval / 60));//"*/1 * * * *" | ||
43 | + //RecurringJob.RemoveIfExists("ischedulermonitorcycle"); | ||
44 | + RecurringJob.AddOrUpdate("ischedulermonitorcycle", () => new Monitor().Examination(null), IntervalCronExpression); | ||
45 | + //var HanfireJobId = BackgroundJob.Enqueue(() => new Monitor().Examination(null)); | ||
46 | + //RecurringJob.AddOrUpdate("ischedulermonitorcycle", () => new Monitor(m_xmlp).Examination(null), intervalcron); //minutes interval | ||
47 | + //RecurringJob.AddOrUpdate("ischedulermonitorcycle", () => new Monitor(m_xmlp).Examination(null), $"{(int)(m_xmlp.CheckInterval / 60)} * * * *"); // cron expression | ||
48 | + } | ||
49 | + } | ||
50 | + catch (Exception ex) { le.AddExceptionResult(ex); le.SetLogLevel(LogLevel.Error); } | ||
51 | + finally { le.Write(); } | ||
52 | + } | ||
32 | 53 | ||
33 | - //Cron Expression | ||
34 | - // <minute> <hour> <day-of-month> <month> <day-of-week> | ||
35 | - // <minute>:0-59 | ||
36 | - // <hour>:0-23 | ||
37 | - // <day-of-month>:1-31 | ||
38 | - // <month>:1-12 | ||
39 | - // <day-of-week>:0-6 (Sunday to Saturday; 7 is Sunday on some systems) | ||
40 | - //Special Characters in Cron Expression | ||
41 | - // * (all) all values. event should happen for every time unit. For example, “*” in the<minute> field means “for every minute.” | ||
42 | - // ? (any) any value. used for the <day-of-month> and <day-of-week> fields. For example “?” in the<day-of-week> field and 5 in the <day-of-month> | ||
43 | - // field means “5th of every month” irrespective of what day is this of the week. | ||
44 | - // – (range) value range. For example, “10-11” in the<hour> field means “10th and 11th hours.” | ||
45 | - // , (values) multiple values. For example, “MON, WED, FRI“ in <day-of-week> field means on the days “Monday, Wednesday and Friday.” | ||
46 | - // / (increments) specifies the incremental values.For example, a “5/15” in the<minute> field means at “5, 20, 35 and 50 minutes of an hour.” | ||
47 | - // L (last) has different meanings when used in various fields. For example, if it's applied in the <day-of-month> field, it means last day of the month, | ||
48 | - // i.e. “31st of January” and so on as per the calendar month. It can be used with an offset value, like “L-3”, | ||
49 | - // which denotes the “third to last day of the calendar month.” In <day-of-week>, it specifies the “last day of a week.” It can also be used with | ||
50 | - // another value in <day-of-week>, like “6L”, which denotes the “last Friday.” | ||
51 | - // W (weekday) determines the weekday (Monday to Friday) nearest to a given day of the month.For example, if we specify “10W” in the<day-of-month> field, | ||
52 | - // it means the “weekday near to 10th of that month.” So if “10th” is a Saturday, the job will be triggered on “9th,” and if “10th” is a Sunday, | ||
53 | - // it will trigger on “11th.” If we specify “1W” in <day-of-month> and if “1st” is Saturday, the job will be triggered on “3rd,” which is Monday, | ||
54 | - // and it will not jump back to the previous month. | ||
55 | - // # specifies the “N-th” occurrence of a weekday of the month, for example, “third Friday of the month” can be indicated as “6#3”. | ||
56 | - //Cron Special Strings | ||
57 | - // run once at the startup: "@reboot" | ||
58 | - // run once a year: "@yearly" or "@annualy" (="0 0 1 1 *") | ||
59 | - // run once a month: "@monthly" (="0 0 1 * *") | ||
60 | - // run once a week: "@weekly" (="0 0 * * 0") | ||
61 | - // run once a day: "@daily" or "@midnight" (="0 0 * * *") | ||
62 | - // run hourly: "@hourly" (="0 * * * *") | 54 | + public static void Stop() |
55 | + { | ||
56 | + var le = new DCLogEntry(LogLevel.Information, $"{typeof(WAHostedMonitorHangfire).FullName}.{System.Reflection.MethodBase.GetCurrentMethod().Name}"); | ||
57 | + try { _MonitorHangfireInstance._StopHangfire(le); } | ||
58 | + catch (Exception ex) { le.AddExceptionResult(ex); le.SetLogLevel(LogLevel.Error); } | ||
59 | + finally { le.Write(); } | ||
60 | + } | ||
63 | 61 | ||
64 | - //At 12:00pm (noon) every day: "0 12 * * ?" | ||
65 | - //At Every five minutes starting at 1pm and ending at 1:55pm and then starting at 6pm and ending at 6:55pm, every day: "0/5 13,18 * * ?" | ||
66 | - //At Every minute starting at 1pm and ending at 1:05pm, every day: "0-5 13 * * ?" | ||
67 | - //At 1:15pm and 1:45pm every Tuesday in the month of June: "15,45 13 ? 6 Tue" | ||
68 | - //At 9:30am every Monday, Tuesday, Wednesday, Thursday and Friday: "30 9 ? *MON - FRI" | ||
69 | - //At 9:30am on the 15th day of every month: "30 9 15 * ?" | ||
70 | - //At 6pm on the last day of every month: "0 18 L * ?" | ||
71 | - //At 6pm on the third to last day of every month: "0 18 L - 3 * ?" | ||
72 | - //At 10:30am on the last Thursday of every month: "30 10 ? *5L" | ||
73 | - //At 10am on the third Monday of every month: "0 10 ? *2#3" | ||
74 | - //At 12 midnight on every 5th day, starting from the 10th until the end of the month: "0 0 10 / 5 * ?" | ||
75 | 62 | ||
76 | - //At every hour: "0 * * * *" | ||
77 | - //At every hour: "@hourly" | ||
78 | - //At once a day at midnight: "0 0 * * *" | ||
79 | - //At every Sunday at midnight: "0 0 * * 0" | ||
80 | - //At every hour on Mondays: "0 * * *1" | ||
81 | - //At twice a day at 6am and 6pm: "0 6,18 * * *" | ||
82 | - //At every 10 minutes: "*/10 * * * *" | ||
83 | - //At every minute on July 20: "* * 20 7 *" | ||
84 | - //At every weekday(Monday to Friday) at 10pm: "0 22 * * 1-5" | ||
85 | - //At at midnight every Tuesday: "0 0 * * 2 *" | ||
86 | - //At every minute during January, February, and May "* * * 1,2,5 *" | ||
87 | - //At every 10 minutes at 5am, starting from 5:10am: "10-59/10 5 * * *" | ||
88 | - //At quarterly on the first day of the month at 8am "0 8 1 */3 *" | ||
89 | - //At every time you turn on the system: "@reboot" | ||
90 | - //At the first Monday of each month, at 8am: "0 8 1-7 * 1" | ||
91 | - //At every Sunday at 4:05 am: "5 4 * * 0" | ||
92 | - //At at 9:15 pm on the 1st and 20th of every month: "15 9 1,20 * *" | ||
93 | - //At at midnight every Wednesday between the 1st and 15th of every month: "0 0 1,15 * 3" | ||
94 | - //At the first day of every month at 2:15pm: "15 14 1 * *" | ||
95 | - //At every day from Monday to Friday every hour from 8 to 5pm: "00 08-17 * * 1-5" | ||
96 | - //At every January 1st at 6:15am: "15 6 1 1 *" | ||
97 | - //At at midnight on the 15th of every month: "0 0 15 * *" | ||
98 | - //At every Monday and Friday: "* * * * 1,5" | 63 | + /// <summary> |
64 | + /// Cron Expression | ||
65 | + /// <minute> <hour> <day-of-month> <month> <day-of-week> | ||
66 | + /// <minute>:0-59 | ||
67 | + /// <hour>:0-23 | ||
68 | + /// <day-of-month>:1-31 | ||
69 | + /// <month>:1-12 | ||
70 | + /// <day-of-week>:0-6 (Sunday to Saturday; 7 is Sunday on some systems) | ||
71 | + /// Special Characters in Cron Expression | ||
72 | + /// * (all) all values. event should happen for every time unit.For example, “*” in the<minute> field means “for every minute.” | ||
73 | + /// ? (any) any value.used for the<day-of-month> and <day-of-week> fields.For example “?” in the<day-of-week> field and 5 in the<day-of-month> | ||
74 | + /// field means “5th of every month” irrespective of what day is this of the week. | ||
75 | + /// – (range) value range.For example, “10-11” in the<hour> field means “10th and 11th hours.” | ||
76 | + /// , (values) multiple values.For example, “MON, WED, FRI“ in <day-of-week> field means on the days “Monday, Wednesday and Friday.” | ||
77 | + /// / (increments) specifies the incremental values.For example, a “5/15” in the<minute> field means at “5, 20, 35 and 50 minutes of an hour.” | ||
78 | + /// | ||
79 | + /// L (last) has different meanings when used in various fields. For example, if it's applied in the <day-of-month> field, it means last day of the month, | ||
80 | + /// i.e. “31st of January” and so on as per the calendar month. It can be used with an offset value, like “L-3”, | ||
81 | + /// which denotes the “third to last day of the calendar month.” In<day-of-week>, it specifies the “last day of a week.” It can also be used with | ||
82 | + /// another value in <day-of-week>, like “6L”, which denotes the “last Friday.” | ||
83 | + /// | ||
84 | + /// W (weekday) determines the weekday (Monday to Friday) nearest to a given day of the month.For example, if we specify “10W” in the<day-of-month> field, | ||
85 | + /// it means the “weekday near to 10th of that month.” So if “10th” is a Saturday, the job will be triggered on “9th,” and if “10th” is a Sunday, | ||
86 | + /// it will trigger on “11th.” If we specify “1W” in <day-of-month> and if “1st” is Saturday, the job will be triggered on “3rd,” which is Monday, | ||
87 | + /// and it will not jump back to the previous month. | ||
88 | + /// # specifies the “N-th” occurrence of a weekday of the month, for example, “third Friday of the month” can be indicated as “6#3”. | ||
89 | + /// Cron Special Strings | ||
90 | + /// run once at the startup: "@reboot" | ||
91 | + /// run once a year: "@yearly" or "@annualy" (= "0 0 1 1 *") | ||
92 | + /// run once a month: "@monthly" (="0 0 1 * *") | ||
93 | + /// run once a week: "@weekly" (="0 0 * * 0") | ||
94 | + /// run once a day: "@daily" or "@midnight" (="0 0 * * *") | ||
95 | + /// run hourly: "@hourly" (="0 * * * *") | ||
96 | + /// | ||
97 | + /// Cron samples | ||
98 | + /// At 12:00pm(noon) every day: "0 12 * * ?" | ||
99 | + /// At Every five minutes starting at 1pm and ending at 1:55pm and then starting at 6pm and ending at 6:55pm, every day: "0/5 13,18 * * ?" | ||
100 | + /// At Every minute starting at 1pm and ending at 1:05pm, every day: "0-5 13 * * ?" | ||
101 | + /// At 1:15pm and 1:45pm every Tuesday in the month of June: "15,45 13 ? 6 Tue" | ||
102 | + /// At 9:30am every Monday, Tuesday, Wednesday, Thursday and Friday: "30 9 ? *MON - FRI" | ||
103 | + /// At 9:30am on the 15th day of every month: "30 9 15 * ?" | ||
104 | + /// At 6pm on the last day of every month: "0 18 L * ?" | ||
105 | + /// At 6pm on the third to last day of every month: "0 18 L - 3 * ?" | ||
106 | + /// At 10:30am on the last Thursday of every month: "30 10 ? *5L" | ||
107 | + /// At 10am on the third Monday of every month: "0 10 ? *2#3" | ||
108 | + /// At 12 midnight on every 5th day, starting from the 10th until the end of the month: "0 0 10 / 5 * ?" | ||
109 | + /// | ||
110 | + /// At every hour: "0 * * * *" | ||
111 | + /// At every hour: "@hourly" | ||
112 | + /// At once a day at midnight: "0 0 * * *" | ||
113 | + /// At every Sunday at midnight: "0 0 * * 0" | ||
114 | + /// At every hour on Mondays: "0 * * *1" | ||
115 | + /// At twice a day at 6am and 6pm: "0 6,18 * * *" | ||
116 | + /// At every 10 minutes: "*/10 * * * *" | ||
117 | + /// At every minute on July 20: "* * 20 7 *" | ||
118 | + /// At every weekday(Monday to Friday) at 10pm: "0 22 * * 1-5" | ||
119 | + /// At at midnight every Tuesday: "0 0 * * 2 *" | ||
120 | + /// At every minute during January, February, and May "* * * 1,2,5 *" | ||
121 | + /// At every 10 minutes at 5am, starting from 5:10am: "10-59/10 5 * * *" | ||
122 | + /// At quarterly on the first day of the month at 8am "0 8 1 */3 *" | ||
123 | + /// At every time you turn on the system: "@reboot" | ||
124 | + /// At the first Monday of each month, at 8am: "0 8 1-7 * 1" | ||
125 | + /// At every Sunday at 4:05 am: "5 4 * * 0" | ||
126 | + /// At at 9:15 pm on the 1st and 20th of every month: "15 9 1,20 * *" | ||
127 | + /// At at midnight every Wednesday between the 1st and 15th of every month: "0 0 1,15 * 3" | ||
128 | + /// At the first day of every month at 2:15pm: "15 14 1 * *" | ||
129 | + /// At every day from Monday to Friday every hour from 8 to 5pm: "00 08-17 * * 1-5" | ||
130 | + /// At every January 1st at 6:15am: "15 6 1 1 *" | ||
131 | + /// At at midnight on the 15th of every month: "0 0 15 * *" | ||
132 | + /// At every Monday and Friday: "* * * * 1,5" | ||
133 | + /// | ||
134 | + /// At Every Minute of Every Day: "* * * * *" or "0-59 0-23 0-31 0-12 0-7" | ||
135 | + /// At Every 10 Minutes of Every Day: "*/10 * * * *" or "0-59/10 * * * *" or "0,10,20,30,40,50 * * * *" | ||
136 | + /// At Every 5 Minutes of the 6am hour starting at 6:07 (tu run at 6:07, 6:012, 6:17, 6:22, 6:27, and so on until 6:57):"07-59/5 06 * * *" | ||
137 | + /// At Every day at midnight: "0 0 * * *" or "0 0 * * 0-7" | ||
138 | + /// At Thrice Daily: "0 */8 * * *" or "0 0-23/8 * * *" or "0 0,8,16 * * *" | ||
139 | + /// At Every weekday at 6am: "0 06 * * 1-5" | ||
140 | + /// At Weekends at 6am: "0 06 * * 6,7" or "0 06 * * 6-7" | ||
141 | + /// At Once a month on the 20th at 6am: "0 06 20 * *" | ||
142 | + /// At Every 4 days at 6am: "0 06 */4 * *" | ||
143 | + /// At Every 4 Months at 6am on the 10th: "0 06 10 */4 *" | ||
144 | + /// </summary> | ||
145 | + private static string IntervalCronExpression = null; | ||
146 | + private static WAHostedMonitorHangfire _MonitorHangfireInstance = new WAHostedMonitorHangfire(); | ||
99 | 147 | ||
100 | - //At Every Minute of Every Day: "* * * * *" or "0-59 0-23 0-31 0-12 0-7" | ||
101 | - //At Every 10 Minutes of Every Day: "*/10 * * * *" or "0-59/10 * * * *" or "0,10,20,30,40,50 * * * *" | ||
102 | - //At Every 5 Minutes of the 6am hour starting at 6:07 (tu run at 6:07, 6:012, 6:17, 6:22, 6:27, and so on until 6:57):"07-59/5 06 * * *" | ||
103 | - //At Every day at midnight: "0 0 * * *" or "0 0 * * 0-7" | ||
104 | - //At Thrice Daily: "0 */8 * * *" or "0 0-23/8 * * *" or "0 0,8,16 * * *" | ||
105 | - //At Every weekday at 6am: "0 06 * * 1-5" | ||
106 | - //At Weekends at 6am: "0 06 * * 6,7" or "0 06 * * 6-7" | ||
107 | - //At Once a month on the 20th at 6am: "0 06 20 * *" | ||
108 | - //At Every 4 days at 6am: "0 06 */4 * *" | ||
109 | - //At Every 4 Months at 6am on the 10th: "0 06 10 */4 *" | 148 | + private BackgroundJobServer _HangfireBackgroundJobServer { get; set; } |
149 | + private static readonly object _HangfireStarterLocker = new object(); | ||
150 | + private static bool _HangFireRunning = false; | ||
151 | + const string HANGFIRE = "HangfireBootstrapper:"; | ||
152 | + const string HANGFIREDBCONNECTIONSTRING = HANGFIRE + "dbconnectionstring"; | ||
153 | + const string HANGFIRESQLDBCONNECTIONSTRINGNAMEDEFAULT = "HANGFIRESQLDB"; | ||
154 | + private void _StartHangfire(DCLogEntry le) | ||
155 | + { | ||
156 | + lock (_HangfireStarterLocker) | ||
157 | + { | ||
158 | + le?.AddDataField("HangfireSqlDBConnectionString", Config_HangFireConnectionString); | ||
110 | 159 | ||
160 | + GlobalConfiguration.Configuration | ||
161 | + .UseSqlServerStorage(Config_HangFireConnectionString) | ||
162 | + // Specify other options here | ||
163 | + ; | ||
164 | + _HangfireBackgroundJobServer = new BackgroundJobServer(); | ||
165 | + _HangFireRunning = true; | ||
166 | + } | ||
167 | + } | ||
168 | + private void _StopHangfire(DCLogEntry le) | ||
169 | + { | ||
170 | + lock (_HangfireStarterLocker) | ||
171 | + { | ||
172 | + if (!_HangFireRunning) return; | ||
173 | + le?.AddDataField("Function", nameof(_StopHangfire)); | ||
174 | + if (_HangfireBackgroundJobServer != null) { _HangfireBackgroundJobServer.Dispose(); } | ||
175 | + _HangFireRunning = false; | ||
176 | + } | ||
177 | + } | ||
178 | + private string Config_HangFireConnectionString | ||
179 | + { | ||
180 | + get | ||
181 | + { | ||
182 | + if (config_hangfireconnectionstring == null) | ||
183 | + { | ||
184 | + string HangfireSqlDBConnectionString = ConfigurationManager.AppSettings[HANGFIREDBCONNECTIONSTRING]; | ||
185 | + if (string.IsNullOrWhiteSpace(HangfireSqlDBConnectionString)) HangfireSqlDBConnectionString = HANGFIRESQLDBCONNECTIONSTRINGNAMEDEFAULT; | ||
186 | + config_hangfireconnectionstring = ConnectionStringStore.GetSQL(HangfireSqlDBConnectionString); | ||
187 | + } | ||
188 | + return config_hangfireconnectionstring; | ||
189 | + } | ||
190 | + } | ||
191 | + private string config_hangfireconnectionstring = null; | ||
192 | + } | ||
193 | +} | ||
194 | +namespace Vrh.iScheduler | ||
195 | +{ | ||
196 | + public class WAHostedMonitor : Monitor | ||
197 | + { | ||
198 | + public static void Start() | ||
199 | + { | ||
200 | + MonitorInstance = new Monitor(Config_scheduleMonitorXmlPath, Config_scheduleXmlPath); | ||
201 | + MonitorInstance.Start(); | ||
202 | + new DCLogEntry(LogLevel.Information, "iSchedulerMonitor started.").Write(); | ||
203 | + } | ||
204 | + public static void Stop() | ||
205 | + { | ||
206 | + MonitorInstance.Stop(); | ||
207 | + MonitorInstance.Dispose(); | ||
208 | + new DCLogEntry(LogLevel.Information, "iSchedulerMonitor stopped.").Write(); | ||
209 | + } | ||
111 | 210 | ||
112 | - string intervalcron = Cron.MinuteInterval((int)(m_xmlp.CheckInterval / 60));//"*/1 * * * *" | ||
113 | - //RecurringJob.RemoveIfExists("ischedulermonitorcycle"); | ||
114 | - RecurringJob.AddOrUpdate("ischedulermonitorcycle", () => new Monitor().Examination(null), intervalcron); | ||
115 | - //var HanfireJobId = BackgroundJob.Enqueue(() => new Monitor().Examination(null)); | ||
116 | - //RecurringJob.AddOrUpdate("ischedulermonitorcycle", () => new Monitor(m_xmlp).Examination(null), intervalcron); //minutes interval | ||
117 | - //RecurringJob.AddOrUpdate("ischedulermonitorcycle", () => new Monitor(m_xmlp).Examination(null), $"{(int)(m_xmlp.CheckInterval / 60)} * * * *"); // cron expression | 211 | + #region private members |
212 | + private static string Config_scheduleMonitorXmlPath | ||
213 | + { | ||
214 | + get | ||
215 | + { | ||
216 | + if (config_schedulemonitorxmlpath == null) | ||
217 | + { | ||
218 | + string schedulemonitorxmlpath = ConfigurationManager.AppSettings[ISCHEDULERMONITORXMLPATH]; | ||
219 | + config_schedulemonitorxmlpath = ConnectionStringStore.GetSQL(schedulemonitorxmlpath); | ||
220 | + } | ||
221 | + return config_schedulemonitorxmlpath; | ||
222 | + } | ||
223 | + } | ||
224 | + private static string config_schedulemonitorxmlpath = null; | ||
225 | + private static string Config_scheduleXmlPath | ||
226 | + { | ||
227 | + get | ||
228 | + { | ||
229 | + if (config_schedulexmlpath == null) | ||
230 | + { | ||
231 | + string schedulexmlpath = ConfigurationManager.AppSettings[ISCHEDULERXMLPATH]; | ||
232 | + config_schedulexmlpath = ConnectionStringStore.GetSQL(schedulexmlpath); | ||
233 | + } | ||
234 | + return config_schedulexmlpath; | ||
118 | } | 235 | } |
119 | } | 236 | } |
237 | + private static string config_schedulexmlpath = null; | ||
238 | + const string ISCHEDULER = "iScheduler:"; | ||
239 | + const string ISCHEDULERMONITORXMLPATH = ISCHEDULER + "monitorxmlpath"; | ||
240 | + const string ISCHEDULERXMLPATH = ISCHEDULER + "xmlpath"; | ||
241 | + private static Monitor MonitorInstance; | ||
242 | + #endregion private members | ||
243 | + } | ||
244 | +} | ||
245 | + | ||
246 | +namespace Vrh.iScheduler | ||
247 | +{ | ||
248 | + public class Monitor : IDisposable | ||
249 | + { | ||
120 | #region Enums | 250 | #region Enums |
121 | /// <summary> | 251 | /// <summary> |
122 | /// Ütemezések lehetséges állapotai. | 252 | /// Ütemezések lehetséges állapotai. |
@@ -140,7 +270,7 @@ namespace Vrh.iScheduler | @@ -140,7 +270,7 @@ namespace Vrh.iScheduler | ||
140 | } | 270 | } |
141 | #endregion Enums | 271 | #endregion Enums |
142 | 272 | ||
143 | - #region Privates | 273 | + #region Private members |
144 | 274 | ||
145 | private Timer m_timer; | 275 | private Timer m_timer; |
146 | private iSchedulerXMLProcessor m_xmlp; | 276 | private iSchedulerXMLProcessor m_xmlp; |
@@ -149,7 +279,7 @@ namespace Vrh.iScheduler | @@ -149,7 +279,7 @@ namespace Vrh.iScheduler | ||
149 | { | 279 | { |
150 | CommonM_xmlp = m_xmlp; | 280 | CommonM_xmlp = m_xmlp; |
151 | } | 281 | } |
152 | - #endregion Privates | 282 | + #endregion Private members |
153 | 283 | ||
154 | #region Constructor | 284 | #region Constructor |
155 | 285 | ||
@@ -198,6 +328,7 @@ namespace Vrh.iScheduler | @@ -198,6 +328,7 @@ namespace Vrh.iScheduler | ||
198 | } | 328 | } |
199 | #endregion Constructor | 329 | #endregion Constructor |
200 | 330 | ||
331 | + #region public methods - Start,Stop | ||
201 | public void Start() | 332 | public void Start() |
202 | { | 333 | { |
203 | new DCLogEntry(LogLevel.Information, "iSchedulerMonitor started.").Write(); | 334 | new DCLogEntry(LogLevel.Information, "iSchedulerMonitor started.").Write(); |
@@ -208,6 +339,7 @@ namespace Vrh.iScheduler | @@ -208,6 +339,7 @@ namespace Vrh.iScheduler | ||
208 | m_timer.Stop(); | 339 | m_timer.Stop(); |
209 | new DCLogEntry(LogLevel.Information, "iSchedulerMonitor stopped.").Write(); | 340 | new DCLogEntry(LogLevel.Information, "iSchedulerMonitor stopped.").Write(); |
210 | } | 341 | } |
342 | + #endregion public methods - Start,Stop | ||
211 | 343 | ||
212 | #region Private methods | 344 | #region Private methods |
213 | 345 |
Vrh.iScheduler/Properties/AssemblyInfo.cs
@@ -32,7 +32,7 @@ using System.Runtime.InteropServices; | @@ -32,7 +32,7 @@ using System.Runtime.InteropServices; | ||
32 | // You can specify all the values or you can default the Build and Revision Numbers | 32 | // You can specify all the values or you can default the Build and Revision Numbers |
33 | // by using the '*' as shown below: | 33 | // by using the '*' as shown below: |
34 | // [assembly: AssemblyVersion("1.0.*")] | 34 | // [assembly: AssemblyVersion("1.0.*")] |
35 | -[assembly: AssemblyVersion("3.2.1.0")] | ||
36 | -[assembly: AssemblyFileVersion("3.2.1.0")] | ||
37 | -[assembly: AssemblyInformationalVersion("3.2.1")] | 35 | +[assembly: AssemblyVersion("3.3.0.0")] |
36 | +[assembly: AssemblyFileVersion("3.3.0.0")] | ||
37 | +[assembly: AssemblyInformationalVersion("3.3.0")] | ||
38 | 38 |