├── .gitignore ├── Agent ├── Hangfire.HttpJob.Agent.MssqlConsole │ ├── Hangfire.HttpJob.Agent.MssqlConsole.csproj │ ├── JobAgentMssqlConsoleCollectionExtensions.cs │ ├── MssqlConsole.cs │ ├── MssqlConsoleOptionsConfigurer.cs │ ├── MssqlStorage.cs │ └── MssqlStorageOptions.cs ├── Hangfire.HttpJob.Agent.MysqlLog │ ├── Hangfire.HttpJob.Agent.MysqlConsole.csproj │ ├── JobAgentConsoleCollectionExtensions.cs │ ├── MySqlStorage.cs │ ├── MySqlStorageOptions.cs │ ├── MysqlConsole.cs │ └── MysqlConsoleOptionsConfigurer.cs ├── Hangfire.HttpJob.Agent.PostgreSqlConsole │ ├── Hangfire.HttpJob.Agent.PostgreSqlConsole.csproj │ ├── JobAgentConsoleCollectionExtensions.cs │ ├── PostgreSqlConsole.cs │ ├── PostgreSqlConsoleOptionsConfigurer.cs │ ├── PostgreSqlStorage.cs │ └── PostgreSqlStorageOptions.cs ├── Hangfire.HttpJob.Agent.RedisConsole │ ├── Hangfire.HttpJob.Agent.RedisConsole.csproj │ ├── JobAgentConsoleCollectionExtensions.cs │ ├── RedisConsole.cs │ ├── RedisConsoleOptionsConfigurer.cs │ ├── RedisStorage.cs │ └── RedisStorageOptions.cs ├── Hangfire.HttpJob.Agent │ ├── Attribute │ │ ├── HangJobUntilStopAttribute.cs │ │ ├── JobAttribute.cs │ │ ├── SingletonJobAttribute.cs │ │ └── TransientJobAttribute.cs │ ├── Config │ │ ├── ConfigureJobAgentConsoleOptions.cs │ │ ├── ConfigureJobAgentOptions.cs │ │ ├── JobAgentOptions.cs │ │ ├── JobAgentOptionsConfigurer.cs │ │ ├── JobAgentServiceConfigurer.cs │ │ └── JobMetaData.cs │ ├── Console │ │ ├── ConsoleFontColor.cs │ │ ├── ConsoleInfo.cs │ │ ├── ConsoleLine.cs │ │ ├── HangfireConsole.cs │ │ ├── HangfireProgressBar.cs │ │ ├── IHangfireConsole.cs │ │ └── IStorageFactory.cs │ ├── Hangfire.HttpJob.Agent.csproj │ ├── Heartbeat.cs │ ├── JobAgent.cs │ ├── JobAgentApplicationBuilderExtensions.cs │ ├── JobAgentMiddleware.cs │ ├── JobAgentRegisterService.cs │ ├── JobAgentServiceCollectionExtensions.cs │ ├── JobContext.cs │ ├── JobStatus.cs │ └── Util │ │ ├── AgentThreadPool.cs │ │ ├── CodingUtil.cs │ │ ├── EnumerableExtensions.cs │ │ ├── LazyConcurrentDictionary.cs │ │ ├── LoggerConsole.cs │ │ └── ProgressEnumerable.cs └── Template │ ├── README.md │ ├── Template.csproj │ └── templates │ └── Template │ ├── .template.config │ └── template.json │ ├── Jobs │ ├── TestHangJob.cs │ ├── TestJob.cs │ └── TestTransientJob.cs │ ├── NLog.Config │ ├── Program.cs │ ├── Properties │ └── launchSettings.json │ ├── Startup.cs │ ├── Template.csproj │ ├── appsettings.Development.json │ └── appsettings.json ├── Client └── Hangfire.HttpJob.Client │ ├── BackgroundJob.cs │ ├── Hangfire.HttpJob.Client.csproj │ ├── HangfireHttpClientFactory.cs │ ├── HangfireJobClient.cs │ ├── HangfireJobResult.cs │ ├── HangfireServerPostOption.cs │ ├── HttpJobItem.cs │ └── RecurringJob.cs ├── Hangfire.HttpJob.sln ├── LICENSE.md ├── README.md ├── Server └── Hangfire.HttpJob │ ├── Content │ ├── cron.js │ ├── httpjob.js │ ├── jsoneditor.css │ ├── jsoneditor.js │ ├── resx │ │ ├── Strings.Designer.cs │ │ ├── Strings.es.resx │ │ ├── Strings.resx │ │ ├── Strings.zh-TW.resx │ │ └── Strings.zh.resx │ ├── sweetalert2.min.css │ └── sweetalert2.min.js │ ├── Dashboard │ ├── DynamicCssDispatcher.cs │ ├── DynamicJsDispatcher.cs │ ├── Heartbeat │ │ └── Dashboard │ │ │ ├── ContentDispatcher.cs │ │ │ ├── OverviewPage.cs │ │ │ ├── OverviewPageModel.cs │ │ │ ├── UtilizationJsonDispatcher.cs │ │ │ ├── css │ │ │ └── styles.css │ │ │ ├── html │ │ │ └── OverviewPage.html │ │ │ └── js │ │ │ ├── OverviewPage.js │ │ │ ├── knockout-3.4.2.js │ │ │ ├── knockout.bindings.orderable.js │ │ │ └── numeral.min.js │ └── Pages │ │ ├── CronJobsPage.cshtml │ │ └── CronJobsPage.generated.cs │ ├── GlobalConfigurationExtension.cs │ ├── Hangfire.HttpJob.csproj │ ├── HangfireHttpJobOptions.cs │ ├── PageDto.cs │ ├── Server │ ├── HangfireHttpClientFactory.cs │ ├── Heartbeat │ │ ├── ConfigurationExtensions.cs │ │ ├── HeartbeatDashboardOptions.cs │ │ ├── HeartbeatProcessMonitorOptions.cs │ │ ├── ProcessInfo.cs │ │ ├── ProcessMonitor.cs │ │ └── Utils.cs │ ├── HttpJob.cs │ ├── HttpJobDispatcher.cs │ ├── HttpJobItem.cs │ └── JobAgent │ │ ├── JobAgentHeartBeatServer.cs │ │ ├── JobAgentReportServer.cs │ │ └── LosedJobCheckServer.cs │ ├── Support │ ├── AutomaticRetrySetAttribute.cs │ ├── CodingUtil.cs │ ├── CompositeDispatcher.cs │ ├── EmailService.cs │ ├── EmbeddedResourceDispatcher.cs │ ├── ErrorState.cs │ ├── HtmlHelperExtensions.cs │ ├── HttpJobDisplayNameAttribute.cs │ ├── HttpStatusCodeException.cs │ ├── JobFilter.cs │ ├── Models.cs │ ├── ProcessingState.cs │ ├── QueueProviderFilter.cs │ ├── RouteCollectionExtensions.cs │ └── UrlUtil.cs │ └── TimeZoneInfoHelper.cs ├── Test ├── Hangfire.HttpJob.Client.Test │ ├── Hangfire.HttpJob.Client.Test.csproj │ └── UnitTest1.cs ├── MemoryHangfire │ └── MemoryHangfire │ │ ├── .dockerignore │ │ ├── Dockerfile │ │ ├── HangfireCollectionExtensions.cs │ │ ├── MemoryHangfire.csproj │ │ ├── NLog.Config │ │ ├── Program.cs │ │ ├── Startup.cs │ │ ├── appsettings.Development.json │ │ ├── appsettings.json │ │ └── hangfire │ │ └── hangfire_global.json ├── PostgreSqlHangfire │ ├── .dockerignore │ ├── Dockerfile │ ├── HangfireCollectionExtensions.cs │ ├── NLog.Config │ ├── PostgreSqlHangfire.csproj │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ ├── Startup.cs │ ├── appsettings.Development.json │ ├── appsettings.json │ └── hangfire │ │ └── hangfire_global.json ├── RedisHangfire │ ├── .dockerignore │ ├── Dockerfile │ ├── HangfireCollectionExtensions.cs │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ ├── RedisHangfire.csproj │ ├── Startup.cs │ ├── appsettings.Development.json │ ├── appsettings.json │ └── hangfire │ │ └── hangfire_global.json ├── TestHangfire │ ├── .dockerignore │ ├── Dockerfile │ ├── HangfireCollectionExtensions.cs │ ├── MysqlHangfire.csproj │ ├── NLog.Config │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ ├── Startup.cs │ ├── appsettings.Development.json │ ├── appsettings.json │ └── hangfire │ │ └── hangfire_global.json ├── TestHangfireAgent │ ├── Jobs │ │ ├── TestHangJob.cs │ │ ├── TestJob.cs │ │ └── TestTransientJob.cs │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ ├── Startup.cs │ ├── TestHangfireAgent.csproj │ └── appsettings.json ├── TestHangfirePostgreSqlAgent │ ├── Jobs │ │ ├── TestHangJob.cs │ │ ├── TestJob.cs │ │ └── TestTransientJob.cs │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ ├── Startup.cs │ ├── TestHangfirePostgreSqlAgent.csproj │ └── appsettings.json ├── TestHangfireRedisAgent │ ├── Jobs │ │ ├── TestHangJob.cs │ │ ├── TestJob.cs │ │ └── TestTransientJob.cs │ ├── NLog.Config │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ ├── Startup.cs │ ├── TestHangfireRedisAgent.csproj │ ├── appsettings.Development.json │ └── appsettings.json ├── TestOwinHangfireRedisAgent │ └── TestOwinHangfireRedisAgent │ │ ├── App.config │ │ ├── Jobs │ │ ├── TestHangJob.cs │ │ ├── TestJob.cs │ │ └── TestTransientJob.cs │ │ ├── NLog.Config │ │ ├── Program.cs │ │ ├── Properties │ │ └── AssemblyInfo.cs │ │ ├── Startup.cs │ │ ├── TestOwinHangfireRedisAgent.csproj │ │ ├── appsettings.Development.json │ │ └── appsettings.json ├── TestSqlserver │ ├── .dockerignore │ ├── Dockerfile │ ├── HangfireCollectionExtensions.cs │ ├── NLog.Config │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ ├── SqlserverHangfire.csproj │ ├── Startup.cs │ ├── appsettings.Development.json │ ├── appsettings.json │ └── hangfire │ │ └── hangfire_global.json └── TestSqlserverHangfireAgent │ ├── Jobs │ ├── TestHangJob.cs │ ├── TestJob.cs │ └── TestTransientJob.cs │ ├── Program.cs │ ├── Properties │ └── launchSettings.json │ ├── Startup.cs │ ├── TestSqlserverHangfireAgent.csproj │ └── appsettings.json ├── pic1.png ├── pic2.png ├── pic3.png └── pic4.png /.gitignore: -------------------------------------------------------------------------------- 1 | [Bb]in 2 | obj/ 3 | *.suo 4 | *.user 5 | packages/ 6 | .vs 7 | .idea/ 8 | _ReSharper.Caches/ 9 | Test/TestHangfire/AntDeploy.json 10 | Test/RedisHangfire/AntDeploy.json 11 | Test/TestSqlserver/AntDeploy.json 12 | -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent.MssqlConsole/Hangfire.HttpJob.Agent.MssqlConsole.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.0;net461 5 | true 6 | true 7 | yuz 8 | yuzd 9 | 10 | https://github.com/yuzd/Hangfire.HttpJob 11 | agent job console to hangfire sqlserver 12 | 1.5.1 13 | MIT 14 | 1.5.1.0 15 | 1.5.1.0 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | TRACE;NETCORE 24 | 25 | 26 | TRACE;OWIN 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent.MssqlConsole/MssqlConsole.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Hangfire.HttpJob.Agent.MssqlConsole 4 | { 5 | public class MssqlConsole : HangfireConsole 6 | { 7 | public MssqlConsole(IHangfireStorage storage) 8 | { 9 | Storage = storage ?? throw new ArgumentNullException(nameof(IHangfireStorage)); 10 | } 11 | 12 | public override IHangfireStorage Storage { get; } 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent.MssqlConsole/MssqlConsoleOptionsConfigurer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Hangfire.HttpJob.Agent.Config; 5 | using Microsoft.Extensions.Configuration; 6 | using Microsoft.Extensions.Options; 7 | 8 | namespace Hangfire.HttpJob.Agent.MssqlConsole.Config 9 | { 10 | public sealed class MssqlConsoleOptionsConfigurer : ConfigureJobAgentConsoleOptions 11 | { 12 | public MssqlConsoleOptionsConfigurer(IConfiguration configuration) : base(configuration) 13 | { 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent.MssqlConsole/MssqlStorageOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Hangfire.HttpJob.Agent.MssqlConsole 4 | { 5 | public class MssqlStorageOptions 6 | { 7 | public string HangfireDb { get; set; } 8 | public string TablePrefix { get; set; } = "HangFire"; 9 | 10 | public int ExpireAtDays { get; set; } = 7; 11 | 12 | public TimeSpan? ExpireAt { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent.MysqlLog/Hangfire.HttpJob.Agent.MysqlConsole.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.0;net461 5 | true 6 | true 7 | yuzd 8 | yuzd 9 | 10 | https://github.com/yuzd/Hangfire.HttpJob 11 | agent job console to hangfire mysql 12 | 1.4.8 13 | MIT 14 | 1.4.8.0 15 | 1.4.8.0 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | TRACE;NETCORE 25 | 26 | 27 | TRACE;OWIN 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent.MysqlLog/MySqlStorageOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Hangfire.HttpJob.Agent.MysqlConsole 6 | { 7 | public class MySqlStorageOptions 8 | { 9 | public string TablePrefix { get; set; } = "hangfire"; 10 | public string HangfireDb { get; set; } 11 | public int ExpireAtDays { get; set; } = 7; 12 | public TimeSpan? ExpireAt { get; set; } 13 | 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent.MysqlLog/MysqlConsole.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Hangfire.HttpJob.Agent.MysqlConsole 4 | { 5 | internal class MysqlConsole : HangfireConsole 6 | { 7 | public MysqlConsole(IHangfireStorage storage) 8 | { 9 | Storage = storage ?? throw new ArgumentNullException(nameof(IHangfireStorage)); 10 | } 11 | 12 | public override IHangfireStorage Storage { get; } 13 | } 14 | 15 | 16 | } 17 | -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent.MysqlLog/MysqlConsoleOptionsConfigurer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Hangfire.HttpJob.Agent.Config; 5 | using Microsoft.Extensions.Configuration; 6 | using Microsoft.Extensions.Options; 7 | 8 | namespace Hangfire.HttpJob.Agent.MysqlConsole.Config 9 | { 10 | 11 | public sealed class MysqlConsoleOptionsConfigurer : ConfigureJobAgentConsoleOptions 12 | { 13 | public MysqlConsoleOptionsConfigurer(IConfiguration configuration) : base(configuration) 14 | { 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent.PostgreSqlConsole/Hangfire.HttpJob.Agent.PostgreSqlConsole.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | netstandard2.0 12 | true 13 | zdyu 14 | agent job console to hangfire postgresql 15 | https://github.com/yuzd/Hangfire.HttpJob 16 | 1.4.8 17 | true 18 | zdyu 19 | MIT 20 | 1.4.8.0 21 | 1.4.8.0 22 | 23 | -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent.PostgreSqlConsole/JobAgentConsoleCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Hangfire.HttpJob.Agent.Config; 3 | using Hangfire.HttpJob.Agent.PostgreSqlConsole.Config; 4 | using Microsoft.AspNetCore.Builder; 5 | using Microsoft.Extensions.DependencyInjection; 6 | using Microsoft.Extensions.DependencyInjection.Extensions; 7 | using Microsoft.Extensions.Logging; 8 | using Microsoft.Extensions.Options; 9 | 10 | namespace Hangfire.HttpJob.Agent.PostgreSqlConsole 11 | { 12 | public static class JobAgentConsoleCollectionExtensions 13 | { 14 | public static IServiceCollection AddHangfireJobAgent(this IServiceCollection services, Action configure = null) 15 | { 16 | services.AddHangfireHttpJobAgent(configure); 17 | services.AddJobAgentConsoleToPostgreSql(); 18 | return services; 19 | } 20 | 21 | public static IApplicationBuilder UseHangfireJobAgent(this IApplicationBuilder app, 22 | Action configureOptions = null, Action configureStorageOptions = null) 23 | { 24 | app.UseHangfireHttpJobAgent(configureOptions); 25 | app.UseJobAgentConsoleToPostgreSql(configureStorageOptions); 26 | return app; 27 | } 28 | 29 | public static IServiceCollection AddJobAgentConsoleToPostgreSql(this IServiceCollection serviceCollection) 30 | { 31 | serviceCollection.AddOptions(); 32 | serviceCollection.TryAddSingleton, PostgreSqlConsoleOptionsConfigurer>(); 33 | serviceCollection.TryAddSingleton(); 34 | serviceCollection.TryAddTransient(); 35 | serviceCollection.TryAddTransient(); 36 | return serviceCollection; 37 | } 38 | 39 | public static IApplicationBuilder UseJobAgentConsoleToPostgreSql(this IApplicationBuilder app, 40 | Action configureOptions = null) 41 | { 42 | var appServices = app.ApplicationServices; 43 | var evt = new EventId(1, "Hangfire.HttpJob.Agent.PostgreSqlConsole"); 44 | var options = appServices.GetService>(); 45 | var loggerFactory = appServices.GetService(); 46 | var logger = loggerFactory.CreateLogger(); 47 | try 48 | { 49 | configureOptions?.Invoke(options.Value); 50 | } 51 | catch (Exception exception) 52 | { 53 | logger.LogCritical(evt, exception, "【Hangfire.HttpJob.Agent.PostgreSqlConsole】 - Failed to configure Hangfire.HttpJob.Agent.PostgreSqlConsole middleware"); 54 | } 55 | 56 | JobStorageConfig.LocalJobStorageConfig = new JobStorageConfig 57 | { 58 | Type = "postgresql", 59 | HangfireDb = options.Value?.HangfireDbConnString, 60 | TablePrefix = options.Value?.TablePrefix, 61 | ExpireAtDays = options.Value?.ExpireAtDays 62 | }; 63 | 64 | logger.LogInformation(evt, "【Hangfire.HttpJob.Agent.PostgreSqlConsole】 - Registered PostgreSqlConsole middleware Success!"); 65 | return app; 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent.PostgreSqlConsole/PostgreSqlConsole.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Hangfire.HttpJob.Agent.PostgreSqlConsole 4 | { 5 | internal class PostgreSqlConsole : HangfireConsole 6 | { 7 | public PostgreSqlConsole(IHangfireStorage storage) 8 | { 9 | Storage = storage ?? throw new ArgumentNullException(nameof(IHangfireStorage)); 10 | } 11 | 12 | public override IHangfireStorage Storage { get; } 13 | } 14 | } -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent.PostgreSqlConsole/PostgreSqlConsoleOptionsConfigurer.cs: -------------------------------------------------------------------------------- 1 | using Hangfire.HttpJob.Agent.Config; 2 | using Microsoft.Extensions.Configuration; 3 | using Microsoft.Extensions.Options; 4 | 5 | namespace Hangfire.HttpJob.Agent.PostgreSqlConsole.Config 6 | { 7 | public sealed class PostgreSqlConsoleOptionsConfigurer : ConfigureJobAgentConsoleOptions 8 | { 9 | public PostgreSqlConsoleOptionsConfigurer(IConfiguration configuration) : base(configuration) 10 | { 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent.PostgreSqlConsole/PostgreSqlStorageOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Hangfire.HttpJob.Agent.PostgreSqlConsole 4 | { 5 | public class PostgreSqlStorageOptions 6 | { 7 | // hangfire.PostgreSql不支持table prefix,此处留空 8 | public string TablePrefix { get; set; } = ""; 9 | public string HangfireDbConnString { get; set; } 10 | public int ExpireAtDays { get; set; } = 7; 11 | public TimeSpan? ExpireAt { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent.RedisConsole/Hangfire.HttpJob.Agent.RedisConsole.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.0;net461 5 | true 6 | true 7 | yuz 8 | yuzd 9 | 10 | https://github.com/yuzd/Hangfire.HttpJob 11 | agent job console to hangfire redis 12 | 1.4.8 13 | MIT 14 | 1.4.8.0 15 | 1.4.8.0 16 | 17 | 18 | 19 | 20 | 21 | 22 | TRACE;NETCORE 23 | 24 | 25 | TRACE;OWIN 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent.RedisConsole/RedisConsole.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Hangfire.HttpJob.Agent.RedisConsole 4 | { 5 | internal class RedisConsole : HangfireConsole 6 | { 7 | public RedisConsole(IHangfireStorage storage) 8 | { 9 | Storage = storage ?? throw new ArgumentNullException(nameof(IHangfireStorage)); 10 | } 11 | 12 | public override IHangfireStorage Storage { get; } 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent.RedisConsole/RedisConsoleOptionsConfigurer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Hangfire.HttpJob.Agent.Config; 5 | using Microsoft.Extensions.Configuration; 6 | using Microsoft.Extensions.Options; 7 | 8 | namespace Hangfire.HttpJob.Agent.RedisConsole.Config 9 | { 10 | public sealed class RedisConsoleOptionsConfigurer : ConfigureJobAgentConsoleOptions 11 | { 12 | public RedisConsoleOptionsConfigurer(IConfiguration configuration) : base(configuration) 13 | { 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent.RedisConsole/RedisStorageOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Hangfire.HttpJob.Agent.RedisConsole 6 | { 7 | public class RedisStorageOptions 8 | { 9 | public string TablePrefix { get; set; } = "hangfire"; 10 | public string HangfireDb { get; set; } 11 | public int DataBase { get; set; } 12 | public int ExpireAtDays { get; set; } = 7; 13 | public TimeSpan? ExpireAt { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent/Attribute/HangJobUntilStopAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Hangfire.HttpJob.Agent.Attribute 6 | { 7 | /// 8 | /// 支持OnStart 运行支持 Hode住 9 | /// 10 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] 11 | public class HangJobUntilStopAttribute : JobAttribute 12 | { 13 | public bool On { get; set; } = true; 14 | 15 | public HangJobUntilStopAttribute() 16 | { 17 | } 18 | public HangJobUntilStopAttribute(string registerId) 19 | { 20 | this.RegisterId = registerId; 21 | } 22 | public HangJobUntilStopAttribute(bool on) 23 | { 24 | On = on; 25 | } 26 | 27 | public HangJobUntilStopAttribute(string registerId,bool on) 28 | { 29 | this.RegisterId = registerId; 30 | On = on; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent/Attribute/JobAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | namespace Hangfire.HttpJob.Agent.Attribute 6 | { 7 | /// 8 | /// 表达式 9 | /// 10 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] 11 | public class JobAttribute: System.Attribute 12 | { 13 | internal bool? enableAutoRegister; 14 | 15 | /// 16 | /// 是否开启自动注册 17 | /// 18 | public bool EnableAutoRegister { 19 | get 20 | { 21 | if (enableAutoRegister == null) return false; 22 | return enableAutoRegister.Value; 23 | } 24 | set { enableAutoRegister = value; } 25 | } 26 | 27 | /// 28 | /// 注册的job名称 为空的话默认是 job的class 和namespace的 md5 16位的 29 | /// 30 | public string RegisterId { get; set; } 31 | 32 | /// 33 | /// 注册的job别名 默认别名为class的name 34 | /// 35 | public string RegisterName { get; set; } 36 | 37 | } 38 | } -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent/Attribute/SingletonJobAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Hangfire.HttpJob.Agent.Attribute 6 | { 7 | /// 8 | /// 单例的 如果没运行玩再次运行会忽略执行 9 | /// 10 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] 11 | public class SingletonJobAttribute : JobAttribute 12 | { 13 | public SingletonJobAttribute() 14 | { 15 | 16 | } 17 | public SingletonJobAttribute(string registerId) 18 | { 19 | this.RegisterId = registerId; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent/Attribute/TransientJobAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Hangfire.HttpJob.Agent.Attribute 6 | { 7 | /// 8 | /// 支持并发运行 9 | /// 10 | [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] 11 | public class TransientJobAttribute : JobAttribute 12 | { 13 | public TransientJobAttribute() 14 | { 15 | 16 | } 17 | public TransientJobAttribute(string registerId) 18 | { 19 | this.RegisterId = registerId; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent/Config/ConfigureJobAgentConsoleOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Microsoft.Extensions.Configuration; 5 | using Microsoft.Extensions.Options; 6 | 7 | namespace Hangfire.HttpJob.Agent.Config 8 | { 9 | public class ConfigureJobAgentConsoleOptions : IConfigureOptions where T:class 10 | { 11 | private readonly IConfiguration configuration; 12 | 13 | public ConfigureJobAgentConsoleOptions(IConfiguration configuration) 14 | { 15 | this.configuration = configuration; 16 | } 17 | public void Configure(T options) 18 | { 19 | configuration.GetSection("JobAgent:HangfireConsol").Bind(options); 20 | } 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent/Config/ConfigureJobAgentOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Microsoft.Extensions.Configuration; 5 | using Microsoft.Extensions.Options; 6 | 7 | namespace Hangfire.HttpJob.Agent.Config 8 | { 9 | public class ConfigureJobAgentOptions : IConfigureOptions 10 | { 11 | private readonly IConfiguration configuration; 12 | 13 | public ConfigureJobAgentOptions(IConfiguration configuration) 14 | { 15 | this.configuration = configuration; 16 | } 17 | public void Configure(JobAgentOptions options) 18 | { 19 | configuration.GetSection("JobAgent").Bind(options); 20 | } 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent/Config/JobAgentOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Hangfire.HttpJob.Agent.Config 6 | { 7 | /// 8 | /// JobAgent 9 | /// 10 | public class JobAgentOptions 11 | { 12 | /// 13 | /// 是否开启jobagent功能 总开关 14 | /// 15 | public bool Enabled { get; set; } = true; 16 | 17 | /// 18 | /// jobagent的路由 19 | /// 20 | public string SitemapUrl { get; set; } = "/jobagent"; 21 | 22 | /// 23 | /// 是否开启basicAuth验证 24 | /// 25 | public bool EnabledBasicAuth { get; set; } 26 | 27 | /// 28 | /// basicauth验证用户名 29 | /// 30 | public string BasicUserName { get; set; } 31 | 32 | /// 33 | /// basicauth验证密码 34 | /// 35 | public string BasicUserPwd { get; set; } 36 | 37 | /// 38 | /// 是否开启自动注册的开关 39 | /// 40 | public bool EnableAutoRegister { get; set; } 41 | 42 | /// 43 | /// 注册job的地址 也就是hangfire调度server的地址 44 | /// 45 | public string RegisterHangfireUrl { get; set; } 46 | /// 47 | /// 当前启动agent的Host 48 | /// 49 | public string RegisterAgentHost { get; set; } 50 | 51 | /// 52 | /// basicauth验证用户名 53 | /// 54 | public string RegisterHangfireBasicName { get; set; } 55 | 56 | /// 57 | /// basicauth验证密码 58 | /// 59 | public string RegisterHangfireBasicPwd { get; set; } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent/Config/JobAgentOptionsConfigurer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Hangfire.HttpJob.Agent.Config 6 | { 7 | public sealed class JobAgentOptionsConfigurer 8 | { 9 | private readonly JobAgentOptions options; 10 | 11 | internal JobAgentOptionsConfigurer(JobAgentOptions options) 12 | { 13 | this.options = options; 14 | } 15 | 16 | public JobAgentOptionsConfigurer Enabled(bool enable = true) 17 | { 18 | options.Enabled = enable; 19 | return this; 20 | } 21 | 22 | public JobAgentOptionsConfigurer WithSitemap(string absoluteSitemapUri) 23 | { 24 | options.SitemapUrl = absoluteSitemapUri; 25 | return this; 26 | } 27 | 28 | public JobAgentOptionsConfigurer EnabledBasicAuth(bool enabledBasicAuth) 29 | { 30 | options.EnabledBasicAuth = enabledBasicAuth; 31 | return this; 32 | } 33 | 34 | public JobAgentOptionsConfigurer WithBasicUserName(string basicUserName) 35 | { 36 | options.BasicUserName = basicUserName; 37 | return this; 38 | } 39 | 40 | public JobAgentOptionsConfigurer WithBasicUserPwd(string basicUserPwd) 41 | { 42 | options.BasicUserPwd = basicUserPwd; 43 | return this; 44 | } 45 | 46 | public JobAgentOptionsConfigurer WithEnableAutoRegister(bool enableAutoRegister) 47 | { 48 | options.EnableAutoRegister = enableAutoRegister; 49 | return this; 50 | } 51 | 52 | public JobAgentOptionsConfigurer WithRegisterHangfireUrl(string registerUrl) 53 | { 54 | options.RegisterHangfireUrl = registerUrl; 55 | return this; 56 | } 57 | public JobAgentOptionsConfigurer WithRegisterAgentHost(string registerAgentHost) 58 | { 59 | options.RegisterAgentHost = registerAgentHost; 60 | return this; 61 | } 62 | 63 | public JobAgentOptionsConfigurer WithRegisterHangfireBasicName(string registerBasicUserName) 64 | { 65 | options.RegisterHangfireBasicName = registerBasicUserName; 66 | return this; 67 | } 68 | 69 | public JobAgentOptionsConfigurer WithRegisterHangfireBasicPwdd(string registerBasicUserPwd) 70 | { 71 | options.RegisterHangfireBasicPwd = registerBasicUserPwd; 72 | return this; 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent/Config/JobAgentServiceConfigurer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | using System.Linq; 4 | using System.Reflection; 5 | using Hangfire.HttpJob.Agent.Attribute; 6 | using Microsoft.Extensions.DependencyInjection; 7 | 8 | namespace Hangfire.HttpJob.Agent.Config 9 | { 10 | 11 | 12 | public class JobAgentServiceConfigurer 13 | { 14 | 15 | internal static readonly ConcurrentDictionary JobAgentDic = new ConcurrentDictionary(); 16 | 17 | public IServiceCollection Services { get; } 18 | 19 | public JobAgentServiceConfigurer(IServiceCollection serviceCollection) 20 | { 21 | Services = serviceCollection; 22 | } 23 | 24 | /// 25 | /// 添加一次 只能运行一次 运行结束才能运行下一次 26 | /// 27 | /// 28 | /// 29 | public JobAgentServiceConfigurer AddJobAgent() where T : JobAgent 30 | { 31 | var type = typeof(T); 32 | AddJobAgent(type); 33 | return this; 34 | } 35 | 36 | public JobAgentServiceConfigurer AddJobAgent(Type type) 37 | { 38 | if (!typeof(JobAgent).IsAssignableFrom(type)) 39 | { 40 | throw new InvalidCastException($"type:{type.Name} is not AssignableFrom typeOf JobAgent"); 41 | } 42 | 43 | if (JobAgentDic.ContainsKey(type)) 44 | { 45 | throw new InvalidOperationException($"type:{type.Name} is registerd!"); 46 | } 47 | 48 | //这三种标签不可以共存 49 | var scopedJobAttribute = type.GetCustomAttribute(); 50 | var singletonJobAttribute = type.GetCustomAttribute();//没有它就是默认的 51 | var hangJobUntilStopAttribute = type.GetCustomAttribute(); 52 | if(scopedJobAttribute==null && hangJobUntilStopAttribute == null && singletonJobAttribute == null) singletonJobAttribute = new SingletonJobAttribute(); 53 | var array = new object[] {scopedJobAttribute, singletonJobAttribute, hangJobUntilStopAttribute}; 54 | 55 | if (array.Count(r => r != null) > 1) 56 | { 57 | throw new InvalidCastException($"type:{type.Name} can not init with mulit xxxxJobAttribute!"); 58 | } 59 | 60 | if (!(array.FirstOrDefault(r=>r!=null) is JobAttribute regesterMeta)) 61 | { 62 | throw new InvalidCastException($"type:{type.Name} is not AssignableFrom typeOf JobAttribute"); 63 | } 64 | 65 | var meta = new JobMetaData 66 | { 67 | RegisterId = regesterMeta.RegisterId, 68 | RegisterName = regesterMeta.RegisterName, 69 | EnableAutoRegister = regesterMeta.enableAutoRegister 70 | }; 71 | 72 | if (hangJobUntilStopAttribute != null) 73 | { 74 | meta.Hang = hangJobUntilStopAttribute.On; 75 | } 76 | 77 | if (scopedJobAttribute != null) 78 | { 79 | meta.Transien = true; 80 | if (JobAgentDic.TryAdd(type, meta)) 81 | { 82 | Services.AddTransient(type); 83 | } 84 | return this; 85 | } 86 | 87 | meta.Transien = false; 88 | if (JobAgentDic.TryAdd(type, meta)) 89 | { 90 | Services.AddSingleton(type); 91 | } 92 | return this; 93 | } 94 | 95 | public JobAgentServiceConfigurer AddJobAgent(Assembly assembly) 96 | { 97 | var types = assembly.GetExportedTypes(); 98 | var agengList = (from t in types 99 | where typeof(JobAgent).IsAssignableFrom(t) && 100 | !t.IsAbstract && 101 | !t.IsInterface 102 | select t).ToList(); 103 | agengList.ForEach(r=>AddJobAgent(r)); 104 | return this; 105 | } 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent/Config/JobMetaData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace Hangfire.HttpJob.Agent.Config 6 | { 7 | internal class JobMetaData 8 | { 9 | public bool Transien { get; set; } 10 | public bool Hang { get; set; } 11 | 12 | public string RegisterName { get; set; } 13 | public string RegisterId { get; set; } 14 | public bool? EnableAutoRegister { get; set; } 15 | public bool AutoRegisterResult { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent/Console/ConsoleFontColor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Text; 5 | using System.Threading; 6 | using Newtonsoft.Json; 7 | 8 | namespace Hangfire.HttpJob.Agent 9 | { 10 | public class ConsoleFontColor 11 | { 12 | /// The color black. 13 | public static readonly ConsoleFontColor Black = new ConsoleFontColor("#000000"); 14 | /// The color dark blue. 15 | public static readonly ConsoleFontColor DarkBlue = new ConsoleFontColor("#000080"); 16 | /// The color dark green. 17 | public static readonly ConsoleFontColor DarkGreen = new ConsoleFontColor("#008000"); 18 | /// The color dark cyan (dark blue-green). 19 | public static readonly ConsoleFontColor DarkCyan = new ConsoleFontColor("#008080"); 20 | /// The color dark red. 21 | public static readonly ConsoleFontColor DarkRed = new ConsoleFontColor("#800000"); 22 | /// The color dark magenta (dark purplish-red). 23 | public static readonly ConsoleFontColor DarkMagenta = new ConsoleFontColor("#800080"); 24 | /// The color dark yellow (ochre). 25 | public static readonly ConsoleFontColor DarkYellow = new ConsoleFontColor("#808000"); 26 | /// The color gray. 27 | public static readonly ConsoleFontColor Gray = new ConsoleFontColor("#c0c0c0"); 28 | /// The color dark gray. 29 | public static readonly ConsoleFontColor DarkGray = new ConsoleFontColor("#808080"); 30 | /// The color blue. 31 | public static readonly ConsoleFontColor Blue = new ConsoleFontColor("#0000ff"); 32 | /// The color green. 33 | public static readonly ConsoleFontColor Green = new ConsoleFontColor("#00ff00"); 34 | /// The color cyan (blue-green). 35 | public static readonly ConsoleFontColor Cyan = new ConsoleFontColor("#00ffff"); 36 | /// The color red. 37 | public static readonly ConsoleFontColor Red = new ConsoleFontColor("#ff0000"); 38 | /// The color magenta (purplish-red). 39 | public static readonly ConsoleFontColor Magenta = new ConsoleFontColor("#ff00ff"); 40 | /// The color yellow. 41 | public static readonly ConsoleFontColor Yellow = new ConsoleFontColor("#ffff00"); 42 | /// The color white. 43 | public static readonly ConsoleFontColor White = new ConsoleFontColor("#ffffff"); 44 | private readonly string _color; 45 | 46 | private ConsoleFontColor(string color) 47 | { 48 | this._color = color; 49 | } 50 | 51 | /// 52 | public override string ToString() 53 | { 54 | return this._color; 55 | } 56 | 57 | /// 58 | /// Implicitly converts to . 59 | /// 60 | public static implicit operator string(ConsoleFontColor color) 61 | { 62 | return color?._color; 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent/Console/ConsoleInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Text; 5 | using System.Threading; 6 | using Newtonsoft.Json; 7 | 8 | namespace Hangfire.HttpJob.Agent 9 | { 10 | public class ConsoleInfo 11 | { 12 | public string SetKey { get; set; } 13 | public int ProgressBarId { get; set; } 14 | public string HashKey { get; set; } 15 | public DateTime StartTime { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent/Console/ConsoleLine.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Text; 5 | using System.Threading; 6 | using Newtonsoft.Json; 7 | 8 | namespace Hangfire.HttpJob.Agent 9 | { 10 | internal class ConsoleLine 11 | { 12 | /// 13 | /// Time offset since console timestamp in fractional seconds 14 | /// 15 | [JsonProperty("t", Required = Required.Always)] 16 | public double TimeOffset { get; set; } 17 | 18 | /// 19 | /// True if is a Hash reference. 20 | /// 21 | [JsonProperty("r", DefaultValueHandling = DefaultValueHandling.Ignore)] 22 | public bool IsReference { get; set; } 23 | 24 | /// 25 | /// Message text, or message reference, or progress bar id 26 | /// 27 | [JsonProperty("s", Required = Required.Always)] 28 | public string Message { get; set; } 29 | 30 | /// 31 | /// Text color for this message 32 | /// 33 | [JsonProperty("c", DefaultValueHandling = DefaultValueHandling.Ignore)] 34 | public string TextColor { get; set; } 35 | 36 | /// 37 | /// Value update for a progress bar 38 | /// 39 | [JsonProperty("p", DefaultValueHandling = DefaultValueHandling.Ignore)] 40 | public double? ProgressValue { get; set; } 41 | 42 | /// 43 | /// Optional name for a progress bar 44 | /// 45 | [JsonProperty("n", DefaultValueHandling = DefaultValueHandling.Ignore)] 46 | public string ProgressName { get; set; } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent/Console/HangfireProgressBar.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Text; 5 | using System.Threading; 6 | using Newtonsoft.Json; 7 | 8 | namespace Hangfire.HttpJob.Agent 9 | { 10 | 11 | public class HangfireProgressBar : IProgressBar 12 | { 13 | private readonly HangfireConsole _context; 14 | private readonly string _progressBarId; 15 | private string _name; 16 | private string _color; 17 | private double _value; 18 | 19 | internal HangfireProgressBar(HangfireConsole context, string progressBarId, string name, ConsoleFontColor color = null) 20 | { 21 | if (string.IsNullOrEmpty(progressBarId)) 22 | throw new ArgumentNullException(nameof(progressBarId)); 23 | 24 | _context = context ?? throw new ArgumentNullException(nameof(context)); 25 | _progressBarId = progressBarId; 26 | _name = name; 27 | _color = color; 28 | _value = -1; 29 | } 30 | 31 | 32 | 33 | public void SetValue(int value) 34 | { 35 | SetValue((double)value); 36 | } 37 | 38 | public void SetValue(double value) 39 | { 40 | value = Math.Round(value, 1); 41 | 42 | if (value < 0 || value > 100) 43 | throw new ArgumentOutOfRangeException(nameof(value), "Value should be in range 0..100"); 44 | 45 | // ReSharper disable once CompareOfFloatsByEqualityOperator 46 | if (Interlocked.Exchange(ref _value, value) == value) return; 47 | 48 | _context.WriteBar(new ConsoleLine() { Message = _progressBarId, ProgressName = _name, ProgressValue = value, TextColor = _color }); 49 | 50 | _name = String.IsNullOrEmpty(_name) ? null : _name; 51 | _color = String.IsNullOrEmpty(_color) ? null : _color; 52 | } 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent/Console/IHangfireConsole.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Text; 5 | using System.Threading; 6 | using Newtonsoft.Json; 7 | 8 | namespace Hangfire.HttpJob.Agent 9 | { 10 | 11 | public interface IHangfireStorage:IDisposable 12 | { 13 | void SetRangeInHash(string key, IEnumerable> keyValuePairs); 14 | 15 | void AddToSet(string key, string value, double score); 16 | } 17 | 18 | public interface ICommonConsole 19 | { 20 | void Error(string err); 21 | void Error(Exception err); 22 | void Info(string info); 23 | void Warning(string warn); 24 | 25 | void Warning(Exception warn); 26 | } 27 | 28 | public interface IHangfireConsole: ICommonConsole 29 | { 30 | void WriteLine(string message, ConsoleFontColor fontColor = null); 31 | IProgressBar WriteProgressBar(string name, double initValue=1, ConsoleFontColor color = null); 32 | } 33 | 34 | 35 | /// 36 | /// Progress bar line inside console. 37 | /// 38 | public interface IProgressBar 39 | { 40 | /// 41 | /// Updates a value of a progress bar. 42 | /// 43 | /// New value 44 | void SetValue(int value); 45 | 46 | /// 47 | /// Updates a value of a progress bar. 48 | /// 49 | /// New value 50 | void SetValue(double value); 51 | } 52 | 53 | public interface IHangfireConsoleInit 54 | { 55 | void Init(ConsoleInfo consoleInfo); 56 | } 57 | 58 | 59 | 60 | } 61 | -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent/Console/IStorageFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Text; 5 | using System.Threading; 6 | using Newtonsoft.Json; 7 | 8 | namespace Hangfire.HttpJob.Agent 9 | { 10 | public interface IStorageFactory 11 | { 12 | IHangfireStorage CreateHangfireStorage(JobStorageConfig config); 13 | IHangfireConsole CreateHangforeConsole(IHangfireStorage storage); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent/Hangfire.HttpJob.Agent.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.0;net461 5 | yuzd 6 | Hangfire HttpJob Agent 7 | HttpJob Agent for Hangfire 8 | https://github.com/yuzd/Hangfire.HttpJob 9 | true 10 | yuzd 11 | 1.5.1 12 | true 13 | MIT 14 | 1.5.1.0 15 | 1.5.1.0 16 | 17 | 18 | 19 | 20 | 21 | TRACE;NETCORE 22 | 23 | 24 | TRACE;OWIN 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent/JobAgentApplicationBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Threading; 5 | using Hangfire.HttpJob.Agent.Config; 6 | using Microsoft.AspNetCore.Builder; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.DependencyInjection; 10 | using Microsoft.Extensions.Hosting; 11 | using Microsoft.Extensions.Logging; 12 | using Microsoft.Extensions.Options; 13 | 14 | #if !NETCORE 15 | using Owin; 16 | 17 | #endif 18 | 19 | namespace Hangfire.HttpJob.Agent 20 | { 21 | public static class JobAgentApplicationBuilderExtensions 22 | { 23 | #if NETCORE 24 | public static IApplicationBuilder UseHangfireHttpJobAgent(this IApplicationBuilder app, 25 | Action configureOptions = null) 26 | #else 27 | public static IAppBuilder UseHangfireHttpJobAgent(this IAppBuilder app,IServiceCollection services, 28 | Action configureOptions = null) 29 | #endif 30 | 31 | { 32 | 33 | #if NETCORE 34 | var sp = app.ApplicationServices; 35 | #else 36 | var sp = services.BuildServiceProvider();//OWIN 37 | var configRoot = sp.GetRequiredService(); 38 | services.Configure(configRoot.GetSection("JobAgent")); 39 | sp = services.BuildServiceProvider();//OWIN 40 | #endif 41 | var evt = new EventId(1, "Hangfire.HttpJob.Agent"); 42 | var loggerFactory = sp.GetService(); 43 | var logger = loggerFactory.CreateLogger(); 44 | var options = sp.GetService>(); 45 | 46 | var configurer = new JobAgentOptionsConfigurer(options.Value); 47 | try 48 | { 49 | configureOptions?.Invoke(configurer); 50 | } 51 | catch (Exception exception) 52 | { 53 | logger.LogCritical(evt, exception, "Failed to configure JobAgent middleware"); 54 | } 55 | 56 | if (!options.Value.Enabled) 57 | { 58 | return app; 59 | } 60 | 61 | 62 | if (string.IsNullOrEmpty(options.Value.SitemapUrl)) options.Value.SitemapUrl = "/jobagent"; 63 | foreach (KeyValuePair jobAgent in JobAgentServiceConfigurer.JobAgentDic) 64 | { 65 | logger.LogInformation(evt, $"【HttpJobAgent】 - [{jobAgent.Key.Name}] [Transient:{jobAgent.Value.Transien}] [HangJob:{jobAgent.Value.Hang}] - Registered"); 66 | } 67 | var registerService = new JobAgentRegisterService(options, loggerFactory); 68 | 69 | #if NETCORE 70 | var lifeRegister = sp.GetRequiredService(); 71 | lifeRegister.ApplicationStarted.Register(async () => 72 | { 73 | await registerService.StartAsync(CancellationToken.None); 74 | }); 75 | lifeRegister.ApplicationStopping.Register(async () => 76 | { 77 | await registerService.StopAsync(CancellationToken.None); 78 | }); 79 | #endif 80 | logger.LogInformation(evt, "【HttpJobAgent】 - Registered HttpJobAgent middleware to respond to {path}", new { path = options.Value.SitemapUrl }); 81 | #if NETCORE 82 | app.Map(options.Value.SitemapUrl, robotsApp => 83 | { 84 | robotsApp.UseMiddleware(); 85 | }); 86 | #else 87 | app.Map(options.Value.SitemapUrl, robotsApp => 88 | { 89 | robotsApp.Use(logger, options, loggerFactory, sp); 90 | }); 91 | 92 | registerService.StartAsync(CancellationToken.None).ConfigureAwait(false).GetAwaiter().GetResult(); 93 | #endif 94 | 95 | return app; 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent/JobAgentServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Reflection; 4 | using System.Text; 5 | using Hangfire.HttpJob.Agent.Config; 6 | using Microsoft.Extensions.DependencyInjection; 7 | using Microsoft.Extensions.DependencyInjection.Extensions; 8 | using Microsoft.Extensions.Options; 9 | 10 | namespace Hangfire.HttpJob.Agent 11 | { 12 | public static class JobAgentServiceCollectionExtensions 13 | { 14 | public static IServiceCollection AddHangfireHttpJobAgent(this IServiceCollection serviceCollection, Action configure = null) 15 | { 16 | serviceCollection.AddOptions(); 17 | serviceCollection.TryAddSingleton, ConfigureJobAgentOptions>(); 18 | var configurer = new JobAgentServiceConfigurer(serviceCollection); 19 | if (configure == null) 20 | { 21 | var assembly = Assembly.GetEntryAssembly(); 22 | configure = (c) => { c.AddJobAgent(assembly); }; 23 | } 24 | configure.Invoke(configurer); 25 | serviceCollection.TryAddSingleton(); 26 | return serviceCollection; 27 | 28 | } 29 | 30 | 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent/JobStatus.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Hangfire.HttpJob.Agent 8 | { 9 | internal enum JobStatus 10 | { 11 | Default, 12 | Running, 13 | Stopping, 14 | Stoped, 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent/Util/CodingUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Newtonsoft.Json; 3 | 4 | namespace Hangfire.HttpJob.Agent.Util 5 | { 6 | internal static class CodingUtil 7 | { 8 | 9 | 10 | public static T ToJson(this string str) 11 | { 12 | try 13 | { 14 | return JsonConvert.DeserializeObject(str); 15 | } 16 | catch (Exception ) 17 | { 18 | return default(T); 19 | } 20 | 21 | } 22 | 23 | /// 24 | ///由秒数得到日期几天几小时。。。 25 | ///秒数 27 | ///0:转换后带秒,1:转换后不带秒 28 | ///几天几小时几分几秒 29 | public static string ParseTimeSeconds(int t, int type = 0) 30 | { 31 | string r = ""; 32 | int day, hour, minute, second; 33 | if (t >= 86400) //天, 34 | { 35 | day = Convert.ToInt16(t / 86400); 36 | hour = Convert.ToInt16((t % 86400) / 3600); 37 | minute = Convert.ToInt16((t % 86400 % 3600) / 60); 38 | second = Convert.ToInt16(t % 86400 % 3600 % 60); 39 | if (type == 0) 40 | r = day + ("D") + hour + ("H") + minute + ("M") + second + ("S"); 41 | else 42 | r = day + ("D") + hour + ("H") + minute + ("M"); 43 | 44 | } 45 | else if (t >= 3600)//时, 46 | { 47 | hour = Convert.ToInt16(t / 3600); 48 | minute = Convert.ToInt16((t % 3600) / 60); 49 | second = Convert.ToInt16(t % 3600 % 60); 50 | if (type == 0) 51 | r = hour + ("H") + minute + ("M") + second + ("S"); 52 | else 53 | r = hour + ("H") + minute + ("M"); 54 | } 55 | else if (t >= 60)//分 56 | { 57 | minute = Convert.ToInt16(t / 60); 58 | second = Convert.ToInt16(t % 60); 59 | r = minute + ("M") + second + ("S"); 60 | } 61 | else 62 | { 63 | second = Convert.ToInt16(t); 64 | r = second + ("S"); 65 | } 66 | return r; 67 | } 68 | 69 | } 70 | } -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent/Util/LazyConcurrentDictionary.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | using System.Collections.Generic; 4 | using System.Threading; 5 | 6 | namespace Hangfire.HttpJob.Agent.Util 7 | { 8 | internal class LazyConcurrentDictionary 9 | { 10 | private readonly ConcurrentDictionary>> concurrentDictionary; 11 | 12 | 13 | public LazyConcurrentDictionary() 14 | { 15 | this.concurrentDictionary = new ConcurrentDictionary>>(); 16 | } 17 | 18 | public ConcurrentDictionary GetOrAdd(string key, Func> valueFactory) 19 | { 20 | var lazyResult = 21 | this.concurrentDictionary.GetOrAdd(key, k => new Lazy>(() => valueFactory(k), LazyThreadSafetyMode.ExecutionAndPublication)); 22 | 23 | return lazyResult.Value; 24 | } 25 | 26 | public bool TryGetValue(string key, out ConcurrentDictionary value) 27 | { 28 | var rt = concurrentDictionary.TryGetValue(key, out Lazy> valueLazy); 29 | value = rt ? valueLazy.Value : new ConcurrentDictionary(); 30 | return rt; 31 | } 32 | 33 | public bool TryRemove(string key, out ConcurrentDictionary value) 34 | { 35 | var rt = concurrentDictionary.TryRemove(key, out Lazy> valueLazy); 36 | value = rt ? valueLazy.Value : new ConcurrentDictionary(); 37 | return rt; 38 | } 39 | 40 | public void JobRemove(object state,TransitentJobDisposeArgs args) 41 | { 42 | try 43 | { 44 | if(args == null) return; 45 | if (string.IsNullOrEmpty(args.Key) || string.IsNullOrEmpty(args.Guid)) return; 46 | if(this.TryGetValue(args.Key ,out var dic)) 47 | { 48 | dic.TryRemove(args.Guid,out _); 49 | } 50 | } 51 | catch (Exception) 52 | { 53 | //ignore 54 | } 55 | } 56 | } 57 | 58 | internal class TransitentJobDisposeArgs : EventArgs 59 | { 60 | public string Key { get; private set; } 61 | public string Guid { get; private set; } 62 | 63 | public TransitentJobDisposeArgs(string key,string guid) 64 | { 65 | Key = key; 66 | Guid = guid; 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /Agent/Hangfire.HttpJob.Agent/Util/LoggerConsole.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Microsoft.Extensions.Logging; 5 | 6 | namespace Hangfire.HttpJob.Agent.Util 7 | { 8 | internal class LoggerConsole : HangfireConsole 9 | { 10 | private readonly ILogger _logger; 11 | public LoggerConsole(ILogger logger) 12 | { 13 | _logger = logger; 14 | } 15 | 16 | public override IHangfireStorage Storage => new LocalLoggerConsole(_logger); 17 | } 18 | 19 | internal class LocalLoggerConsole : IHangfireStorage 20 | { 21 | private readonly ILogger _logger; 22 | 23 | public LocalLoggerConsole(ILogger logger) 24 | { 25 | _logger = logger; 26 | } 27 | public void Dispose() 28 | { 29 | } 30 | 31 | public void SetRangeInHash(string key, IEnumerable> keyValuePairs) 32 | { 33 | foreach (var keyvalue in keyValuePairs) 34 | { 35 | _logger.LogInformation(new EventId(0, key), keyvalue.Key + "->" + keyvalue.Value); 36 | } 37 | 38 | } 39 | 40 | public void AddToSet(string key, string value, double score) 41 | { 42 | _logger.LogInformation(key + "->" + value); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Agent/Template/README.md: -------------------------------------------------------------------------------- 1 | ## HttpAgent Project Template 2 | 3 | ### Push to Nuget 4 | 5 | * dotnet pack 6 | * modified Template.csproj 7 | * push to nuget.org 8 | 9 | 10 | ### Quick Start 11 | 12 | **install** 13 | ``` 14 | dotnet new -i HttpJob.Agent.Template 15 | ``` 16 | 17 | **usage** 18 | ``` 19 | ## --type default value is RedisConsole 20 | dotnet new agent -n=Hello --type=MysqlConsole 21 | ``` -------------------------------------------------------------------------------- /Agent/Template/Template.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | Template 4 | 1.0.1 5 | HttpJob.Agent.Template 6 | HttpJob Agent Quick Start Project Template 7 | agent 8 | dotnet-new;templates;httpjob;hangfire 9 | netstandard2.0 10 | 11 | true 12 | false 13 | content 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Agent/Template/templates/Template/.template.config/template.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json.schemastore.org/template", 3 | "author": "agent", 4 | "classifications": [ "agent", "webapi","httpjob" ], 5 | "identity": "HttpJob.Agent.Template", 6 | "name": "Hangfire HttpJob Agent QuickStart Project Template", 7 | "shortName": "agent", 8 | "sourceName": "Template", 9 | "preferNameDirectory": true, 10 | "symbols":{ 11 | "type": { 12 | "type": "parameter", 13 | "defaultValue": "RedisConsole", 14 | "replaces":"AgentType" 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /Agent/Template/templates/Template/Jobs/TestHangJob.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Hangfire.HttpJob.Agent; 6 | using Hangfire.HttpJob.Agent.Attribute; 7 | using Microsoft.Extensions.Logging; 8 | 9 | namespace Template.Jobs 10 | { 11 | [HangJobUntilStop(RegisterName = "HangJob测试")] 12 | public class TestHangJob : JobAgent 13 | { 14 | private readonly ILogger _logger; 15 | 16 | public TestHangJob(ILogger logger) 17 | { 18 | _logger = logger; 19 | _logger.LogInformation($"Create {nameof(TestHangJob)} Instance Success"); 20 | } 21 | public override async Task OnStart(JobContext jobContext) 22 | { 23 | jobContext.Console.Info(nameof(OnStart) + (jobContext.Param ?? string.Empty)); 24 | 25 | while (!jobContext.CancelToken.IsCancellationRequested) 26 | { 27 | jobContext.Console.Info("dddd"); 28 | await Task.Delay(1000 * 10); 29 | } 30 | throw new Exception("dddddd"); 31 | jobContext.Console.Warning("game over"); 32 | } 33 | 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Agent/Template/templates/Template/Jobs/TestJob.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Hangfire.HttpJob.Agent; 6 | using Hangfire.HttpJob.Agent.Attribute; 7 | using Microsoft.Extensions.Logging; 8 | 9 | namespace Template.Jobs 10 | { 11 | [SingletonJob(RegisterName = "单例job")]//不打这个标签也行 默认就是单例的 12 | public class TestJob : JobAgent 13 | { 14 | private readonly ILogger _logger; 15 | 16 | public TestJob(ILogger logger) 17 | { 18 | _logger = logger; 19 | _logger.LogInformation($"Create {nameof(TestJob)} Instance Success"); 20 | } 21 | public override async Task OnStart(JobContext jobContext) 22 | { 23 | jobContext.Console.Info("info消息"); 24 | jobContext.Console.Warning("waring消息"); 25 | jobContext.Console.Error("error消息"); 26 | jobContext.Console.Info("开始等待1秒"); 27 | await Task.Delay(1000 * 1); 28 | jobContext.Console.Info("结束等待1秒"); 29 | jobContext.Console.WriteLine("开始测试Progressbar", ConsoleFontColor.Cyan); 30 | 31 | var bar = jobContext.Console.WriteProgressBar("testbar"); 32 | for (int i = 0; i < 10; i++) 33 | { 34 | bar.SetValue(i * 10); 35 | await Task.Delay(1000); 36 | } 37 | } 38 | 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Agent/Template/templates/Template/Jobs/TestTransientJob.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | using Hangfire.HttpJob.Agent; 7 | using Hangfire.HttpJob.Agent.Attribute; 8 | using Microsoft.Extensions.Logging; 9 | 10 | namespace Template.Jobs 11 | { 12 | [TransientJob(RegisterName = "多例job")] 13 | public class TestTransientJob:JobAgent 14 | { 15 | private readonly ILogger _logger; 16 | 17 | public TestTransientJob(ILogger logger) 18 | { 19 | _logger = logger; 20 | _logger.LogInformation($"Create {nameof(TestTransientJob)} Instance Success"); 21 | } 22 | public override async Task OnStart(JobContext jobContext) 23 | { 24 | jobContext.Console.Warning("ManagedThreadId:" + Thread.CurrentThread.ManagedThreadId); 25 | _logger.LogWarning("ManagedThreadId:" + Thread.CurrentThread.ManagedThreadId); 26 | await Task.Delay(5000); 27 | _logger.LogWarning(nameof(OnStart) + (jobContext.Param ?? string.Empty)); 28 | jobContext.Console.Warning(nameof(OnStart) + (jobContext.Param ?? string.Empty)); 29 | } 30 | 31 | 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Agent/Template/templates/Template/NLog.Config: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 20 | 21 | 22 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /Agent/Template/templates/Template/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.Hosting; 10 | using Microsoft.Extensions.Logging; 11 | using NLog.Web; 12 | 13 | namespace TestSqlserverHangfireAgent 14 | { 15 | public class Program 16 | { 17 | public static void Main(string[] args) 18 | { 19 | var logger = NLog.Web.NLogBuilder.ConfigureNLog("NLog.Config").GetCurrentClassLogger(); 20 | try 21 | { 22 | logger.Debug("init main"); 23 | CreateHostBuilder(args).Build().Run(); 24 | } 25 | catch (Exception ex) 26 | { 27 | //NLog: catch setup errors 28 | logger.Error(ex, "Stopped program because of exception"); 29 | throw; 30 | } 31 | finally 32 | { 33 | // Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux) 34 | NLog.LogManager.Shutdown(); 35 | } 36 | } 37 | 38 | public static IHostBuilder CreateHostBuilder(string[] args) => 39 | Host.CreateDefaultBuilder(args) 40 | .ConfigureWebHostDefaults(webBuilder => 41 | { 42 | webBuilder.UseStartup() 43 | .ConfigureLogging(logging => 44 | { 45 | logging.ClearProviders(); 46 | #if DEBUG 47 | logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Debug); 48 | 49 | #else 50 | logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace); 51 | #endif 52 | }).UseNLog(); 53 | }); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Agent/Template/templates/Template/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "TestHangfireRedisAgent": { 4 | "commandName": "Project", 5 | "launchBrowser": true, 6 | "applicationUrl": "http://0.0.0.0:5000", 7 | "environmentVariables": { 8 | "ASPNETCORE_ENVIRONMENT": "Development" 9 | } 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Agent/Template/templates/Template/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Hangfire.HttpJob.Agent; 6 | using Hangfire.HttpJob.Agent.RedisConsole; 7 | using Microsoft.AspNetCore.Builder; 8 | using Microsoft.AspNetCore.Hosting; 9 | using Microsoft.AspNetCore.Http; 10 | using Microsoft.Extensions.DependencyInjection; 11 | using Microsoft.Extensions.Logging; 12 | using NLog.Extensions.Logging; 13 | 14 | namespace TestSqlserverHangfireAgent 15 | { 16 | public class Startup 17 | { 18 | // This method gets called by the runtime. Use this method to add services to the container. 19 | // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 20 | public void ConfigureServices(IServiceCollection services) 21 | { 22 | services.AddHangfireJobAgent(); 23 | } 24 | 25 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 26 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory logging) 27 | { 28 | app.UseHangfireJobAgent(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Agent/Template/templates/Template/Template.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | Always 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Agent/Template/templates/Template/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Agent/Template/templates/Template/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "IncludeScopes": false, 4 | "LogLevel": { 5 | "Default": "Trace", 6 | "Microsoft": "Warning", 7 | "Microsoft.Hosting.Lifetime": "Information" 8 | } 9 | }, 10 | "JobAgent": { 11 | "Enabled": true, 12 | "SitemapUrl": "/jobagent", 13 | "EnabledBasicAuth": true, 14 | "BasicUserName": "test", 15 | "BasicUserPwd": "123456", 16 | "EnableAutoRegister": true, 17 | "RegisterAgentHost": "http://localhost:5002", 18 | "RegisterHangfireUrl": "http://localhost:5000/job", 19 | "RegisterHangfireBasicName": "admin", 20 | "RegisterHangfireBasicPwd": "test" 21 | } 22 | } -------------------------------------------------------------------------------- /Client/Hangfire.HttpJob.Client/Hangfire.HttpJob.Client.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net45;netstandard2.0 5 | true 6 | yuzd 7 | Hangfire HttpJob Client 8 | zdyu 9 | https://github.com/yuzd/Hangfire.HttpJob 10 | yuzd 11 | 1.2.9 12 | true 13 | MIT 14 | 1.2.9.0 15 | 1.2.9.0 16 | 17 | 18 | 19 | portable 20 | TRACE;DEBUG 21 | 22 | 23 | 24 | RELEASE 25 | 26 | 27 | 28 | $(DefineConstants);NETCORE 29 | 30 | 31 | 32 | TRACE;DEBUG;NET45 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /Client/Hangfire.HttpJob.Client/HangfireHttpClientFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net; 5 | using System.Net.Http; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using HttpClientFactory.Impl; 9 | 10 | namespace Hangfire.HttpJob.Client 11 | { 12 | internal class HangfireHttpClientFactory:PerHostHttpClientFactory 13 | { 14 | protected override HttpClient CreateHttpClient(HttpMessageHandler handler) 15 | { 16 | var client = new HttpClient(handler); 17 | client.DefaultRequestHeaders.ConnectionClose = false; 18 | client.Timeout = TimeSpan.FromHours(1); 19 | client.DefaultRequestHeaders.Add("UserAgent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36"); 20 | return client; 21 | } 22 | 23 | protected override HttpMessageHandler CreateMessageHandler(string proxyUrl = null) 24 | { 25 | var handler = new HttpClientHandler(); 26 | if (string.IsNullOrEmpty(proxyUrl)) 27 | { 28 | handler.UseProxy = false; 29 | } 30 | else 31 | { 32 | handler.UseProxy = true; 33 | handler.Proxy = new WebProxy(proxyUrl); 34 | } 35 | 36 | handler.AllowAutoRedirect = false; 37 | handler.AutomaticDecompression = DecompressionMethods.None; 38 | handler.UseCookies = false; 39 | return handler; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Client/Hangfire.HttpJob.Client/HangfireJobResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Hangfire.HttpJob.Client 8 | { 9 | public class HangfirJobResult 10 | { 11 | public string ErrMessage { get; set; } 12 | public bool IsSuccess { get; set; } 13 | 14 | } 15 | 16 | public class AddBackgroundHangfirJobResult: HangfirJobResult 17 | { 18 | public string JobId { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Client/Hangfire.HttpJob.Client/HangfireServerPostOption.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net; 5 | using System.Net.Http; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Hangfire.HttpJob.Client 10 | { 11 | 12 | /// 13 | /// 其他额外设置 14 | /// 15 | public class HangfireServerPostOption 16 | { 17 | public HangfireServerPostOption() 18 | { 19 | TimeOut = 5000; 20 | ThrowException = false; 21 | } 22 | 23 | /// 24 | /// 请求HangfireServer的超时时间 毫秒 25 | /// 26 | public int TimeOut { get; set; } 27 | 28 | /// 29 | /// 请求HangfireServer的时候错误是否抛出 30 | /// 31 | public bool ThrowException { get; set; } 32 | 33 | /// 34 | /// 请求HangfireServer的basic 验证的用户名 35 | /// 36 | public string BasicUserName { get; set; } 37 | 38 | /// 39 | /// 请求HangfireServer的basic 验证的密码 40 | /// 41 | public string BasicPassword { get; set; } 42 | 43 | /// 44 | /// 代理 45 | /// 46 | public string ProxyUrl { get; set; } 47 | 48 | internal HttpClient HttpClient { get; set; } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Client/Hangfire.HttpJob.Client/RecurringJob.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Hangfire.HttpJob.Client 8 | { 9 | 10 | /// 11 | /// 循环job 12 | /// 13 | public class RecurringJob 14 | { 15 | public RecurringJob() 16 | { 17 | Method = "Post"; 18 | ContentType = "application/json"; 19 | Timeout = 20000; 20 | } 21 | /// 22 | /// 请求Url 23 | /// 24 | public string Url { get; set; } 25 | 26 | /// 27 | /// 请求参数 28 | /// 29 | public string Method { get; set; } 30 | 31 | /// 32 | /// 参数 33 | /// 34 | public object Data { get; set; } 35 | 36 | /// 37 | /// 类型 38 | /// 39 | public string ContentType { get; set; } 40 | 41 | /// 42 | /// 超时 毫秒 43 | /// 44 | public int Timeout { get; set; } 45 | 46 | /// 47 | /// Cron表达式 48 | /// 49 | public string Cron { get; set; } 50 | 51 | /// 52 | /// JOB的名称 53 | /// 54 | public string JobName { get; set; } 55 | 56 | /// 57 | /// job的唯一标识 如果没有设置值的话就等同于JobName 58 | /// 59 | public string RecurringJobIdentifier { get; set; } 60 | 61 | /// 62 | /// QueueName的名称 如果不配置就用默认的 DEFAULT 63 | /// 64 | public string QueueName { get; set; } 65 | 66 | /// 67 | /// 是否成功发送通知 68 | /// 69 | public bool SendSuccess { get; set; } 70 | 71 | /// 72 | /// 是否失败发送通知 73 | /// 74 | public bool SendFail { get; set; } 75 | 76 | /// 77 | /// 指定发送邮件 78 | /// 79 | public List Mail { get; set; } 80 | 81 | /// 82 | /// 开启失败重启 83 | /// 84 | public bool EnableRetry { get; set; } 85 | 86 | /// 87 | /// 错误尝试次数自定义 88 | /// 89 | public int RetryTimes { get; set; } 90 | 91 | /// 92 | /// 失败重试区间 半角逗号隔开 93 | /// 94 | public string RetryDelaysInSeconds { get; set; } 95 | 96 | /// 97 | /// basic 验证用户名 98 | /// 99 | public string BasicUserName { get; set; } 100 | 101 | /// 102 | /// basic 验证密码 103 | /// 104 | public string BasicPassword { get; set; } 105 | 106 | /// 107 | /// 代理设置 108 | /// 109 | public string AgentClass { get; set; } 110 | 111 | /// 112 | /// 判断是否成功还是失败的EL表达式 113 | /// 114 | public string CallbackEL { get; set; } 115 | 116 | /// 117 | /// Header 118 | /// 119 | public Dictionary Headers { get; set; } = new Dictionary(); 120 | 121 | public HttpCallbackJob Success { get; set; } 122 | public HttpCallbackJob Fail { get; set; } 123 | /// 124 | /// 每个job运行的时区 125 | /// 126 | public string TimeZone { get; set; } 127 | 128 | /// 129 | /// 钉钉配置 130 | /// 131 | public DingTalkOption DingTalk { get; set; } 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Server/Hangfire.HttpJob/Dashboard/DynamicCssDispatcher.cs: -------------------------------------------------------------------------------- 1 | using Hangfire.Dashboard; 2 | using System; 3 | using System.Text; 4 | using System.Threading.Tasks; 5 | 6 | namespace Hangfire.HttpJob.Dashboard 7 | { 8 | public class DynamicCssDispatcher : IDashboardDispatcher 9 | { 10 | private readonly HangfireHttpJobOptions _options; 11 | public DynamicCssDispatcher(HangfireHttpJobOptions options) 12 | { 13 | if (options == null) 14 | throw new ArgumentNullException(nameof(options)); 15 | 16 | _options = options; 17 | } 18 | 19 | public Task Dispatch(DashboardContext context) 20 | { 21 | var builder = new StringBuilder(); 22 | 23 | builder.AppendLine(".table tbody .tooltip{word-break: break-all;}"); 24 | 25 | builder.AppendLine(".console, .console .line-buffer {") 26 | .Append(" color: ").Append("red").AppendLine(";") 27 | .AppendLine("}"); 28 | 29 | if (context.Request != null) 30 | { 31 | if (context is AspNetCoreDashboardContext abc) 32 | { 33 | if (abc.HttpContext.Request.Headers.TryGetValue("Referer", out var refer) && (refer.ToString().Contains("/processing") ||refer.ToString().Contains("/recurring")|| refer.ToString().Contains("/succeeded") || refer.ToString().Contains("/deleted"))) 34 | { 35 | builder.AppendLine(".table tbody { display:none; }"); 36 | } 37 | } 38 | } 39 | 40 | return context.Response.WriteAsync(builder.ToString()); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Server/Hangfire.HttpJob/Dashboard/Heartbeat/Dashboard/ContentDispatcher.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Threading.Tasks; 4 | using Hangfire.Dashboard; 5 | 6 | namespace Hangfire.Heartbeat.Dashboard 7 | { 8 | internal class ContentDispatcher : IDashboardDispatcher 9 | { 10 | private static readonly Assembly ThisAssembly = typeof(ContentDispatcher).Assembly; 11 | private readonly string _contentType; 12 | private readonly string _resourceName; 13 | private readonly TimeSpan _expiresIn; 14 | 15 | public ContentDispatcher(string contentType, string resourceName, TimeSpan expiresIn) 16 | { 17 | _contentType = contentType; 18 | _resourceName = resourceName; 19 | _expiresIn = expiresIn; 20 | } 21 | 22 | public async Task Dispatch(DashboardContext context) 23 | { 24 | context.Response.ContentType = _contentType; 25 | context.Response.SetExpire(DateTimeOffset.UtcNow + _expiresIn); 26 | 27 | await WriteResourceAsync(context); 28 | } 29 | 30 | private async Task WriteResourceAsync(DashboardContext context) 31 | { 32 | using (var stream = ThisAssembly.GetManifestResourceStream(_resourceName)) 33 | { 34 | if (stream == null) 35 | { 36 | context.Response.StatusCode = 404; 37 | } 38 | else 39 | { 40 | await stream.CopyToAsync(context.Response.Body); 41 | } 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Server/Hangfire.HttpJob/Dashboard/Heartbeat/Dashboard/OverviewPage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Hangfire.Dashboard; 3 | using Hangfire.Dashboard.Pages; 4 | 5 | namespace Hangfire.Heartbeat.Dashboard 6 | { 7 | internal sealed class OverviewPage : RazorPage 8 | { 9 | private readonly HeartbeatDashboardOptions _dashboardOptions; 10 | public const string Title = "Heartbeat"; 11 | public const string PageRoute = "/heartbeat"; 12 | public const string StatsRoute = "/heartbeat/stats"; 13 | 14 | private static readonly string PageHtml; 15 | 16 | static OverviewPage() 17 | { 18 | PageHtml = Utils.ReadStringResource("Hangfire.HttpJob.Dashboard.Heartbeat.Dashboard.html.OverviewPage.html"); 19 | } 20 | 21 | public OverviewPage(HeartbeatDashboardOptions dashboardOptions) 22 | { 23 | _dashboardOptions = dashboardOptions ?? throw new ArgumentNullException(nameof(dashboardOptions)); 24 | } 25 | 26 | public override void Execute() 27 | { 28 | WriteEmptyLine(); 29 | Layout = new LayoutPage(Title); 30 | WriteLiteralLine(PageHtml); 31 | WriteEmptyLine(); 32 | } 33 | 34 | private void WriteLiteralLine(string textToAppend) 35 | { 36 | WriteLiteral(textToAppend); 37 | WriteConfig(); 38 | WriteLiteral("\r\n"); 39 | } 40 | 41 | private void WriteConfig() 42 | { 43 | WriteLiteral($@"
2 | 3 | 4 | 5 | 6 | 7 |
8 |
9 |

CPU

10 | 11 |
12 |
13 |

RAM

14 | 15 |
16 |
17 | 18 |
19 |
20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 |
PIDServerExec nameCPURAMDisk
44 | 45 | 46 | 47 |
56 |
57 |
58 |
59 | -------------------------------------------------------------------------------- /Server/Hangfire.HttpJob/Hangfire.HttpJob.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.0 5 | true 6 | httpjob for Hangfire(基于hangfire的webjob调度服务) 7 | https://github.com/yuzd/Hangfire.HttpJob 8 | 3.8.5 9 | yuzd 10 | 3.8.5.0 11 | 3.8.5.0 12 | true 13 | MIT 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | True 61 | True 62 | Strings.resx 63 | 64 | 65 | True 66 | True 67 | CronJobsPage.cshtml 68 | 69 | 70 | 71 | 72 | 73 | PublicResXFileCodeGenerator 74 | Strings.Designer.cs 75 | 76 | 77 | 78 | 79 | 80 | RazorGenerator 81 | CronJobsPage.generated.cs 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /Server/Hangfire.HttpJob/PageDto.cs: -------------------------------------------------------------------------------- 1 | namespace Hangfire.HttpJob 2 | { 3 | public class PageDto 4 | { 5 | public int PageNo { get; set; } 6 | 7 | public int PageSize { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Server/Hangfire.HttpJob/Server/HangfireHttpClientFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net; 5 | using System.Net.Http; 6 | using HttpClientFactory; 7 | using HttpClientFactory.Impl; 8 | 9 | namespace Hangfire.HttpJob.Server 10 | { 11 | public class HangfireHttpClientFactory:PerHostHttpClientFactory 12 | { 13 | private readonly TimeSpan _timeOut; 14 | private readonly string _contentType; 15 | /// 16 | /// httpjob的请求处理 17 | /// 18 | internal static IHttpClientFactory HttpJobInstance; 19 | /// 20 | /// 钉钉的请求发送 21 | /// 22 | internal static IHttpClientFactory DingTalkInstance; 23 | 24 | /// 25 | /// 设置httpclientFactory来处理HttpClient请求 26 | /// 27 | /// 28 | public static void SetDefaultHttpJobInstance(IHttpClientFactory factory = null) 29 | { 30 | HttpJobInstance = factory ?? new HangfireHttpClientFactory(TimeSpan.FromHours(1),null);//这里设置1小时 是为了取消HttpClient自带的默认超时100s的限制 会在业务逻辑里面设使用实际的Timeout 31 | } 32 | 33 | /// 34 | /// 设置httpclientFactory来处理HttpClient请求 35 | /// 36 | /// 37 | public static void SetDefaultDingTalkInstance(IHttpClientFactory factory = null) 38 | { 39 | DingTalkInstance = factory?? new HangfireHttpClientFactory(TimeSpan.FromSeconds(60), "application/json;charset=UTF-8"); 40 | } 41 | 42 | 43 | public HangfireHttpClientFactory(TimeSpan timeOut,string contentType) 44 | { 45 | _timeOut = timeOut; 46 | _contentType = contentType; 47 | } 48 | 49 | 50 | protected override HttpClient CreateHttpClient(HttpMessageHandler handler) 51 | { 52 | var client = new HttpClient(handler); 53 | client.DefaultRequestHeaders.ConnectionClose = false; 54 | client.DefaultRequestHeaders.Add("UserAgent", "Hangfire.HttpClient"); 55 | client.Timeout = this._timeOut; 56 | 57 | if (!string.IsNullOrEmpty(_contentType)) 58 | { 59 | client.DefaultRequestHeaders.TryAddWithoutValidation("content-type", _contentType); 60 | } 61 | return client; 62 | } 63 | 64 | protected override HttpMessageHandler CreateMessageHandler(string proxyUrl = null) 65 | { 66 | var handler = new HttpClientHandler(); 67 | if (string.IsNullOrEmpty(proxyUrl)) 68 | { 69 | handler.UseProxy = false; 70 | } 71 | else 72 | { 73 | handler.UseProxy = true; 74 | handler.Proxy = new WebProxy(proxyUrl); 75 | } 76 | 77 | handler.AllowAutoRedirect = false; 78 | handler.AutomaticDecompression = DecompressionMethods.None; 79 | handler.UseCookies = false; 80 | return handler; 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Server/Hangfire.HttpJob/Server/Heartbeat/ConfigurationExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Hangfire.Annotations; 3 | using Hangfire.Dashboard; 4 | using Hangfire.Heartbeat.Dashboard; 5 | 6 | namespace Hangfire.Heartbeat 7 | { 8 | public static class ConfigurationExtensions 9 | { 10 | [PublicAPI] 11 | public static IGlobalConfiguration UseHeartbeatPage(this IGlobalConfiguration config, TimeSpan? checkInterval = null) 12 | { 13 | return UseHeartbeatPage(config, new HeartbeatDashboardOptions(checkInterval??TimeSpan.FromSeconds(1))); 14 | } 15 | 16 | 17 | [PublicAPI] 18 | public static IGlobalConfiguration UseHeartbeatPage(this IGlobalConfiguration config, HeartbeatDashboardOptions heartbeatDashboardOptions) 19 | { 20 | DashboardRoutes.Routes.AddRazorPage(OverviewPage.PageRoute, x => new OverviewPage(heartbeatDashboardOptions)); 21 | NavigationMenu.Items.Add(page => new MenuItem(OverviewPage.Title, page.Url.To(OverviewPage.PageRoute)) 22 | { 23 | Active = page.RequestPath.StartsWith(OverviewPage.PageRoute) 24 | }); 25 | DashboardRoutes.Routes.Add(OverviewPage.StatsRoute, new UtilizationJsonDispatcher()); 26 | 27 | DashboardRoutes.Routes.Add( 28 | "/heartbeat/jsknockout", 29 | new ContentDispatcher("application/javascript", "Hangfire.HttpJob.Dashboard.Heartbeat.Dashboard.js.knockout-3.4.2.js", 30 | TimeSpan.FromDays(30))); 31 | 32 | DashboardRoutes.Routes.Add( 33 | "/heartbeat/jsknockoutorderable", 34 | new ContentDispatcher("application/javascript", "Hangfire.HttpJob.Dashboard.Heartbeat.Dashboard.js.knockout.bindings.orderable.js", 35 | TimeSpan.FromDays(30))); 36 | 37 | DashboardRoutes.Routes.Add( 38 | "/heartbeat/jsnumeral", 39 | new ContentDispatcher("application/javascript", "Hangfire.HttpJob.Dashboard.Heartbeat.Dashboard.js.numeral.min.js", TimeSpan.FromDays(30))); 40 | 41 | DashboardRoutes.Routes.Add( 42 | "/heartbeat/jspage", 43 | new ContentDispatcher("application/javascript", "Hangfire.HttpJob.Dashboard.Heartbeat.Dashboard.js.OverviewPage.js", TimeSpan.FromSeconds(1))); 44 | 45 | DashboardRoutes.Routes.Add( 46 | "/heartbeat/cssstyles", 47 | new ContentDispatcher("text/css", "Hangfire.HttpJob.Dashboard.Heartbeat.Dashboard.css.styles.css", TimeSpan.FromSeconds(1))); 48 | 49 | return config; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Server/Hangfire.HttpJob/Server/Heartbeat/HeartbeatDashboardOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Hangfire.Heartbeat 4 | { 5 | /// 6 | /// Contains initialization options for Hangfire Dashboard UI. 7 | /// 8 | public sealed class HeartbeatDashboardOptions 9 | { 10 | /// 11 | /// Status polling interval. 12 | /// 13 | public TimeSpan CheckInterval { get; } 14 | 15 | /// 16 | /// Creates new options. 17 | /// 18 | /// Status polling interval. 19 | public HeartbeatDashboardOptions(TimeSpan checkInterval) 20 | { 21 | if (checkInterval == TimeSpan.Zero) throw new ArgumentException("Check interval must be nonzero value.", nameof(checkInterval)); 22 | if (checkInterval != checkInterval.Duration()) throw new ArgumentException("Check interval must be positive value.", nameof(checkInterval)); 23 | 24 | CheckInterval = checkInterval; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Server/Hangfire.HttpJob/Server/Heartbeat/HeartbeatProcessMonitorOptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Hangfire.Heartbeat 4 | { 5 | /// 6 | /// Contains initialization options for Hangfire Dashboard UI. 7 | /// 8 | public sealed class HeartbeatProcessMonitorOptions 9 | { 10 | /// 11 | /// Status polling interval. 12 | /// 13 | public TimeSpan CheckInterval { get; } 14 | 15 | /// 16 | /// Creates new options. 17 | /// 18 | /// Status polling interval. 19 | public HeartbeatProcessMonitorOptions(TimeSpan checkInterval) 20 | { 21 | if (checkInterval == TimeSpan.Zero) throw new ArgumentException("Check interval must be nonzero value.", nameof(checkInterval)); 22 | if (checkInterval != checkInterval.Duration()) throw new ArgumentException("Check interval must be positive value.", nameof(checkInterval)); 23 | 24 | CheckInterval = checkInterval; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Server/Hangfire.HttpJob/Server/Heartbeat/ProcessInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Hangfire.Heartbeat.Server 4 | { 5 | internal class ProcessInfo 6 | { 7 | public int Id { get; set; } 8 | public string Server { get; set; } 9 | public string ProcessName { get; set; } 10 | public double CpuUsage { get; set; } 11 | public long WorkingSet { get; set; } 12 | public long DiskUsage { get; set; } 13 | public DateTimeOffset Timestamp { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Server/Hangfire.HttpJob/Server/Heartbeat/Utils.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Resources; 3 | 4 | namespace Hangfire.Heartbeat 5 | { 6 | internal static class Utils 7 | { 8 | public static string ReadStringResource(string resourceName) 9 | { 10 | var assembly = typeof(Utils).Assembly; 11 | using (var stream = assembly.GetManifestResourceStream(resourceName)) 12 | { 13 | if (stream == null) throw new MissingManifestResourceException($"Cannot find resource {resourceName}"); 14 | 15 | using (var reader = new StreamReader(stream)) 16 | { 17 | return reader.ReadToEnd(); 18 | } 19 | } 20 | } 21 | 22 | public static string FormatKey(string serverId) => "utilization:" + serverId; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Server/Hangfire.HttpJob/Support/CompositeDispatcher.cs: -------------------------------------------------------------------------------- 1 | using Hangfire.Dashboard; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Threading.Tasks; 5 | 6 | namespace Hangfire.HttpJob.Support 7 | { 8 | /// 9 | /// Dispatcher that combines output from several other dispatchers. 10 | /// Used internally by . 11 | /// 12 | internal class CompositeDispatcher : IDashboardDispatcher 13 | { 14 | private readonly List _dispatchers; 15 | 16 | public CompositeDispatcher(params IDashboardDispatcher[] dispatchers) 17 | { 18 | _dispatchers = new List(dispatchers); 19 | } 20 | 21 | public void AddDispatcher(IDashboardDispatcher dispatcher) 22 | { 23 | if (dispatcher == null) 24 | throw new ArgumentNullException(nameof(dispatcher)); 25 | 26 | _dispatchers.Add(dispatcher); 27 | } 28 | 29 | public async Task Dispatch(DashboardContext context) 30 | { 31 | if (context == null) 32 | throw new ArgumentNullException(nameof(context)); 33 | 34 | if (_dispatchers.Count == 0) 35 | throw new InvalidOperationException("CompositeDispatcher should contain at least one dispatcher"); 36 | 37 | foreach (var dispatcher in _dispatchers) 38 | { 39 | await dispatcher.Dispatch(context); 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Server/Hangfire.HttpJob/Support/EmbeddedResourceDispatcher.cs: -------------------------------------------------------------------------------- 1 | using Hangfire.Dashboard; 2 | using System; 3 | using System.Reflection; 4 | using System.Threading.Tasks; 5 | 6 | namespace Hangfire.HttpJob.Support 7 | { 8 | /// 9 | /// Alternative to built-in EmbeddedResourceDispatcher, which (for some reasons) is not public. 10 | /// 11 | internal class EmbeddedResourceDispatcher : IDashboardDispatcher 12 | { 13 | private readonly Assembly _assembly; 14 | private readonly string _resourceName; 15 | private readonly string _contentType; 16 | 17 | public EmbeddedResourceDispatcher(Assembly assembly, string resourceName, string contentType = null) 18 | { 19 | if (assembly == null) 20 | throw new ArgumentNullException(nameof(assembly)); 21 | if (string.IsNullOrEmpty(resourceName)) 22 | throw new ArgumentNullException(nameof(resourceName)); 23 | 24 | _assembly = assembly; 25 | _resourceName = resourceName; 26 | _contentType = contentType; 27 | } 28 | 29 | public async Task Dispatch(DashboardContext context) 30 | { 31 | if (!string.IsNullOrEmpty(_contentType)) 32 | { 33 | var contentType = context.Response.ContentType; 34 | 35 | if (string.IsNullOrEmpty(contentType)) 36 | { 37 | // content type not yet set 38 | context.Response.ContentType = _contentType; 39 | } 40 | else if (contentType != _contentType) 41 | { 42 | // content type already set, but doesn't match ours 43 | throw new InvalidOperationException($"ContentType '{_contentType}' conflicts with '{context.Response.ContentType}'"); 44 | } 45 | } 46 | 47 | await WriteResourceAsync(context.Response, _assembly, _resourceName); 48 | } 49 | 50 | private static async Task WriteResourceAsync(DashboardResponse response, Assembly assembly, string resourceName) 51 | { 52 | using (var stream = assembly.GetManifestResourceStream(resourceName)) 53 | { 54 | if (stream == null) 55 | throw new ArgumentException($@"Resource '{resourceName}' not found in assembly {assembly}."); 56 | 57 | await stream.CopyToAsync(response.Body); 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Server/Hangfire.HttpJob/Support/ErrorState.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Hangfire.Common; 5 | using Hangfire.States; 6 | using Newtonsoft.Json; 7 | 8 | namespace Hangfire.HttpJob.Support 9 | { 10 | internal class ErrorState:IState 11 | { 12 | public static readonly string StateName = "Failed"; 13 | private readonly string _title; 14 | 15 | public ErrorState(string err,string title = "HttpJob") 16 | { 17 | FailedAt = DateTime.UtcNow; 18 | Reason = err; 19 | _title = string.IsNullOrEmpty(title) ? "HttpJob" : title; 20 | } 21 | 22 | [JsonIgnore] 23 | public DateTime FailedAt { get; set; } 24 | 25 | [JsonIgnore] 26 | public string Name => StateName; 27 | 28 | public Dictionary SerializeData() 29 | { 30 | return new Dictionary 31 | { 32 | { "FailedAt", JobHelper.SerializeDateTime(FailedAt) }, 33 | { "ExceptionType", _title }, 34 | { "ExceptionMessage", Reason }, 35 | { "ExceptionDetails", ""} 36 | }; 37 | } 38 | 39 | public string Reason { get; set; } 40 | 41 | 42 | [JsonIgnore] 43 | public bool IsFinal => false; 44 | [JsonIgnore] 45 | public bool IgnoreJobLoadException => false; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Server/Hangfire.HttpJob/Support/HtmlHelperExtensions.cs: -------------------------------------------------------------------------------- 1 | using Hangfire.Dashboard; 2 | using System; 3 | using System.Reflection; 4 | 5 | namespace Hangfire.HttpJob.Support 6 | { 7 | /// 8 | /// Provides extension methods for . 9 | /// 10 | internal static class HtmlHelperExtensions 11 | { 12 | private static readonly FieldInfo _page = typeof(HtmlHelper).GetTypeInfo().GetDeclaredField(nameof(_page)); 13 | 14 | /// 15 | /// Returs a associated with . 16 | /// 17 | /// Helper 18 | public static RazorPage GetPage(this HtmlHelper helper) 19 | { 20 | if (helper == null) 21 | throw new ArgumentNullException(nameof(helper)); 22 | 23 | return (RazorPage)_page.GetValue(helper); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Server/Hangfire.HttpJob/Support/HttpJobDisplayNameAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | using System.Text; 6 | using Hangfire.Common; 7 | using Hangfire.Dashboard; 8 | using Hangfire.HttpJob.Server; 9 | 10 | namespace Hangfire.HttpJob.Support 11 | { 12 | class HttpJobDisplayNameAttribute: JobDisplayNameAttribute 13 | { 14 | 15 | public override string Format(DashboardContext context, Job job) 16 | { 17 | var data = job.Args.FirstOrDefault() as HttpJobItem; 18 | if (data == null) return job.Method.Name; 19 | try 20 | { 21 | if (string.IsNullOrEmpty(data.RecurringJobIdentifier)) data.RecurringJobIdentifier = data.JobName; 22 | 23 | //增加别名 24 | if (!string.IsNullOrEmpty(data.AgentClass)) 25 | { 26 | return "Agent:"+data.AgentClass+ ",Queue:" + data.QueueName + ",Retry:" + (data.EnableRetry) + "|" + data.AgentClass.Split(',')[0].Split('.').Last()+(!data.RecurringJobIdentifier.Equals(data.JobName)? "|" + data.JobName:"|")+"|"+ data.GetUrlHost(); 27 | } 28 | 29 | var name = (data.Url.Split('/').LastOrDefault() ?? data.JobName); 30 | return data.Url.Replace("|","").Replace("\"","“").Replace("'","’") + ",Queue:" + data.QueueName + ",Retry:" + (data.EnableRetry) + "|" + name + (!data.JobName.Equals(name) ?"|" + data.JobName :"|") + "|"+ data.GetUrlHost(); 31 | } 32 | catch (Exception) 33 | { 34 | return data.JobName; 35 | } 36 | } 37 | 38 | public HttpJobDisplayNameAttribute(string displayName) : base(displayName) 39 | { 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Server/Hangfire.HttpJob/Support/HttpStatusCodeException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Net; 4 | using System.Text; 5 | using Hangfire.HttpJob.Content.resx; 6 | 7 | namespace Hangfire.HttpJob.Support 8 | { 9 | public class HttpStatusCodeException:Exception 10 | { 11 | public string Msg { get; set; } 12 | public bool IsEl { get; set; } 13 | public string El { get; set; } 14 | public HttpStatusCodeException(HttpStatusCode code,string data):base($"{Strings.ResponseCode}:{code} ===> CheckResult: Fail ") 15 | { 16 | Msg = data; 17 | } 18 | 19 | public HttpStatusCodeException(string el, string data) : base($"{Strings.CallbackELExcuteError}:{el} ===> CheckResult: Fail ") 20 | { 21 | IsEl = true; 22 | El = el; 23 | Msg = data; 24 | } 25 | } 26 | 27 | public class CallbackJobException:Exception 28 | { 29 | public CallbackJobException(string code):base($"{Strings.CallbackFail} ===> {code} ") 30 | { 31 | 32 | } 33 | } 34 | 35 | public class AgentJobException : Exception 36 | { 37 | public AgentJobException(string agentClass,string err) : base($"AgentClass:"+ agentClass + "=>" + err) 38 | { 39 | 40 | } 41 | } 42 | 43 | public class HangfireServerShutDownError : Exception 44 | { 45 | public HangfireServerShutDownError():this("hangfire server was shut down!") 46 | { 47 | 48 | } 49 | public HangfireServerShutDownError(string msg):base(msg) 50 | { 51 | 52 | } 53 | } 54 | 55 | public class HangfireAgentShutDownError : Exception 56 | { 57 | public HangfireAgentShutDownError() : this("hangfire agent was shut down!") 58 | { 59 | 60 | } 61 | public HangfireAgentShutDownError(string msg) : base(msg) 62 | { 63 | 64 | } 65 | } 66 | 67 | public class HangfireAgentShutDownCauseJobRequeue : Exception 68 | { 69 | 70 | public HangfireAgentShutDownCauseJobRequeue(string msg) : base("hangfire agent was shut down! the processing job requeue:" + msg) 71 | { 72 | 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Server/Hangfire.HttpJob/Support/QueueProviderFilter.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using Hangfire.Common; 4 | using Hangfire.HttpJob.Server; 5 | 6 | namespace Hangfire.HttpJob.Support 7 | { 8 | /// 9 | /// 自定义queue名称 10 | /// 11 | public class QueueProviderFilter : IJobFilterProvider 12 | { 13 | public IEnumerable GetFilters(Job job) 14 | { 15 | var arg = job.Args.FirstOrDefault() as HttpJobItem; 16 | if (arg == null || string.IsNullOrEmpty(arg.QueueName)) return new Common.JobFilter[] { }; 17 | 18 | 19 | return new[] 20 | { 21 | new Common.JobFilter( 22 | new QueueAttribute(arg.QueueName.ToLower()), 23 | JobFilterScope.Method, null 24 | ) 25 | }; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /Server/Hangfire.HttpJob/Support/UrlUtil.cs: -------------------------------------------------------------------------------- 1 | using Hangfire.Dashboard; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace Hangfire.HttpJob.Support 7 | { 8 | /// 9 | /// Url工具类 10 | /// 11 | public static class UrlUtil 12 | { 13 | /// 14 | /// 获取hangfire服务器url地址(解决hangfire部署后带前缀PrefixPath,后部分url路径问题) 15 | /// 域名无前缀路径:http://domain.com/hangfire 16 | /// 域名无前缀路径:http://domain.com/{PrefixPath}/hangfire 17 | /// 18 | /// 19 | /// 20 | public static string GetCurrentHangfireUrl(this DashboardContext context) 21 | { 22 | var hangfireUrl = context.Request.PathBase; 23 | if (!string.IsNullOrEmpty(context.Options.PrefixPath)) 24 | { 25 | hangfireUrl = context.Options.PrefixPath + context.Request.PathBase; 26 | } 27 | return hangfireUrl; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Test/Hangfire.HttpJob.Client.Test/Hangfire.HttpJob.Client.Test.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /Test/MemoryHangfire/MemoryHangfire/.dockerignore: -------------------------------------------------------------------------------- 1 | **/AntDeploy.json -------------------------------------------------------------------------------- /Test/MemoryHangfire/MemoryHangfire/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 2 | COPY . /publish 3 | WORKDIR /publish 4 | ENV ASPNETCORE_URLS=http://*:5000 5 | EXPOSE 5000 6 | ENTRYPOINT ["dotnet", "MemoryHangfire.dll"] 7 | # server_port@80@ 8 | # volume@/opt/hangfire/logs:/publish/Logs@ -------------------------------------------------------------------------------- /Test/MemoryHangfire/MemoryHangfire/MemoryHangfire.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | 10 | true 11 | PreserveNewest 12 | PreserveNewest 13 | 14 | 15 | true 16 | Always 17 | PreserveNewest 18 | 19 | 20 | true 21 | Always 22 | PreserveNewest 23 | 24 | 25 | 26 | 27 | 28 | Always 29 | 30 | 31 | Always 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /Test/MemoryHangfire/MemoryHangfire/NLog.Config: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 20 | 21 | 22 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /Test/MemoryHangfire/MemoryHangfire/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.Extensions.Hosting; 4 | using Microsoft.Extensions.Logging; 5 | using NLog.Web; 6 | 7 | namespace MemoryHangfire 8 | { 9 | class Program 10 | { 11 | static void Main(string[] args) 12 | { 13 | var logger = NLog.Web.NLogBuilder.ConfigureNLog("NLog.Config").GetCurrentClassLogger(); 14 | try 15 | { 16 | logger.Debug("init main"); 17 | CreateHostBuilder(args).Build().Run(); 18 | } 19 | catch (Exception ex) 20 | { 21 | //NLog: catch setup errors 22 | logger.Error(ex, "Stopped program because of exception"); 23 | throw; 24 | } 25 | finally 26 | { 27 | // Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux) 28 | NLog.LogManager.Shutdown(); 29 | } 30 | } 31 | 32 | public static IHostBuilder CreateHostBuilder(string[] args) => 33 | Host.CreateDefaultBuilder(args) 34 | .ConfigureWebHostDefaults(webBuilder => 35 | { 36 | webBuilder.UseStartup() 37 | .ConfigureLogging(logging => 38 | { 39 | logging.ClearProviders(); 40 | #if DEBUG 41 | logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Debug); 42 | 43 | #else 44 | logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Warning); 45 | #endif 46 | }).UseNLog(); 47 | }); 48 | } 49 | } -------------------------------------------------------------------------------- /Test/MemoryHangfire/MemoryHangfire/Startup.cs: -------------------------------------------------------------------------------- 1 | using Hangfire; 2 | using Hangfire.Console; 3 | using Hangfire.Dashboard.BasicAuthorization; 4 | using Hangfire.HttpJob; 5 | using Microsoft.AspNetCore.Builder; 6 | using Microsoft.AspNetCore.Hosting; 7 | using Microsoft.AspNetCore.Http; 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.DependencyInjection; 10 | using Microsoft.Extensions.Logging; 11 | using NLog.Extensions.Logging; 12 | using System; 13 | using System.Collections.Generic; 14 | using System.Data; 15 | using Hangfire.Heartbeat; 16 | using Hangfire.Heartbeat.Server; 17 | using Hangfire.Tags; 18 | using Microsoft.AspNetCore.Localization; 19 | using Microsoft.Extensions.Hosting; 20 | using Newtonsoft.Json; 21 | using IsolationLevel = System.Transactions.IsolationLevel; 22 | 23 | namespace MemoryHangfire 24 | { 25 | public class Startup 26 | { 27 | public Startup(IConfiguration configuration) 28 | { 29 | JsonConfig = configuration; 30 | } 31 | 32 | public IConfiguration JsonConfig { get; } 33 | 34 | 35 | public void ConfigureServices(IServiceCollection services) 36 | { 37 | services.AddSelfHangfire(JsonConfig); 38 | } 39 | 40 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory logging) 41 | { 42 | app.ConfigureSelfHangfire(JsonConfig); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /Test/MemoryHangfire/MemoryHangfire/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "IncludeScopes": false, 4 | "LogLevel": { 5 | "Default": "Error", 6 | "System": "Error", 7 | "Microsoft": "Error" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Test/MemoryHangfire/MemoryHangfire/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "IncludeScopes": false, 4 | "LogLevel": { 5 | "Default": "Trace", 6 | "Microsoft": "Warning", 7 | "Microsoft.Hosting.Lifetime": "Information" 8 | } 9 | }, 10 | "Hangfire": { 11 | "HangfireSettings": { 12 | "ServerName": "MemoryHangfire", 13 | "TablePrefix": "hangfire", 14 | "StartUpPath": "/job", 15 | "ReadOnlyPath": "", 16 | "JobQueues": [ "default", "apis", "recurring" ], 17 | "WorkerCount": 50, 18 | "DisplayStorageConnectionString": false, 19 | "HttpAuthInfo": { 20 | "SslRedirect": false, 21 | "RequireSsl": false, 22 | "LoginCaseSensitive": true, 23 | "IsOpenLogin": true, 24 | "Users": [ 25 | { 26 | "Login": "admin", 27 | "PasswordClear": "test" 28 | } 29 | ] 30 | } 31 | }, 32 | "HttpJobOptions": { 33 | "Lang": "zh", 34 | "DefaultTimeZone": "", 35 | "CurrentDomain": "//", 36 | "EnableDingTalk": true, 37 | "DefaultRecurringQueueName": "recurring", 38 | "GlobalSettingJsonFilePath": "", 39 | "Proxy": "", 40 | "JobExpirationTimeoutDay": 7, 41 | "GlobalHttpTimeOut": 5000, 42 | "MailOption": { 43 | "Server": "", 44 | "Port": 0, 45 | "User": "", 46 | "Password": "", 47 | "UseSsl": false, 48 | "AlertMailList": [] 49 | }, 50 | "DingTalkOption": { 51 | "Token": "", 52 | "AtPhones": "", 53 | "IsAtAll": false 54 | } 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Test/MemoryHangfire/MemoryHangfire/hangfire/hangfire_global.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /Test/PostgreSqlHangfire/.dockerignore: -------------------------------------------------------------------------------- 1 | **/AntDeploy.json -------------------------------------------------------------------------------- /Test/PostgreSqlHangfire/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 2 | COPY . /publish 3 | WORKDIR /publish 4 | ENV ASPNETCORE_URLS=http://*:5000 5 | EXPOSE 5000 6 | ENTRYPOINT ["dotnet", "PostgreSqlHangfire.dll"] 7 | # server_port@80@ 8 | # volume@/opt/hangfire/logs:/publish/Logs@ -------------------------------------------------------------------------------- /Test/PostgreSqlHangfire/NLog.Config: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 20 | 21 | 22 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /Test/PostgreSqlHangfire/PostgreSqlHangfire.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | Always 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | Always 32 | 33 | 34 | 35 | 36 | 37 | Always 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Test/PostgreSqlHangfire/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Hosting; 2 | using Microsoft.Extensions.Configuration; 3 | using Microsoft.Extensions.Hosting; 4 | using Microsoft.Extensions.Logging; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | using NLog.Web; 10 | 11 | namespace PostgreSqlHangfire 12 | { 13 | public class Program 14 | { 15 | public static void Main(string[] args) 16 | { 17 | var logger = NLog.Web.NLogBuilder.ConfigureNLog("NLog.Config").GetCurrentClassLogger(); 18 | try 19 | { 20 | logger.Debug("init main"); 21 | CreateHostBuilder(args).Build().Run(); 22 | } 23 | catch (Exception ex) 24 | { 25 | //NLog: catch setup errors 26 | logger.Error(ex, "Stopped program because of exception"); 27 | throw; 28 | } 29 | finally 30 | { 31 | // Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux) 32 | NLog.LogManager.Shutdown(); 33 | } 34 | } 35 | 36 | public static IHostBuilder CreateHostBuilder(string[] args) => 37 | Host.CreateDefaultBuilder(args) 38 | .ConfigureWebHostDefaults(webBuilder => 39 | { 40 | webBuilder.UseStartup() 41 | .ConfigureLogging(logging => 42 | { 43 | logging.ClearProviders(); 44 | #if DEBUG 45 | logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Debug); 46 | 47 | #else 48 | logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Warning); 49 | #endif 50 | }).UseNLog(); 51 | }); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Test/PostgreSqlHangfire/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:1945", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "PostgreSqlHangfire": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "applicationUrl": "http://localhost:5000", 22 | "environmentVariables": { 23 | "ASPNETCORE_ENVIRONMENT": "Development" 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Test/PostgreSqlHangfire/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Builder; 2 | using Microsoft.AspNetCore.Hosting; 3 | using Microsoft.AspNetCore.Http; 4 | using Microsoft.Extensions.DependencyInjection; 5 | using Microsoft.Extensions.Hosting; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Threading.Tasks; 10 | using Microsoft.Extensions.Configuration; 11 | using Microsoft.Extensions.Logging; 12 | 13 | namespace PostgreSqlHangfire 14 | { 15 | public class Startup 16 | { 17 | public Startup(IConfiguration configuration) 18 | { 19 | JsonConfig = configuration; 20 | } 21 | 22 | public IConfiguration JsonConfig { get; } 23 | 24 | 25 | public void ConfigureServices(IServiceCollection services) 26 | { 27 | services.AddSelfHangfire(JsonConfig); 28 | } 29 | 30 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory logging) 31 | { 32 | app.ConfigureSelfHangfire(JsonConfig); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Test/PostgreSqlHangfire/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Test/PostgreSqlHangfire/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "IncludeScopes": false, 4 | "LogLevel": { 5 | "Default": "Trace", 6 | "Microsoft": "Warning", 7 | "Microsoft.Hosting.Lifetime": "Information" 8 | } 9 | }, 10 | "Hangfire": { 11 | "HangfireSettings": { 12 | "ServerName": "PostgreSqlHangfire", 13 | "TablePrefix": "", 14 | "StartUpPath": "/job", 15 | "ReadOnlyPath": "", 16 | "JobQueues": [ "default", "apis", "recurring" ], 17 | "WorkerCount": 50, 18 | "DisplayStorageConnectionString": false, 19 | "HttpAuthInfo": { 20 | "SslRedirect": false, 21 | "RequireSsl": false, 22 | "LoginCaseSensitive": true, 23 | "IsOpenLogin": true, 24 | "Users": [ 25 | { 26 | "Login": "admin", 27 | "PasswordClear": "test" 28 | } 29 | ] 30 | }, 31 | "ConnectionString": "Server=localhost;Port=5432;Database=hangfire;User Id=postgres;Password=postgres;" 32 | }, 33 | "HttpJobOptions": { 34 | "Lang": "zh", 35 | "DefaultTimeZone": "", 36 | "CurrentDomain": "//", 37 | "EnableDingTalk": true, 38 | "DefaultRecurringQueueName": "recurring", 39 | "GlobalSettingJsonFilePath": "", 40 | "Proxy": "", 41 | "JobExpirationTimeoutDay": 7, 42 | "GlobalHttpTimeOut": 5000, 43 | "MailOption": { 44 | "Server": "", 45 | "Port": 0, 46 | "User": "", 47 | "Password": "", 48 | "UseSsl": false, 49 | "AlertMailList": [] 50 | }, 51 | "DingTalkOption": { 52 | "Token": "", 53 | "AtPhones": "", 54 | "IsAtAll": false 55 | } 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /Test/PostgreSqlHangfire/hangfire/hangfire_global.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /Test/RedisHangfire/.dockerignore: -------------------------------------------------------------------------------- 1 | **/AntDeploy.json -------------------------------------------------------------------------------- /Test/RedisHangfire/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 2 | COPY . /publish 3 | WORKDIR /publish 4 | ENV ASPNETCORE_URLS=http://*:5000 5 | EXPOSE 5000 6 | ENTRYPOINT ["dotnet", "RedisHangfire.dll"] 7 | # server_port@80@ 8 | # volume@/opt/hangfire/logs:/publish/Logs@ -------------------------------------------------------------------------------- /Test/RedisHangfire/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.Hosting; 10 | using Microsoft.Extensions.Logging; 11 | 12 | namespace RedisHangfire 13 | { 14 | public class Program 15 | { 16 | public static void Main(string[] args) 17 | { 18 | CreateHostBuilder(args).Build().Run(); 19 | } 20 | 21 | public static IHostBuilder CreateHostBuilder(string[] args) => 22 | Host.CreateDefaultBuilder(args) 23 | .ConfigureWebHostDefaults(webBuilder => 24 | { 25 | webBuilder.UseStartup() 26 | .ConfigureLogging(logging => 27 | { 28 | logging.ClearProviders(); 29 | 30 | #if DEBUG 31 | logging.AddConsole(); 32 | logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Debug); 33 | 34 | #else 35 | logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Warning); 36 | #endif 37 | }); 38 | }); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Test/RedisHangfire/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:7911", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "RedisHangfire": { 19 | "commandName": "Project", 20 | "launchBrowser": false, 21 | "applicationUrl": "http://localhost:5000", 22 | "environmentVariables": { 23 | "ASPNETCORE_ENVIRONMENT": "Development" 24 | } 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Test/RedisHangfire/RedisHangfire.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | Always 26 | 27 | 28 | 29 | 30 | 31 | Always 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /Test/RedisHangfire/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Hangfire; 7 | using Hangfire.Console; 8 | using Hangfire.Dashboard.BasicAuthorization; 9 | using Hangfire.Heartbeat; 10 | using Hangfire.Heartbeat.Server; 11 | using Hangfire.HttpJob; 12 | using Hangfire.Redis; 13 | using Microsoft.AspNetCore.Builder; 14 | using Microsoft.AspNetCore.Hosting; 15 | using Microsoft.AspNetCore.Http; 16 | using Microsoft.AspNetCore.Localization; 17 | using Microsoft.Extensions.Configuration; 18 | using Microsoft.Extensions.DependencyInjection; 19 | using Newtonsoft.Json; 20 | using StackExchange.Redis; 21 | 22 | namespace RedisHangfire 23 | { 24 | public class Startup 25 | { 26 | public IConfiguration JsonConfig { get; } 27 | 28 | public Startup(IConfiguration configuration) 29 | { 30 | JsonConfig = configuration; 31 | } 32 | 33 | // This method gets called by the runtime. Use this method to add services to the container. 34 | // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 35 | public void ConfigureServices(IServiceCollection services) 36 | { 37 | services.AddSelfHangfire(JsonConfig); 38 | } 39 | 40 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 41 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 42 | { 43 | app.ConfigureSelfHangfire(JsonConfig); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Test/RedisHangfire/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Test/RedisHangfire/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "IncludeScopes": false, 4 | "LogLevel": { 5 | "Default": "Trace", 6 | "Microsoft": "Warning", 7 | "Microsoft.Hosting.Lifetime": "Information" 8 | } 9 | }, 10 | "Hangfire": { 11 | "HangfireSettings": { 12 | "ServerName": "RedisHangfire", 13 | "TablePrefix": "hangfire:", 14 | "StartUpPath": "/job", 15 | "ReadOnlyPath": "", 16 | "JobQueues": [ "default", "apis", "recurring" ], 17 | "WorkerCount": 50, 18 | "DisplayStorageConnectionString": false, 19 | "HttpAuthInfo": { 20 | "SslRedirect": false, 21 | "RequireSsl": false, 22 | "LoginCaseSensitive": true, 23 | "IsOpenLogin": true, 24 | "Users": [ 25 | { 26 | "Login": "admin", 27 | "PasswordClear": "test" 28 | } 29 | ] 30 | }, 31 | "ConnectionString": "127.0.0.1:6379" 32 | }, 33 | "HttpJobOptions": { 34 | "Lang": "zh", 35 | "DefaultTimeZone": "", 36 | "CurrentDomain": "//", 37 | "EnableDingTalk": true, 38 | "DefaultRecurringQueueName": "recurring", 39 | "GlobalSettingJsonFilePath": "", 40 | "Proxy": "", 41 | "JobExpirationTimeoutDay": 7, 42 | "GlobalHttpTimeOut": 5000, 43 | "MailOption": { 44 | "Server": "", 45 | "Port": 0, 46 | "User": "", 47 | "Password": "", 48 | "UseSsl": false, 49 | "AlertMailList": [] 50 | }, 51 | "DingTalkOption": { 52 | "Token": "", 53 | "AtPhones": "", 54 | "IsAtAll": false 55 | } 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /Test/RedisHangfire/hangfire/hangfire_global.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /Test/TestHangfire/.dockerignore: -------------------------------------------------------------------------------- 1 | **/AntDeploy.json -------------------------------------------------------------------------------- /Test/TestHangfire/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 2 | COPY . /publish 3 | WORKDIR /publish 4 | ENV ASPNETCORE_URLS=http://*:5000 5 | EXPOSE 5000 6 | ENTRYPOINT ["dotnet", "MysqlHangfire.dll"] 7 | # server_port@80@ 8 | # volume@/opt/hangfire/logs:/publish/Logs@ -------------------------------------------------------------------------------- /Test/TestHangfire/MysqlHangfire.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp3.1 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | Always 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | Always 46 | 47 | 48 | 49 | 50 | 51 | Always 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /Test/TestHangfire/NLog.Config: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 20 | 21 | 22 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /Test/TestHangfire/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.Extensions.Hosting; 9 | using Microsoft.Extensions.Logging; 10 | using NLog.Web; 11 | 12 | namespace MysqlHangfire 13 | { 14 | public class Program 15 | { 16 | public static void Main(string[] args) 17 | { 18 | var logger = NLog.Web.NLogBuilder.ConfigureNLog("NLog.Config").GetCurrentClassLogger(); 19 | try 20 | { 21 | logger.Info("Starting jobagent host"); 22 | CreateHostBuilder(args).Build().Run(); 23 | } 24 | catch (Exception ex) 25 | { 26 | //NLog: catch setup errors 27 | logger.Error(ex, "Stopped program because of exception"); 28 | throw; 29 | } 30 | finally 31 | { 32 | // Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux) 33 | NLog.LogManager.Shutdown(); 34 | } 35 | } 36 | 37 | public static IHostBuilder CreateHostBuilder(string[] args) => 38 | Host.CreateDefaultBuilder(args) 39 | .ConfigureWebHostDefaults(webBuilder => 40 | { 41 | webBuilder.UseStartup() 42 | .ConfigureLogging(logging => 43 | { 44 | logging.ClearProviders(); 45 | #if DEBUG 46 | logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Debug); 47 | 48 | #else 49 | logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Warning); 50 | #endif 51 | }).UseNLog(); 52 | }); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Test/TestHangfire/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:12688", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "TestHangfire": { 19 | "commandName": "Project", 20 | "environmentVariables": { 21 | "ASPNETCORE_ENVIRONMENT": "Development" 22 | }, 23 | "nativeDebugging": true, 24 | "applicationUrl": "http://localhost:5000" 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Test/TestHangfire/Startup.cs: -------------------------------------------------------------------------------- 1 | using Hangfire.Console; 2 | using Hangfire.Dashboard.BasicAuthorization; 3 | using Hangfire.HttpJob; 4 | using Microsoft.AspNetCore.Builder; 5 | using Microsoft.AspNetCore.Hosting; 6 | using Microsoft.AspNetCore.Http; 7 | using Microsoft.Extensions.Configuration; 8 | using Microsoft.Extensions.DependencyInjection; 9 | using Microsoft.Extensions.Logging; 10 | using NLog.Extensions.Logging; 11 | using System.Collections.Generic; 12 | using System.Data; 13 | using Hangfire.Heartbeat; 14 | using Hangfire.Heartbeat.Server; 15 | using Hangfire.Tags; 16 | using Microsoft.AspNetCore.Localization; 17 | using Microsoft.Extensions.Hosting; 18 | using Newtonsoft.Json; 19 | using IsolationLevel = System.Transactions.IsolationLevel; 20 | 21 | namespace MysqlHangfire 22 | { 23 | public class Startup 24 | { 25 | public Startup(IConfiguration configuration) 26 | { 27 | JsonConfig = configuration; 28 | } 29 | 30 | public IConfiguration JsonConfig { get; } 31 | 32 | 33 | public void ConfigureServices(IServiceCollection services) 34 | { 35 | services.AddSelfHangfire(JsonConfig); 36 | } 37 | 38 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory logging) 39 | { 40 | app.ConfigureSelfHangfire(JsonConfig); 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /Test/TestHangfire/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "IncludeScopes": false, 4 | "LogLevel": { 5 | "Default": "Error", 6 | "System": "Error", 7 | "Microsoft": "Error" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Test/TestHangfire/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "IncludeScopes": false, 4 | "LogLevel": { 5 | "Default": "Trace", 6 | "Microsoft": "Warning", 7 | "Microsoft.Hosting.Lifetime": "Information" 8 | } 9 | }, 10 | "Hangfire": { 11 | "HangfireSettings": { 12 | "ServerName": "MysqlHangfire", 13 | "TablePrefix": "hangfire", 14 | "StartUpPath": "/job", 15 | "ReadOnlyPath": "", 16 | "JobQueues": [ "default", "apis", "recurring" ], 17 | "WorkerCount": 50, 18 | "DisplayStorageConnectionString": false, 19 | "HttpAuthInfo": { 20 | "SslRedirect": false, 21 | "RequireSsl": false, 22 | "LoginCaseSensitive": true, 23 | "IsOpenLogin": true, 24 | "Users": [ 25 | { 26 | "Login": "admin", 27 | "PasswordClear": "test" 28 | } 29 | ] 30 | }, 31 | "ConnectionString": "Server=localhost;Port=3306;Database=hangfire;Uid=root;Pwd=123456;charset=utf8;SslMode=none;Allow User Variables=True" 32 | }, 33 | "HttpJobOptions": { 34 | "Lang": "zh", 35 | "DefaultTimeZone": "", 36 | "CurrentDomain": "//", 37 | "EnableDingTalk": true, 38 | "DefaultRecurringQueueName": "recurring", 39 | "GlobalSettingJsonFilePath": "", 40 | "Proxy": "", 41 | "JobExpirationTimeoutDay": 7, 42 | "GlobalHttpTimeOut": 5000, 43 | "MailOption": { 44 | "Server": "", 45 | "Port": 0, 46 | "User": "", 47 | "Password": "", 48 | "UseSsl": false, 49 | "AlertMailList": [] 50 | }, 51 | "DingTalkOption": { 52 | "Token": "", 53 | "AtPhones": "", 54 | "IsAtAll": false 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Test/TestHangfire/hangfire/hangfire_global.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /Test/TestHangfireAgent/Jobs/TestHangJob.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Hangfire.HttpJob.Agent; 6 | using Hangfire.HttpJob.Agent.Attribute; 7 | using Microsoft.Extensions.Logging; 8 | 9 | namespace TestHangfireAgent.Jobs 10 | { 11 | [HangJobUntilStop(RegisterName = "HangJob测试")] 12 | public class TestHangJob : JobAgent 13 | { 14 | private readonly ILogger _logger; 15 | 16 | public TestHangJob(ILogger logger) 17 | { 18 | _logger = logger; 19 | _logger.LogInformation($"Create {nameof(TestHangJob)} Instance Success"); 20 | } 21 | public override async Task OnStart(JobContext jobContext) 22 | { 23 | jobContext.Console.Info(nameof(OnStart) + (jobContext.Param ?? string.Empty)); 24 | 25 | while (!jobContext.CancelToken.IsCancellationRequested) 26 | { 27 | jobContext.Console.Info("dddd"); 28 | await Task.Delay(1000 * 10); 29 | } 30 | jobContext.Console.Warning("game over"); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Test/TestHangfireAgent/Jobs/TestJob.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Hangfire.HttpJob.Agent; 6 | using Hangfire.HttpJob.Agent.Attribute; 7 | using Hangfire.HttpJob.Agent.Util; 8 | using Microsoft.Extensions.Logging; 9 | 10 | namespace TestHangfireAgent.Jobs 11 | { 12 | [SingletonJob(RegisterName = "单例job")]//不打这个标签也行 默认就是单例的 13 | public class TestJob : JobAgent 14 | { 15 | public TestJob(ILogger logger) 16 | { 17 | logger.LogInformation($"Create {nameof(TestJob)} Instance Success"); 18 | } 19 | public override async Task OnStart(JobContext jobContext) 20 | { 21 | jobContext.Console.Info("info消息"); 22 | jobContext.Console.Warning("waring消息"); 23 | jobContext.Console.Error("error消息"); 24 | jobContext.Console.Info("开始等待1秒"); 25 | await Task.Delay(1000 * 1); 26 | jobContext.Console.Info("结束等待1秒"); 27 | jobContext.Console.WriteLine("开始测试Progressbar",ConsoleFontColor.Cyan); 28 | 29 | var bar = jobContext.Console.WriteProgressBar("testbar"); 30 | for (int i = 0; i < 10; i++) 31 | { 32 | bar.SetValue(i * 10); 33 | await Task.Delay(1000); 34 | } 35 | } 36 | 37 | 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Test/TestHangfireAgent/Jobs/TestTransientJob.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | using Hangfire.HttpJob.Agent; 7 | using Hangfire.HttpJob.Agent.Attribute; 8 | using Microsoft.Extensions.Logging; 9 | 10 | namespace TestHangfireAgent.Jobs 11 | { 12 | [TransientJob(RegisterName = "多例job")] 13 | public class TestTransientJob:JobAgent 14 | { 15 | private readonly ILogger _logger; 16 | 17 | public TestTransientJob(ILogger logger) 18 | { 19 | _logger = logger; 20 | _logger.LogInformation($"Create {nameof(TestTransientJob)} Instance Success"); 21 | } 22 | public override async Task OnStart(JobContext jobContext) 23 | { 24 | jobContext.Console.Warning("ManagedThreadId:" + Thread.CurrentThread.ManagedThreadId); 25 | _logger.LogWarning("ManagedThreadId:" + Thread.CurrentThread.ManagedThreadId); 26 | await Task.Delay(5000); 27 | _logger.LogWarning(nameof(OnStart) + (jobContext.Param ?? string.Empty)); 28 | jobContext.Console.Warning(nameof(OnStart) + (jobContext.Param ?? string.Empty)); 29 | } 30 | 31 | 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Test/TestHangfireAgent/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.Hosting; 10 | using Microsoft.Extensions.Logging; 11 | 12 | namespace TestHangfireAgent 13 | { 14 | public class Program 15 | { 16 | public static void Main(string[] args) 17 | { 18 | CreateHostBuilder(args).Build().Run(); 19 | } 20 | public static IHostBuilder CreateHostBuilder(string[] args) => 21 | Host.CreateDefaultBuilder(args) 22 | .ConfigureWebHostDefaults(webBuilder => 23 | { 24 | webBuilder.UseStartup() 25 | .ConfigureLogging(logging => 26 | { 27 | logging.ClearProviders(); 28 | #if DEBUG 29 | logging.AddConsole(); 30 | logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Debug); 31 | 32 | #else 33 | logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace); 34 | #endif 35 | }).UseUrls("http://*:5002"); 36 | }); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Test/TestHangfireAgent/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:62813", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "TestHangfireAgent": { 19 | "commandName": "Project", 20 | "environmentVariables": { 21 | "ASPNETCORE_ENVIRONMENT": "Development" 22 | }, 23 | "applicationUrl": "http://localhost:5000" 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /Test/TestHangfireAgent/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Hangfire.HttpJob.Agent; 6 | using Hangfire.HttpJob.Agent.MysqlConsole; 7 | using Microsoft.AspNetCore.Builder; 8 | using Microsoft.AspNetCore.Hosting; 9 | using Microsoft.AspNetCore.Http; 10 | using Microsoft.Extensions.DependencyInjection; 11 | using Microsoft.Extensions.Logging; 12 | 13 | namespace TestHangfireAgent 14 | { 15 | public class Startup 16 | { 17 | // This method gets called by the runtime. Use this method to add services to the container. 18 | // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 19 | public void ConfigureServices(IServiceCollection services) 20 | { 21 | services.AddHangfireJobAgent(); 22 | } 23 | 24 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 25 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory logging) 26 | { 27 | app.UseHangfireJobAgent(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Test/TestHangfireAgent/TestHangfireAgent.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | Always 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Test/TestHangfireAgent/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "IncludeScopes": false, 4 | "LogLevel": { 5 | "Default": "Trace", 6 | "Microsoft": "Warning", 7 | "Microsoft.Hosting.Lifetime": "Information" 8 | } 9 | }, 10 | "JobAgent": { 11 | "Enabled": true, 12 | "SitemapUrl": "/jobagent", 13 | "EnabledBasicAuth": true, 14 | "BasicUserName": "admin", 15 | "BasicUserPwd": "123456", 16 | "EnableAutoRegister": true, 17 | "RegisterAgentHost": "http://localhost:5002", 18 | "RegisterHangfireUrl": "http://localhost:5000/job", 19 | "RegisterHangfireBasicName": "admin", 20 | "RegisterHangfireBasicPwd": "test" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Test/TestHangfirePostgreSqlAgent/Jobs/TestHangJob.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Hangfire.HttpJob.Agent; 6 | using Hangfire.HttpJob.Agent.Attribute; 7 | using Microsoft.Extensions.Logging; 8 | 9 | namespace TestHangfirePostgreSqlAgent.Jobs 10 | { 11 | [HangJobUntilStop(RegisterName = "HangJob测试")] 12 | public class TestHangJob : JobAgent 13 | { 14 | private readonly ILogger _logger; 15 | 16 | public TestHangJob(ILogger logger) 17 | { 18 | _logger = logger; 19 | _logger.LogInformation($"Create {nameof(TestHangJob)} Instance Success"); 20 | } 21 | public override async Task OnStart(JobContext jobContext) 22 | { 23 | jobContext.Console.Info(nameof(OnStart) + (jobContext.Param ?? string.Empty)); 24 | 25 | while (!jobContext.CancelToken.IsCancellationRequested) 26 | { 27 | jobContext.Console.Info("dddd"); 28 | await Task.Delay(1000 * 10); 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Test/TestHangfirePostgreSqlAgent/Jobs/TestJob.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Hangfire.HttpJob.Agent; 6 | using Hangfire.HttpJob.Agent.Attribute; 7 | using Microsoft.Extensions.Logging; 8 | 9 | namespace TestHangfirePostgreSqlAgent.Jobs 10 | { 11 | [SingletonJob(RegisterName = "单例job")]//不打这个标签也行 默认就是单例的 12 | public class TestJob : JobAgent 13 | { 14 | private readonly ILogger _logger; 15 | 16 | public TestJob(ILogger logger) 17 | { 18 | _logger = logger; 19 | _logger.LogInformation($"Create {nameof(TestJob)} Instance Success"); 20 | } 21 | public override async Task OnStart(JobContext jobContext) 22 | { 23 | jobContext.Console.Info("info消息"); 24 | jobContext.Console.Warning("waring消息"); 25 | jobContext.Console.Error("error消息"); 26 | jobContext.Console.Info("开始等待1秒"); 27 | await Task.Delay(1000 * 1); 28 | jobContext.Console.Info("结束等待1秒"); 29 | jobContext.Console.WriteLine("开始测试Progressbar", ConsoleFontColor.Cyan); 30 | 31 | var bar = jobContext.Console.WriteProgressBar("testbar"); 32 | for (int i = 0; i < 10; i++) 33 | { 34 | bar.SetValue(i * 10); 35 | await Task.Delay(1000); 36 | } 37 | } 38 | 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Test/TestHangfirePostgreSqlAgent/Jobs/TestTransientJob.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | using Hangfire.HttpJob.Agent; 7 | using Hangfire.HttpJob.Agent.Attribute; 8 | using Microsoft.Extensions.Logging; 9 | 10 | namespace TestHangfirePostgreSqlAgent.Jobs 11 | { 12 | [TransientJob(RegisterName = "多例job")] 13 | public class TestTransientJob:JobAgent 14 | { 15 | private readonly ILogger _logger; 16 | 17 | public TestTransientJob(ILogger logger) 18 | { 19 | _logger = logger; 20 | _logger.LogInformation($"Create {nameof(TestTransientJob)} Instance Success"); 21 | } 22 | public override async Task OnStart(JobContext jobContext) 23 | { 24 | jobContext.Console.Warning("ManagedThreadId:" + Thread.CurrentThread.ManagedThreadId); 25 | _logger.LogWarning("ManagedThreadId:" + Thread.CurrentThread.ManagedThreadId); 26 | await Task.Delay(5000); 27 | _logger.LogWarning(nameof(OnStart) + (jobContext.Param ?? string.Empty)); 28 | jobContext.Console.Warning(nameof(OnStart) + (jobContext.Param ?? string.Empty)); 29 | } 30 | 31 | 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Test/TestHangfirePostgreSqlAgent/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using Microsoft.AspNetCore.Hosting; 4 | using Microsoft.Extensions.Hosting; 5 | using Microsoft.Extensions.Logging; 6 | 7 | namespace TestHangfirePostgreSqlAgent 8 | { 9 | public class Program 10 | { 11 | public static void Main(string[] args) 12 | { 13 | CreateHostBuilder(args).Build().Run(); 14 | } 15 | public static IHostBuilder CreateHostBuilder(string[] args) => 16 | Host.CreateDefaultBuilder(args) 17 | .ConfigureWebHostDefaults(webBuilder => 18 | { 19 | webBuilder.UseStartup() 20 | .ConfigureLogging(logging => 21 | { 22 | logging.ClearProviders(); 23 | #if DEBUG 24 | logging.AddConsole(); 25 | logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Debug); 26 | 27 | #else 28 | logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace); 29 | #endif 30 | }).UseUrls("http://*:5002"); 31 | }); 32 | 33 | 34 | } 35 | } -------------------------------------------------------------------------------- /Test/TestHangfirePostgreSqlAgent/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:65324/", 7 | "sslPort": 44357 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "TestHangfirePostgreSqlAgent": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "environmentVariables": { 22 | "ASPNETCORE_ENVIRONMENT": "Development" 23 | }, 24 | "applicationUrl": "https://localhost:5001;http://localhost:5000" 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Test/TestHangfirePostgreSqlAgent/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Microsoft.AspNetCore.Builder; 6 | using Microsoft.AspNetCore.Hosting; 7 | using Microsoft.Extensions.DependencyInjection; 8 | using Hangfire.HttpJob.Agent.PostgreSqlConsole; 9 | 10 | namespace TestHangfirePostgreSqlAgent 11 | { 12 | public class Startup 13 | { 14 | 15 | // This method gets called by the runtime. Use this method to add services to the container. 16 | public void ConfigureServices(IServiceCollection services) 17 | { 18 | services.AddHangfireJobAgent(); 19 | } 20 | 21 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 22 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 23 | { 24 | app.UseHangfireJobAgent(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Test/TestHangfirePostgreSqlAgent/TestHangfirePostgreSqlAgent.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Test/TestHangfirePostgreSqlAgent/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "IncludeScopes": false, 4 | "LogLevel": { 5 | "Default": "Trace", 6 | "Microsoft": "Warning", 7 | "Microsoft.Hosting.Lifetime": "Information" 8 | } 9 | }, 10 | "JobAgent": { 11 | "Enabled": true, 12 | "SitemapUrl": "/jobagent", 13 | "EnabledBasicAuth": true, 14 | "BasicUserName": "admin", 15 | "BasicUserPwd": "123456", 16 | "EnableAutoRegister": true, 17 | "RegisterAgentHost": "http://localhost:5002", 18 | "RegisterHangfireUrl": "http://localhost:5000/job", 19 | "RegisterHangfireBasicName": "admin", 20 | "RegisterHangfireBasicPwd": "test" 21 | } 22 | } -------------------------------------------------------------------------------- /Test/TestHangfireRedisAgent/Jobs/TestHangJob.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Hangfire.HttpJob.Agent; 6 | using Hangfire.HttpJob.Agent.Attribute; 7 | using Microsoft.Extensions.Logging; 8 | 9 | namespace TestHangfireRedisAgent.Jobs 10 | { 11 | [HangJobUntilStop(RegisterName = "HangJob测试")] 12 | public class TestHangJob : JobAgent 13 | { 14 | private readonly ILogger _logger; 15 | 16 | public TestHangJob(ILogger logger) 17 | { 18 | _logger = logger; 19 | _logger.LogInformation($"Create {nameof(TestHangJob)} Instance Success"); 20 | } 21 | public override async Task OnStart(JobContext jobContext) 22 | { 23 | jobContext.Console.Info(nameof(OnStart) + (jobContext.Param ?? string.Empty)); 24 | 25 | while (!jobContext.CancelToken.IsCancellationRequested) 26 | { 27 | jobContext.Console.Info("dddd"); 28 | await Task.Delay(1000 * 10); 29 | } 30 | throw new Exception("dddddd"); 31 | jobContext.Console.Warning("game over"); 32 | } 33 | 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Test/TestHangfireRedisAgent/Jobs/TestJob.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Hangfire.HttpJob.Agent; 6 | using Hangfire.HttpJob.Agent.Attribute; 7 | using Microsoft.Extensions.Logging; 8 | 9 | namespace TestHangfireRedisAgent.Jobs 10 | { 11 | [SingletonJob(RegisterName = "单例job")]//不打这个标签也行 默认就是单例的 12 | public class TestJob : JobAgent 13 | { 14 | private readonly ILogger _logger; 15 | 16 | public TestJob(ILogger logger) 17 | { 18 | _logger = logger; 19 | _logger.LogInformation($"Create {nameof(TestJob)} Instance Success"); 20 | } 21 | public override async Task OnStart(JobContext jobContext) 22 | { 23 | jobContext.Console.Info("info消息"); 24 | jobContext.Console.Warning("waring消息"); 25 | jobContext.Console.Error("error消息"); 26 | jobContext.Console.Info("开始等待1秒"); 27 | await Task.Delay(1000 * 1); 28 | jobContext.Console.Info("结束等待1秒"); 29 | jobContext.Console.WriteLine("开始测试Progressbar", ConsoleFontColor.Cyan); 30 | 31 | var bar = jobContext.Console.WriteProgressBar("testbar"); 32 | for (int i = 0; i < 10; i++) 33 | { 34 | bar.SetValue(i * 10); 35 | await Task.Delay(1000); 36 | } 37 | } 38 | 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Test/TestHangfireRedisAgent/Jobs/TestTransientJob.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | using Hangfire.HttpJob.Agent; 7 | using Hangfire.HttpJob.Agent.Attribute; 8 | using Microsoft.Extensions.Logging; 9 | 10 | namespace TestHangfireRedisAgent.Jobs 11 | { 12 | [TransientJob(RegisterName = "多例job")] 13 | public class TestTransientJob:JobAgent 14 | { 15 | private readonly ILogger _logger; 16 | 17 | public TestTransientJob(ILogger logger) 18 | { 19 | _logger = logger; 20 | _logger.LogInformation($"Create {nameof(TestTransientJob)} Instance Success"); 21 | } 22 | public override async Task OnStart(JobContext jobContext) 23 | { 24 | jobContext.Console.Warning("ManagedThreadId:" + Thread.CurrentThread.ManagedThreadId); 25 | _logger.LogWarning("ManagedThreadId:" + Thread.CurrentThread.ManagedThreadId); 26 | await Task.Delay(5000); 27 | _logger.LogWarning(nameof(OnStart) + (jobContext.Param ?? string.Empty)); 28 | jobContext.Console.Warning(nameof(OnStart) + (jobContext.Param ?? string.Empty)); 29 | } 30 | 31 | 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Test/TestHangfireRedisAgent/NLog.Config: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 20 | 21 | 22 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /Test/TestHangfireRedisAgent/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.Hosting; 10 | using Microsoft.Extensions.Logging; 11 | using NLog.Web; 12 | 13 | namespace TestSqlserverHangfireAgent 14 | { 15 | public class Program 16 | { 17 | public static void Main(string[] args) 18 | { 19 | var logger = NLog.Web.NLogBuilder.ConfigureNLog("NLog.Config").GetCurrentClassLogger(); 20 | try 21 | { 22 | logger.Info("Starting jobagent host"); 23 | CreateHostBuilder(args).Build().Run(); 24 | } 25 | catch (Exception ex) 26 | { 27 | //NLog: catch setup errors 28 | logger.Error(ex, "Stopped program because of exception"); 29 | throw; 30 | } 31 | finally 32 | { 33 | // Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux) 34 | NLog.LogManager.Shutdown(); 35 | } 36 | } 37 | 38 | public static IHostBuilder CreateHostBuilder(string[] args) => 39 | Host.CreateDefaultBuilder(args) 40 | .ConfigureWebHostDefaults(webBuilder => 41 | { 42 | webBuilder.UseStartup() 43 | .ConfigureLogging(logging => 44 | { 45 | logging.ClearProviders(); 46 | #if DEBUG 47 | logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Debug); 48 | 49 | #else 50 | logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace); 51 | #endif 52 | }).UseNLog().UseUrls("http://*:5002"); 53 | }); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Test/TestHangfireRedisAgent/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:10276", 7 | "sslPort": 44354 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "TestHangfireRedisAgent": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "applicationUrl": "https://localhost:5001;http://localhost:5000", 22 | "environmentVariables": { 23 | "ASPNETCORE_ENVIRONMENT": "Development" 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Test/TestHangfireRedisAgent/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Hangfire.HttpJob.Agent; 6 | using Hangfire.HttpJob.Agent.RedisConsole; 7 | using Microsoft.AspNetCore.Builder; 8 | using Microsoft.AspNetCore.Hosting; 9 | using Microsoft.AspNetCore.Http; 10 | using Microsoft.Extensions.DependencyInjection; 11 | using Microsoft.Extensions.Logging; 12 | using NLog.Extensions.Logging; 13 | 14 | namespace TestSqlserverHangfireAgent 15 | { 16 | public class Startup 17 | { 18 | // This method gets called by the runtime. Use this method to add services to the container. 19 | // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 20 | public void ConfigureServices(IServiceCollection services) 21 | { 22 | services.AddHangfireJobAgent(); 23 | } 24 | 25 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 26 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory logging) 27 | { 28 | app.UseHangfireJobAgent(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Test/TestHangfireRedisAgent/TestHangfireRedisAgent.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | Always 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /Test/TestHangfireRedisAgent/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Test/TestHangfireRedisAgent/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "IncludeScopes": false, 4 | "LogLevel": { 5 | "Default": "Trace", 6 | "Microsoft": "Warning", 7 | "Microsoft.Hosting.Lifetime": "Information" 8 | } 9 | }, 10 | "JobAgent": { 11 | "Enabled": true, 12 | "SitemapUrl": "/jobagent", 13 | "EnabledBasicAuth": true, 14 | "BasicUserName": "test", 15 | "BasicUserPwd": "123456", 16 | "EnableAutoRegister": true, 17 | "RegisterAgentHost": "http://localhost:5002", 18 | "RegisterHangfireUrl": "http://localhost:5000/job", 19 | "RegisterHangfireBasicName": "admin", 20 | "RegisterHangfireBasicPwd": "test" 21 | } 22 | } -------------------------------------------------------------------------------- /Test/TestOwinHangfireRedisAgent/TestOwinHangfireRedisAgent/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Test/TestOwinHangfireRedisAgent/TestOwinHangfireRedisAgent/Jobs/TestHangJob.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Hangfire.HttpJob.Agent; 6 | using Hangfire.HttpJob.Agent.Attribute; 7 | using Microsoft.Extensions.Logging; 8 | 9 | namespace TestOwinHangfireRedisAgent.Jobs 10 | { 11 | [HangJobUntilStop(true)] 12 | public class TestHangJob : JobAgent 13 | { 14 | private readonly ILogger _logger; 15 | 16 | public TestHangJob(ILogger logger) 17 | { 18 | _logger = logger; 19 | _logger.LogInformation($"Create {nameof(TestHangJob)} Instance Success"); 20 | } 21 | public override async Task OnStart(JobContext jobContext) 22 | { 23 | jobContext.Console.Info(nameof(OnStart) + (jobContext.Param ?? string.Empty)); 24 | 25 | while (!jobContext.CancelToken.IsCancellationRequested) 26 | { 27 | jobContext.Console.Info("dddd"); 28 | await Task.Delay(1000 * 10); 29 | } 30 | throw new Exception("dddddd"); 31 | jobContext.Console.Warning("game over"); 32 | } 33 | 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Test/TestOwinHangfireRedisAgent/TestOwinHangfireRedisAgent/Jobs/TestJob.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Hangfire.HttpJob.Agent; 6 | using Hangfire.HttpJob.Agent.Attribute; 7 | using Microsoft.Extensions.Logging; 8 | 9 | namespace TestOwinHangfireRedisAgent.Jobs 10 | { 11 | public class TestJob : JobAgent 12 | { 13 | private readonly ILogger _logger; 14 | 15 | public TestJob(ILogger logger) 16 | { 17 | _logger = logger; 18 | _logger.LogInformation($"Create {nameof(TestJob)} Instance Success"); 19 | } 20 | public override async Task OnStart(JobContext jobContext) 21 | { 22 | 23 | jobContext.Console.Info("info消息"); 24 | jobContext.Console.Warning("waring消息"); 25 | jobContext.Console.Error("error消息"); 26 | jobContext.Console.Info("开始等待1秒"); 27 | await Task.Delay(1000 * 1); 28 | jobContext.Console.Info("结束等待1秒"); 29 | jobContext.Console.WriteLine("开始测试Progressbar", ConsoleFontColor.Cyan); 30 | 31 | var bar = jobContext.Console.WriteProgressBar("testbar"); 32 | for (int i = 0; i < 10; i++) 33 | { 34 | bar.SetValue(i * 10); 35 | await Task.Delay(1000); 36 | } 37 | } 38 | 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Test/TestOwinHangfireRedisAgent/TestOwinHangfireRedisAgent/Jobs/TestTransientJob.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | using Hangfire.HttpJob.Agent; 7 | using Hangfire.HttpJob.Agent.Attribute; 8 | using Microsoft.Extensions.Logging; 9 | 10 | namespace TestOwinHangfireRedisAgent.Jobs 11 | { 12 | [TransientJob] 13 | public class TestTransientJob:JobAgent 14 | { 15 | private readonly ILogger _logger; 16 | 17 | public TestTransientJob(ILogger logger) 18 | { 19 | _logger = logger; 20 | _logger.LogInformation($"Create {nameof(TestTransientJob)} Instance Success"); 21 | } 22 | public override async Task OnStart(JobContext jobContext) 23 | { 24 | jobContext.Console.Warning("ManagedThreadId:" + Thread.CurrentThread.ManagedThreadId); 25 | _logger.LogWarning("ManagedThreadId:" + Thread.CurrentThread.ManagedThreadId); 26 | await Task.Delay(5000); 27 | _logger.LogWarning(nameof(OnStart) + (jobContext.Param ?? string.Empty)); 28 | jobContext.Console.Warning(nameof(OnStart) + (jobContext.Param ?? string.Empty)); 29 | } 30 | 31 | 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Test/TestOwinHangfireRedisAgent/TestOwinHangfireRedisAgent/NLog.Config: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 15 | 16 | 17 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /Test/TestOwinHangfireRedisAgent/TestOwinHangfireRedisAgent/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Microsoft.Owin; 7 | using Microsoft.Owin.Hosting; 8 | 9 | [assembly: OwinStartup(typeof(TestOwinHangfireRedisAgent.Startup))] 10 | namespace TestOwinHangfireRedisAgent 11 | { 12 | class Program 13 | { 14 | const string url = "http://localhost:5366"; 15 | static void Main(string[] args) 16 | { 17 | using (WebApp.Start(url)) 18 | { 19 | Console.WriteLine("Server started at:" + url); 20 | Console.ReadLine(); 21 | } 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Test/TestOwinHangfireRedisAgent/TestOwinHangfireRedisAgent/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的一般信息由以下 6 | // 控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("TestOwinHangfireRedisAgent")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("TestOwinHangfireRedisAgent")] 13 | [assembly: AssemblyCopyright("Copyright © 2020")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // 将 ComVisible 设置为 false 会使此程序集中的类型 18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 19 | //请将此类型的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("bc8b9574-1c54-46fe-b2f0-c0aee74b5cff")] 24 | 25 | // 程序集的版本信息由下列四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 33 | //通过使用 "*",如下所示: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Test/TestOwinHangfireRedisAgent/TestOwinHangfireRedisAgent/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Hangfire.HttpJob.Agent; 7 | using Hangfire.HttpJob.Agent.RedisConsole; 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.DependencyInjection; 10 | using Microsoft.Extensions.Logging; 11 | using NLog.Extensions.Logging; 12 | using Owin; 13 | 14 | 15 | namespace TestOwinHangfireRedisAgent 16 | { 17 | public class Startup 18 | { 19 | public void Configuration(IAppBuilder app) 20 | { 21 | NLog.LogManager.LoadConfiguration("NLog.Config"); 22 | 23 | var builder = new ConfigurationBuilder(); 24 | var localtion = Path.GetDirectoryName(typeof(Startup).Assembly.Location); 25 | var appsettingPath = Path.Combine(localtion, "appsettings.json"); 26 | builder.AddJsonFile(appsettingPath); 27 | var configRoot = builder.Build(); 28 | 29 | 30 | var services = new ServiceCollection() 31 | .AddLogging(loggingBuilder => 32 | { 33 | // configure Logging with NLog 34 | loggingBuilder.ClearProviders(); 35 | loggingBuilder.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace); 36 | loggingBuilder.AddNLog(configRoot); 37 | }); 38 | 39 | 40 | services.AddSingleton(configRoot); 41 | services.AddHangfireJobAgent(); 42 | app.UseHangfireJobAgent(services); 43 | Console.WriteLine("owin job agent ...."); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Test/TestOwinHangfireRedisAgent/TestOwinHangfireRedisAgent/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Test/TestOwinHangfireRedisAgent/TestOwinHangfireRedisAgent/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "IncludeScopes": false, 4 | "LogLevel": { 5 | "Default": "Trace", 6 | "Microsoft": "Warning", 7 | "Microsoft.Hosting.Lifetime": "Information" 8 | } 9 | }, 10 | "JobAgent": { 11 | "Enabled": true, 12 | "SitemapUrl": "/jobagent", 13 | "EnabledBasicAuth": true, 14 | "BasicUserName": "test", 15 | "BasicUserPwd": "123456" 16 | } 17 | } -------------------------------------------------------------------------------- /Test/TestSqlserver/.dockerignore: -------------------------------------------------------------------------------- 1 | **/AntDeploy.json -------------------------------------------------------------------------------- /Test/TestSqlserver/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 2 | COPY . /publish 3 | WORKDIR /publish 4 | ENV ASPNETCORE_URLS=http://*:5000 5 | EXPOSE 5000 6 | ENTRYPOINT ["dotnet", "SqlserverHangfire.dll"] 7 | # server_port@80@ 8 | # volume@/opt/hangfire/logs:/publish/Logs@ -------------------------------------------------------------------------------- /Test/TestSqlserver/NLog.Config: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 20 | 21 | 22 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /Test/TestSqlserver/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.Hosting; 10 | using Microsoft.Extensions.Logging; 11 | using NLog.Web; 12 | 13 | namespace SqlserverHangfire 14 | { 15 | public class Program 16 | { 17 | public static void Main(string[] args) 18 | { 19 | var logger = NLog.Web.NLogBuilder.ConfigureNLog("NLog.Config").GetCurrentClassLogger(); 20 | try 21 | { 22 | logger.Debug("init main"); 23 | CreateHostBuilder(args).Build().Run(); 24 | } 25 | catch (Exception ex) 26 | { 27 | //NLog: catch setup errors 28 | logger.Error(ex, "Stopped program because of exception"); 29 | throw; 30 | } 31 | finally 32 | { 33 | // Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux) 34 | NLog.LogManager.Shutdown(); 35 | } 36 | } 37 | 38 | public static IHostBuilder CreateHostBuilder(string[] args) => 39 | Host.CreateDefaultBuilder(args) 40 | .ConfigureWebHostDefaults(webBuilder => 41 | { 42 | webBuilder.UseStartup() 43 | .ConfigureLogging(logging => 44 | { 45 | logging.ClearProviders(); 46 | #if DEBUG 47 | logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Debug); 48 | 49 | #else 50 | logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Warning); 51 | #endif 52 | }).UseNLog(); 53 | }); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Test/TestSqlserver/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true 5 | }, 6 | "profiles": { 7 | "TestSqlserver": { 8 | "commandName": "Project", 9 | "launchBrowser": false, 10 | "applicationUrl": "http://localhost:5000", 11 | "environmentVariables": { 12 | "ASPNETCORE_ENVIRONMENT": "Development" 13 | } 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /Test/TestSqlserver/SqlserverHangfire.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | InProcess 6 | SqlserverHangfire 7 | SqlserverHangfire 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | Always 25 | 26 | 27 | Always 28 | 29 | 30 | 31 | 32 | 33 | Always 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /Test/TestSqlserver/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Hangfire; 6 | using Hangfire.Console; 7 | using Hangfire.Dashboard.BasicAuthorization; 8 | using Hangfire.Heartbeat; 9 | using Hangfire.Heartbeat.Server; 10 | using Hangfire.HttpJob; 11 | using Hangfire.SqlServer; 12 | using Hangfire.Tags; 13 | using Hangfire.Tags.SqlServer; 14 | using Microsoft.AspNetCore.Builder; 15 | using Microsoft.AspNetCore.Hosting; 16 | using Microsoft.AspNetCore.Http; 17 | using Microsoft.AspNetCore.Localization; 18 | using Microsoft.Extensions.Configuration; 19 | using Microsoft.Extensions.DependencyInjection; 20 | using Microsoft.Extensions.Logging; 21 | using NLog.Extensions.Logging; 22 | 23 | namespace SqlserverHangfire 24 | { 25 | public class Startup 26 | { 27 | public Startup(IConfiguration configuration) 28 | { 29 | JsonConfig = configuration; 30 | } 31 | 32 | public IConfiguration JsonConfig { get; } 33 | // This method gets called by the runtime. Use this method to add services to the container. 34 | // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 35 | public void ConfigureServices(IServiceCollection services) 36 | { 37 | services.AddSelfHangfire(JsonConfig); 38 | } 39 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 40 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory logging) 41 | { 42 | app.ConfigureSelfHangfire(JsonConfig); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Test/TestSqlserver/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Debug", 5 | "System": "Information", 6 | "Microsoft": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Test/TestSqlserver/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "IncludeScopes": false, 4 | "LogLevel": { 5 | "Default": "Trace", 6 | "Microsoft": "Warning", 7 | "Microsoft.Hosting.Lifetime": "Information" 8 | } 9 | }, 10 | "Hangfire": { 11 | "HangfireSettings": { 12 | "ServerName": "SqlserverHangfire", 13 | "StartUpPath": "/job", 14 | "ReadOnlyPath": "", 15 | "JobQueues": [ "default", "apis", "recurring" ], 16 | "WorkerCount": 50, 17 | "DisplayStorageConnectionString": false, 18 | "HttpAuthInfo": { 19 | "SslRedirect": false, 20 | "RequireSsl": false, 21 | "LoginCaseSensitive": true, 22 | "IsOpenLogin": true, 23 | "Users": [ 24 | { 25 | "Login": "admin", 26 | "PasswordClear": "test" 27 | } 28 | ] 29 | }, 30 | "ConnectionString": "Server=.\\;Database=hangfire;Trusted_Connection=True;Enlist=False;" 31 | }, 32 | "HttpJobOptions": { 33 | "Lang": "zh", 34 | "DefaultTimeZone": "", 35 | "CurrentDomain": "//", 36 | "EnableDingTalk": true, 37 | "DefaultRecurringQueueName": "recurring", 38 | "GlobalSettingJsonFilePath": "", 39 | "Proxy": "", 40 | "JobExpirationTimeoutDay": 7, 41 | "GlobalHttpTimeOut": 5000, 42 | "MailOption": { 43 | "Server": "", 44 | "Port": 0, 45 | "User": "", 46 | "Password": "", 47 | "UseSsl": false, 48 | "AlertMailList": [] 49 | }, 50 | "DingTalkOption": { 51 | "Token": "", 52 | "AtPhones": "", 53 | "IsAtAll": false 54 | } 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /Test/TestSqlserver/hangfire/hangfire_global.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /Test/TestSqlserverHangfireAgent/Jobs/TestHangJob.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Hangfire.HttpJob.Agent; 6 | using Hangfire.HttpJob.Agent.Attribute; 7 | using Microsoft.Extensions.Logging; 8 | 9 | namespace TestSqlserverHangfireAgent.Jobs 10 | { 11 | [HangJobUntilStop(RegisterName = "HangJob测试")] 12 | public class TestHangJob : JobAgent 13 | { 14 | private readonly ILogger _logger; 15 | 16 | public TestHangJob(ILogger logger) 17 | { 18 | _logger = logger; 19 | _logger.LogInformation($"Create {nameof(TestHangJob)} Instance Success"); 20 | } 21 | public override async Task OnStart(JobContext jobContext) 22 | { 23 | jobContext.Console.Info(nameof(OnStart) + (jobContext.Param ?? string.Empty)); 24 | 25 | while (!jobContext.CancelToken.IsCancellationRequested) 26 | { 27 | jobContext.Console.Info("dddd"); 28 | await Task.Delay(1000 * 10); 29 | } 30 | jobContext.Console.Warning("game over"); 31 | } 32 | 33 | 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Test/TestSqlserverHangfireAgent/Jobs/TestJob.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Hangfire.HttpJob.Agent; 6 | using Hangfire.HttpJob.Agent.Attribute; 7 | using Microsoft.Extensions.Logging; 8 | 9 | namespace TestSqlserverHangfireAgent.Jobs 10 | { 11 | [SingletonJob(RegisterName = "单例job")]//不打这个标签也行 默认就是单例的 12 | public class TestJob : JobAgent 13 | { 14 | private readonly ILogger _logger; 15 | 16 | public TestJob(ILogger logger) 17 | { 18 | _logger = logger; 19 | _logger.LogInformation($"Create {nameof(TestJob)} Instance Success"); 20 | } 21 | public override async Task OnStart(JobContext jobContext) 22 | { 23 | jobContext.Console.Info("info消息"); 24 | jobContext.Console.Warning("waring消息"); 25 | jobContext.Console.Error("error消息"); 26 | jobContext.Console.Info("开始等待1秒"); 27 | await Task.Delay(1000 * 1); 28 | jobContext.Console.Info("结束等待1秒"); 29 | jobContext.Console.WriteLine("开始测试Progressbar", ConsoleFontColor.Cyan); 30 | 31 | var bar = jobContext.Console.WriteProgressBar("testbar"); 32 | for (int i = 0; i < 10; i++) 33 | { 34 | bar.SetValue(i * 10); 35 | await Task.Delay(1000); 36 | } 37 | } 38 | 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Test/TestSqlserverHangfireAgent/Jobs/TestTransientJob.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading; 5 | using System.Threading.Tasks; 6 | using Hangfire.HttpJob.Agent; 7 | using Hangfire.HttpJob.Agent.Attribute; 8 | using Microsoft.Extensions.Logging; 9 | 10 | namespace TestSqlserverHangfireAgent.Jobs 11 | { 12 | [TransientJob(RegisterName = "多例job")] 13 | public class TestTransientJob:JobAgent 14 | { 15 | private readonly ILogger _logger; 16 | 17 | public TestTransientJob(ILogger logger) 18 | { 19 | _logger = logger; 20 | _logger.LogInformation($"Create {nameof(TestTransientJob)} Instance Success"); 21 | } 22 | public override async Task OnStart(JobContext jobContext) 23 | { 24 | jobContext.Console.Warning("ManagedThreadId:" + Thread.CurrentThread.ManagedThreadId); 25 | _logger.LogWarning("ManagedThreadId:" + Thread.CurrentThread.ManagedThreadId); 26 | await Task.Delay(5000); 27 | _logger.LogWarning(nameof(OnStart) + (jobContext.Param ?? string.Empty)); 28 | jobContext.Console.Warning(nameof(OnStart) + (jobContext.Param ?? string.Empty)); 29 | } 30 | 31 | 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Test/TestSqlserverHangfireAgent/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore; 7 | using Microsoft.AspNetCore.Hosting; 8 | using Microsoft.Extensions.Configuration; 9 | using Microsoft.Extensions.Hosting; 10 | using Microsoft.Extensions.Logging; 11 | 12 | namespace TestSqlserverHangfireAgent 13 | { 14 | public class Program 15 | { 16 | public static void Main(string[] args) 17 | { 18 | CreateHostBuilder(args).Build().Run(); 19 | } 20 | 21 | public static IHostBuilder CreateHostBuilder(string[] args) => 22 | Host.CreateDefaultBuilder(args) 23 | .ConfigureWebHostDefaults(webBuilder => 24 | { 25 | webBuilder.UseStartup() 26 | .ConfigureLogging(logging => 27 | { 28 | logging.ClearProviders(); 29 | #if DEBUG 30 | logging.AddConsole(); 31 | logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Debug); 32 | 33 | #else 34 | logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace); 35 | #endif 36 | }).UseUrls("http://*:5002"); 37 | }); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Test/TestSqlserverHangfireAgent/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:62813", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "TestHangfireAgent": { 19 | "commandName": "Project", 20 | "environmentVariables": { 21 | "ASPNETCORE_ENVIRONMENT": "Development" 22 | }, 23 | "applicationUrl": "http://localhost:5000" 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /Test/TestSqlserverHangfireAgent/Startup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Hangfire.HttpJob.Agent; 6 | using Hangfire.HttpJob.Agent.MssqlConsole; 7 | using Microsoft.AspNetCore.Builder; 8 | using Microsoft.AspNetCore.Hosting; 9 | using Microsoft.AspNetCore.Http; 10 | using Microsoft.Extensions.DependencyInjection; 11 | using Microsoft.Extensions.Logging; 12 | 13 | namespace TestSqlserverHangfireAgent 14 | { 15 | public class Startup 16 | { 17 | // This method gets called by the runtime. Use this method to add services to the container. 18 | // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 19 | public void ConfigureServices(IServiceCollection services) 20 | { 21 | services.AddHangfireJobAgent(); 22 | } 23 | 24 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 25 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory logging) 26 | { 27 | app.UseHangfireJobAgent(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Test/TestSqlserverHangfireAgent/TestSqlserverHangfireAgent.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | Always 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /Test/TestSqlserverHangfireAgent/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "IncludeScopes": false, 4 | "LogLevel": { 5 | "Default": "Trace", 6 | "Microsoft": "Warning", 7 | "Microsoft.Hosting.Lifetime": "Information" 8 | } 9 | }, 10 | "JobAgent": { 11 | "Enabled": true, 12 | "SitemapUrl": "/jobagent", 13 | "EnabledBasicAuth": true, 14 | "BasicUserName": "test", 15 | "BasicUserPwd": "123456", 16 | "EnableAutoRegister": true, 17 | "RegisterAgentHost": "http://localhost:5002", 18 | "RegisterHangfireUrl": "http://localhost:5000/job", 19 | "RegisterHangfireBasicName": "admin", 20 | "RegisterHangfireBasicPwd": "test" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /pic1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuzd/Hangfire.HttpJob/34c2888858a3ec239d46726081e8ef936ea11e86/pic1.png -------------------------------------------------------------------------------- /pic2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuzd/Hangfire.HttpJob/34c2888858a3ec239d46726081e8ef936ea11e86/pic2.png -------------------------------------------------------------------------------- /pic3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuzd/Hangfire.HttpJob/34c2888858a3ec239d46726081e8ef936ea11e86/pic3.png -------------------------------------------------------------------------------- /pic4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yuzd/Hangfire.HttpJob/34c2888858a3ec239d46726081e8ef936ea11e86/pic4.png --------------------------------------------------------------------------------