diff --git a/DotXxlJob.sln b/DotXxlJob.sln
index ac19b8f..dee34fe 100644
--- a/DotXxlJob.sln
+++ b/DotXxlJob.sln
@@ -13,6 +13,14 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{352EC932
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hessian.NET.Tests", "tests\Hessian.NET.Tests\Hessian.NET.Tests.csproj", "{187B28C7-C3D7-4E0A-A84B-98B7C1C758F9}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{E959F9B5-F3EB-48B1-B842-2CDDFDB01900}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ASPNetCoreExecutor", "samples\ASPNetCoreExecutor\ASPNetCoreExecutor.csproj", "{DC9E5AF3-18FF-4713-BDB4-672E47ADA4E5}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HessianReader", "samples\HessianReader\HessianReader.csproj", "{F822B528-95FD-40B4-9EE0-3AE8878075AC}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hessian", "src\Hessian\Hessian.csproj", "{BD9B8108-6528-430F-AD28-6F8434A29F55}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -29,6 +37,9 @@ Global
{FFFEEA78-CB09-4BFB-89B7-E9A46EC3ED65} = {97756BA5-1E7C-4536-A49E-AE2190C0E6A5}
{86456232-19D5-48DD-AC39-A0526517E0AD} = {97756BA5-1E7C-4536-A49E-AE2190C0E6A5}
{187B28C7-C3D7-4E0A-A84B-98B7C1C758F9} = {352EC932-F112-4A2F-9DC3-F0761C85E068}
+ {DC9E5AF3-18FF-4713-BDB4-672E47ADA4E5} = {E959F9B5-F3EB-48B1-B842-2CDDFDB01900}
+ {F822B528-95FD-40B4-9EE0-3AE8878075AC} = {E959F9B5-F3EB-48B1-B842-2CDDFDB01900}
+ {BD9B8108-6528-430F-AD28-6F8434A29F55} = {97756BA5-1E7C-4536-A49E-AE2190C0E6A5}
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{FFFEEA78-CB09-4BFB-89B7-E9A46EC3ED65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
@@ -67,5 +78,41 @@ Global
{187B28C7-C3D7-4E0A-A84B-98B7C1C758F9}.Release|x64.Build.0 = Release|Any CPU
{187B28C7-C3D7-4E0A-A84B-98B7C1C758F9}.Release|x86.ActiveCfg = Release|Any CPU
{187B28C7-C3D7-4E0A-A84B-98B7C1C758F9}.Release|x86.Build.0 = Release|Any CPU
+ {DC9E5AF3-18FF-4713-BDB4-672E47ADA4E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {DC9E5AF3-18FF-4713-BDB4-672E47ADA4E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {DC9E5AF3-18FF-4713-BDB4-672E47ADA4E5}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {DC9E5AF3-18FF-4713-BDB4-672E47ADA4E5}.Debug|x64.Build.0 = Debug|Any CPU
+ {DC9E5AF3-18FF-4713-BDB4-672E47ADA4E5}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {DC9E5AF3-18FF-4713-BDB4-672E47ADA4E5}.Debug|x86.Build.0 = Debug|Any CPU
+ {DC9E5AF3-18FF-4713-BDB4-672E47ADA4E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {DC9E5AF3-18FF-4713-BDB4-672E47ADA4E5}.Release|Any CPU.Build.0 = Release|Any CPU
+ {DC9E5AF3-18FF-4713-BDB4-672E47ADA4E5}.Release|x64.ActiveCfg = Release|Any CPU
+ {DC9E5AF3-18FF-4713-BDB4-672E47ADA4E5}.Release|x64.Build.0 = Release|Any CPU
+ {DC9E5AF3-18FF-4713-BDB4-672E47ADA4E5}.Release|x86.ActiveCfg = Release|Any CPU
+ {DC9E5AF3-18FF-4713-BDB4-672E47ADA4E5}.Release|x86.Build.0 = Release|Any CPU
+ {F822B528-95FD-40B4-9EE0-3AE8878075AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F822B528-95FD-40B4-9EE0-3AE8878075AC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F822B528-95FD-40B4-9EE0-3AE8878075AC}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {F822B528-95FD-40B4-9EE0-3AE8878075AC}.Debug|x64.Build.0 = Debug|Any CPU
+ {F822B528-95FD-40B4-9EE0-3AE8878075AC}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {F822B528-95FD-40B4-9EE0-3AE8878075AC}.Debug|x86.Build.0 = Debug|Any CPU
+ {F822B528-95FD-40B4-9EE0-3AE8878075AC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F822B528-95FD-40B4-9EE0-3AE8878075AC}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F822B528-95FD-40B4-9EE0-3AE8878075AC}.Release|x64.ActiveCfg = Release|Any CPU
+ {F822B528-95FD-40B4-9EE0-3AE8878075AC}.Release|x64.Build.0 = Release|Any CPU
+ {F822B528-95FD-40B4-9EE0-3AE8878075AC}.Release|x86.ActiveCfg = Release|Any CPU
+ {F822B528-95FD-40B4-9EE0-3AE8878075AC}.Release|x86.Build.0 = Release|Any CPU
+ {BD9B8108-6528-430F-AD28-6F8434A29F55}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BD9B8108-6528-430F-AD28-6F8434A29F55}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BD9B8108-6528-430F-AD28-6F8434A29F55}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {BD9B8108-6528-430F-AD28-6F8434A29F55}.Debug|x64.Build.0 = Debug|Any CPU
+ {BD9B8108-6528-430F-AD28-6F8434A29F55}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {BD9B8108-6528-430F-AD28-6F8434A29F55}.Debug|x86.Build.0 = Debug|Any CPU
+ {BD9B8108-6528-430F-AD28-6F8434A29F55}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BD9B8108-6528-430F-AD28-6F8434A29F55}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BD9B8108-6528-430F-AD28-6F8434A29F55}.Release|x64.ActiveCfg = Release|Any CPU
+ {BD9B8108-6528-430F-AD28-6F8434A29F55}.Release|x64.Build.0 = Release|Any CPU
+ {BD9B8108-6528-430F-AD28-6F8434A29F55}.Release|x86.ActiveCfg = Release|Any CPU
+ {BD9B8108-6528-430F-AD28-6F8434A29F55}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
diff --git a/samples/ASPNetCoreExecutor/1547620263.dat b/samples/ASPNetCoreExecutor/1547620263.dat
new file mode 100644
index 0000000..3f69aab
Binary files /dev/null and b/samples/ASPNetCoreExecutor/1547620263.dat differ
diff --git a/samples/ASPNetCoreExecutor/1547621183.dat b/samples/ASPNetCoreExecutor/1547621183.dat
new file mode 100644
index 0000000..d8c48ad
Binary files /dev/null and b/samples/ASPNetCoreExecutor/1547621183.dat differ
diff --git a/samples/ASPNetCoreExecutor/ASPNetCoreExecutor.csproj b/samples/ASPNetCoreExecutor/ASPNetCoreExecutor.csproj
new file mode 100644
index 0000000..181e783
--- /dev/null
+++ b/samples/ASPNetCoreExecutor/ASPNetCoreExecutor.csproj
@@ -0,0 +1,16 @@
+
+
+
+ netcoreapp2.2
+ InProcess
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/ASPNetCoreExecutor/ApplicationBuilderExtensions.cs b/samples/ASPNetCoreExecutor/ApplicationBuilderExtensions.cs
new file mode 100644
index 0000000..5c2bbcf
--- /dev/null
+++ b/samples/ASPNetCoreExecutor/ApplicationBuilderExtensions.cs
@@ -0,0 +1,12 @@
+using Microsoft.AspNetCore.Builder;
+
+namespace ASPNetCoreExecutor
+{
+ public static class ApplicationBuilderExtensions
+ {
+ public static IApplicationBuilder UseXxlJobExecutor(this IApplicationBuilder @this)
+ {
+ return @this.UseMiddleware();
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/ASPNetCoreExecutor/Program.cs b/samples/ASPNetCoreExecutor/Program.cs
new file mode 100644
index 0000000..f446a2f
--- /dev/null
+++ b/samples/ASPNetCoreExecutor/Program.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Logging;
+
+namespace ASPNetCoreExecutor
+{
+ public class Program
+ {
+ public static void Main(string[] args)
+ {
+ CreateWebHostBuilder(args).Build().Run();
+ }
+
+ public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
+ WebHost.CreateDefaultBuilder(args)
+ .UseStartup();
+ }
+}
\ No newline at end of file
diff --git a/samples/ASPNetCoreExecutor/Properties/launchSettings.json b/samples/ASPNetCoreExecutor/Properties/launchSettings.json
new file mode 100644
index 0000000..663adfb
--- /dev/null
+++ b/samples/ASPNetCoreExecutor/Properties/launchSettings.json
@@ -0,0 +1,27 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "http://localhost:22613",
+ "sslPort": 44333
+ }
+ },
+ "profiles": {
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "ASPNetCoreExecutor": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "https://localhost:5001;http://localhost:5000",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/ASPNetCoreExecutor/Startup.cs b/samples/ASPNetCoreExecutor/Startup.cs
new file mode 100644
index 0000000..dd413a2
--- /dev/null
+++ b/samples/ASPNetCoreExecutor/Startup.cs
@@ -0,0 +1,29 @@
+using DotXxlJob.Core;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace ASPNetCoreExecutor
+{
+ public class Startup
+ {
+ // This method gets called by the runtime. Use this method to add services to the container.
+ // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddXxlJobExecutor();
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+ public void Configure(IApplicationBuilder app, IHostingEnvironment env)
+ {
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+
+ //启用XxlExecutor
+ app.UseXxlJobExecutor();
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/ASPNetCoreExecutor/XxlJobExecutorMiddleware.cs b/samples/ASPNetCoreExecutor/XxlJobExecutorMiddleware.cs
new file mode 100644
index 0000000..882891f
--- /dev/null
+++ b/samples/ASPNetCoreExecutor/XxlJobExecutorMiddleware.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Net;
+using System.Threading.Tasks;
+using DotXxlJob.Core;
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace ASPNetCoreExecutor
+{
+ public class XxlJobExecutorMiddleware
+ {
+ private readonly IServiceProvider _provider;
+ private readonly RequestDelegate _next;
+
+ private readonly XxlRpcServiceHandler _rpcService;
+ public XxlJobExecutorMiddleware(IServiceProvider provider, RequestDelegate next)
+ {
+ _provider = provider;
+ _next = next;
+
+ _rpcService = _provider.GetRequiredService();
+ }
+
+
+ public async Task Invoke(HttpContext context)
+ {
+
+ if ("POST".Equals(context.Request.Method, StringComparison.OrdinalIgnoreCase) &&
+ "application/octet-stream".Equals(context.Request.ContentType, StringComparison.OrdinalIgnoreCase))
+ {
+ var rsp = await _rpcService.HandlerAsync(context.Request.Body);
+
+ context.Response.StatusCode = (int) HttpStatusCode.OK;
+ context.Response.ContentType = "text/plain;utf-8";
+ await context.Response.Body.WriteAsync(rsp,0,rsp.Length);
+ }
+
+ await _next.Invoke(context);
+ }
+ }
+}
\ No newline at end of file
diff --git a/samples/ASPNetCoreExecutor/appsettings.Development.json b/samples/ASPNetCoreExecutor/appsettings.Development.json
new file mode 100644
index 0000000..e203e94
--- /dev/null
+++ b/samples/ASPNetCoreExecutor/appsettings.Development.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Debug",
+ "System": "Information",
+ "Microsoft": "Information"
+ }
+ }
+}
diff --git a/samples/ASPNetCoreExecutor/appsettings.json b/samples/ASPNetCoreExecutor/appsettings.json
new file mode 100644
index 0000000..def9159
--- /dev/null
+++ b/samples/ASPNetCoreExecutor/appsettings.json
@@ -0,0 +1,8 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Warning"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/samples/HessianReader/1547620263.dat b/samples/HessianReader/1547620263.dat
new file mode 100644
index 0000000..3f69aab
Binary files /dev/null and b/samples/HessianReader/1547620263.dat differ
diff --git a/samples/HessianReader/1547621183.dat b/samples/HessianReader/1547621183.dat
new file mode 100644
index 0000000..d8c48ad
Binary files /dev/null and b/samples/HessianReader/1547621183.dat differ
diff --git a/samples/HessianReader/HessianReader.csproj b/samples/HessianReader/HessianReader.csproj
new file mode 100644
index 0000000..1178b9f
--- /dev/null
+++ b/samples/HessianReader/HessianReader.csproj
@@ -0,0 +1,19 @@
+
+
+
+ Exe
+ netcoreapp2.2
+
+
+
+
+
+
+
+
+
+ C:\Program Files\dotnet\sdk\NuGetFallbackFolder\newtonsoft.json\11.0.2\lib\netstandard2.0\Newtonsoft.Json.dll
+
+
+
+
diff --git a/samples/HessianReader/Program.cs b/samples/HessianReader/Program.cs
new file mode 100644
index 0000000..f7518e6
--- /dev/null
+++ b/samples/HessianReader/Program.cs
@@ -0,0 +1,133 @@
+using System;
+using System.Collections;
+using System.IO;
+using DotXxlJob.Core.Model;
+using Hessian.Net;
+using Newtonsoft.Json;
+
+namespace HessianReader
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ byte[] myBinary = File.ReadAllBytes("1547621183.dat");
+
+ foreach (var i in myBinary)
+ {
+ Console.Write("0x");
+ Console.Write(i.ToString("x2"));
+ Console.Write(",");
+ }
+
+ Console.WriteLine(Environment.NewLine);
+ Console.WriteLine("---------------------------------------------------------------");
+
+
+
+
+ var serializer = new DataContractHessianSerializer(typeof (RpcRequest));
+
+ using (var stream1 = new MemoryStream(myBinary))
+ {
+ var ds = new Hessian.Deserializer(stream1);
+
+ Hessian.ClassDef def = ds.ReadClassDefinition();
+ Console.WriteLine(JsonConvert.SerializeObject(def));
+ Console.WriteLine(ds.ReadValue());
+ //Console.WriteLine(ds.ReadLong());
+ //Console.WriteLine(ds.ReadString());
+ //Console.WriteLine(ds.ReadString());
+ //Console.WriteLine(ds.ReadString());
+ //Console.WriteLine(ds.ReadString());
+ //Console.WriteLine(ds.ReadValue());
+ //Console.WriteLine(ds.ReadValue());
+ Console.WriteLine(JsonConvert.SerializeObject(def));
+ }
+
+ return;
+
+ RpcRequest req = new RpcRequest {
+ RequestId = "71565f61-94e8-4dcf-9760-f2fb73a6886a",
+ CreateMillisTime = 1547621183585,
+ AccessToken = "",
+ ClassName = "com.xxl.job.core.biz.ExecutorBiz",
+ MethodName = "run",
+ ParameterTypes = new HessianArrayList {"class com.xxl.job.core.biz.model.TriggerParam"},
+ Version = "null",
+ Parameters = new HessianArrayList()
+ };
+
+ var p =new TriggerParam {
+ JobId=1,
+ ExecutorHandler="demoJobHandler",
+ ExecutorParams="111",
+ ExecutorBlockStrategy="SERIAL_EXECUTION",
+ ExecutorTimeout=0,
+ LogId=5,
+ LogDateTime=1547621183414L,
+ GlueType="BEAN",
+ GlueSource="",
+ GlueUpdateTime=1541254891000,
+ BroadcastIndex=0,
+ BroadcastTotal=1
+ };
+ req.Parameters.Add(p);
+
+ byte[] distArray;
+
+ using (MemoryStream stream = new MemoryStream())
+ {
+
+
+ serializer.WriteObject(stream,req);
+ //Console.WriteLine(Environment.NewLine);
+ //Console.WriteLine("---------------------------"+ stream.Length+"------------------------------------");
+ stream.Flush();
+ distArray =stream.ToArray();
+ }
+ foreach (var j in distArray)
+ {
+ Console.Write("0x");
+ Console.Write(j.ToString("x2"));
+ Console.Write(",");
+ }
+
+ Console.WriteLine(Environment.NewLine);
+ Console.WriteLine("---------------------------------------------------------------");
+
+ using (var stream2 = new MemoryStream(distArray))
+ {
+
+ var instance = serializer.ReadObject(stream2) as RpcRequest;
+
+ Console.WriteLine(JsonConvert.SerializeObject(instance));
+ }
+ /**
+ * requestId='71565f61-94e8-4dcf-9760-f2fb73a6886a',
+ * createMillisTime=1547621183585,
+ * accessToken='',
+ * className='com.xxl.job.core.biz.ExecutorBiz',
+ * methodName='run',
+ * parameterTypes=[class com.xxl.job.core.biz.model.TriggerParam],
+ * parameters=[
+ * TriggerParam{
+ * jobId=1,
+ * executorHandler='demoJobHandler',
+ * executorParams='111',
+ * executorBlockStrategy='SERIAL_EXECUTION',
+ * executorTimeout=0,
+ * logId=5,
+ * logDateTim=1547621183414,
+ * glueType='BEAN',
+ * glueSource='',
+ * glueUpdatetime=1541254891000,
+ * broadcastIndex=0,
+ * broadcastTotal=1
+ * }
+ * ], version='null'
+ *
+ */
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/DotXxlJob.Core/CallbackTaskQueue.cs b/src/DotXxlJob.Core/CallbackTaskQueue.cs
new file mode 100644
index 0000000..4df750c
--- /dev/null
+++ b/src/DotXxlJob.Core/CallbackTaskQueue.cs
@@ -0,0 +1,12 @@
+using DotXxlJob.Core.Model;
+
+namespace DotXxlJob.Core
+{
+ public class CallbackTaskQueue
+ {
+ public void Push(CallbackParam callbackParam)
+ {
+ throw new System.NotImplementedException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/DotXxlJob.Core/Config/XxlJobExecutorOptions.cs b/src/DotXxlJob.Core/Config/XxlJobExecutorOptions.cs
new file mode 100644
index 0000000..84e76cd
--- /dev/null
+++ b/src/DotXxlJob.Core/Config/XxlJobExecutorOptions.cs
@@ -0,0 +1,27 @@
+namespace DotXxlJob.Core.Config
+{
+ public class XxlJobExecutorOptions
+ {
+
+ public string AdminAddresses { get; set; }
+
+
+ public string AppName { get; set; }
+
+
+ public string SpecialBindAddress { get; set; }
+
+
+ public int Port { get; set; }
+
+
+ public string AccessToken { get; set; }
+
+
+ public string LogPath { get; set; }
+
+
+ public int LogRetentionDays { get; set; }
+
+ }
+}
\ No newline at end of file
diff --git a/src/DotXxlJob.Core/Constants.cs b/src/DotXxlJob.Core/Constants.cs
new file mode 100644
index 0000000..ec5092a
--- /dev/null
+++ b/src/DotXxlJob.Core/Constants.cs
@@ -0,0 +1,42 @@
+using System;
+
+namespace DotXxlJob.Core
+{
+ internal static class Constants
+ {
+ public const string XxlLogsDefaultRootDirectory = "xxl-job-logs";
+ public const string HandleLogsDirectory = "HandlerLogs";
+ public const string LogFileNameCallContextKey = "XxlJob.LogFileName";
+ public const int DefaultLogRetentionDays = 30;
+
+ public static TimeSpan RpcRequestExpireTimeSpan = TimeSpan.FromMinutes(3);
+
+ public const int MaxCallbackRetryTimes = 10;
+ //每次回调最多发送几条记录
+ public const int MaxCallbackRecordsPerRequest = 100;
+ public static TimeSpan CallbackRetryInterval = TimeSpan.FromSeconds(600);
+
+ //Admin集群机器请求默认超时时间
+ public static TimeSpan AdminServerDefaultTimeout = TimeSpan.FromSeconds(15);
+ //Admin集群中的某台机器熔断后间隔多长时间再重试
+ public static TimeSpan AdminServerReconnectInterval = TimeSpan.FromMinutes(3);
+ //Admin集群中的某台机器请求失败多少次后熔断
+ public const int AdminServerCircuitFaildTimes = 3;
+
+ public static TimeSpan JobThreadWaitTime = TimeSpan.FromSeconds(90);
+
+ public static class GlueType
+ {
+ public const string BEAN = "BEAN";
+ }
+
+ public static class ExecutorBlockStrategy
+ {
+ public const string SERIAL_EXECUTION = "SERIAL_EXECUTION";
+
+ public const string DISCARD_LATER = "DISCARD_LATER";
+
+ public const string COVER_EARLY = "COVER_EARLY";
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/DotXxlJob.Core/DateTimeExtensions.cs b/src/DotXxlJob.Core/DateTimeExtensions.cs
new file mode 100644
index 0000000..5ba3014
--- /dev/null
+++ b/src/DotXxlJob.Core/DateTimeExtensions.cs
@@ -0,0 +1,35 @@
+using System;
+
+namespace DotXxlJob.Core
+{
+ public static class DateTimeExtensions
+ {
+ private const long UnixEpochTicks = 621355968000000000;
+ private const long UnixEpochSeconds = 62135596800;
+ private const long UnixEpochMilliseconds = 62135596800000;
+
+ public static DateTimeOffset FromUnixTimeSeconds(this long seconds)
+ {
+ long ticks = seconds * TimeSpan.TicksPerSecond + UnixEpochTicks;
+ return new DateTime(ticks, DateTimeKind.Utc);
+ }
+
+ public static DateTime FromUnixTimeMilliseconds(this long milliseconds)
+ {
+ long ticks = milliseconds * TimeSpan.TicksPerMillisecond + UnixEpochTicks;
+ return new DateTime(ticks, DateTimeKind.Utc);
+ }
+
+ public static long ToUnixTimeSeconds(this DateTime dateTime)
+ {
+ long seconds = dateTime.ToUniversalTime().Ticks / TimeSpan.TicksPerSecond;
+ return seconds - UnixEpochSeconds;
+ }
+
+ public static long ToUnixTimeMilliseconds(this DateTime dateTime)
+ {
+ long milliseconds = dateTime.ToUniversalTime().Ticks / TimeSpan.TicksPerMillisecond;
+ return milliseconds - UnixEpochMilliseconds;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/DotXxlJob.Core/DefaultJobHandlerFactory.cs b/src/DotXxlJob.Core/DefaultJobHandlerFactory.cs
new file mode 100644
index 0000000..a3ebab6
--- /dev/null
+++ b/src/DotXxlJob.Core/DefaultJobHandlerFactory.cs
@@ -0,0 +1,10 @@
+namespace DotXxlJob.Core
+{
+ public class DefaultJobHandlerFactory:IJobHandlerFactory
+ {
+ public IJobHandler GetJobHandler(string handlerName)
+ {
+ return new HttpJobHandler();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/DotXxlJob.Core/DotXxlJob.Core.csproj b/src/DotXxlJob.Core/DotXxlJob.Core.csproj
index c5fbb8f..fc5fc47 100644
--- a/src/DotXxlJob.Core/DotXxlJob.Core.csproj
+++ b/src/DotXxlJob.Core/DotXxlJob.Core.csproj
@@ -8,4 +8,8 @@
+
+
+
+
diff --git a/src/DotXxlJob.Core/ExecutorRegistry.cs b/src/DotXxlJob.Core/ExecutorRegistry.cs
index 919fd73..d32f530 100644
--- a/src/DotXxlJob.Core/ExecutorRegistry.cs
+++ b/src/DotXxlJob.Core/ExecutorRegistry.cs
@@ -3,8 +3,11 @@ namespace DotXxlJob.Core
///
/// 执行器注册注册
///
- public class ExecutorRegistry
+ public class ExecutorRegistry:IExecutorRegistry
{
-
+ public void Start()
+ {
+ throw new System.NotImplementedException();
+ }
}
}
\ No newline at end of file
diff --git a/src/DotXxlJob.Core/HttpJobHandler.cs b/src/DotXxlJob.Core/HttpJobHandler.cs
new file mode 100644
index 0000000..9228d74
--- /dev/null
+++ b/src/DotXxlJob.Core/HttpJobHandler.cs
@@ -0,0 +1,18 @@
+using System.Threading.Tasks;
+using DotXxlJob.Core.Model;
+
+namespace DotXxlJob.Core
+{
+ public class HttpJobHandler:IJobHandler
+ {
+ public void Dispose()
+ {
+
+ }
+
+ public Task Execute(JobExecuteContext context)
+ {
+ return Task.FromResult(ReturnT.SUCCESS);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/DotXxlJob.Core/IJobHandler.cs b/src/DotXxlJob.Core/IJobHandler.cs
index c458fe1..3734aa2 100644
--- a/src/DotXxlJob.Core/IJobHandler.cs
+++ b/src/DotXxlJob.Core/IJobHandler.cs
@@ -1,17 +1,17 @@
using System;
using System.Threading.Tasks;
+using DotXxlJob.Core.Model;
namespace DotXxlJob.Core
{
public abstract class AbstractJobHandler:IJobHandler
{
-
///
///
///
///
///
- public abstract Task> Execute(string param);
+ public abstract Task Execute(JobExecuteContext context);
public virtual void Dispose()
@@ -21,6 +21,6 @@ namespace DotXxlJob.Core
public interface IJobHandler:IDisposable
{
- Task> Execute(string param);
+ Task Execute(JobExecuteContext context);
}
}
\ No newline at end of file
diff --git a/src/DotXxlJob.Core/ITaskExecutor.cs b/src/DotXxlJob.Core/ITaskExecutor.cs
new file mode 100644
index 0000000..679f513
--- /dev/null
+++ b/src/DotXxlJob.Core/ITaskExecutor.cs
@@ -0,0 +1,12 @@
+using System.Threading.Tasks;
+using DotXxlJob.Core.Model;
+
+namespace DotXxlJob.Core
+{
+ public interface ITaskExecutor
+ {
+ string GlueType { get; }
+
+ Task Execute(TriggerParam triggerParam);
+ }
+}
\ No newline at end of file
diff --git a/src/DotXxlJob.Core/IXxlJobExecutor.cs b/src/DotXxlJob.Core/IXxlJobExecutor.cs
index 3c65fe3..07254b5 100644
--- a/src/DotXxlJob.Core/IXxlJobExecutor.cs
+++ b/src/DotXxlJob.Core/IXxlJobExecutor.cs
@@ -1,7 +1,20 @@
+using DotXxlJob.Core.Model;
+
namespace DotXxlJob.Core
{
public interface IXxlJobExecutor
{
-
+ ReturnT Beat();
+
+
+ ReturnT IdleBeat(int jobId);
+
+
+ ReturnT Kill(int jobId);
+
+ ReturnT Log(long logDateTim, int logId, int fromLineNum);
+
+
+ ReturnT Run(TriggerParam triggerParam);
}
}
\ No newline at end of file
diff --git a/src/DotXxlJob.Core/JobDispatcher.cs b/src/DotXxlJob.Core/JobDispatcher.cs
new file mode 100644
index 0000000..de95df8
--- /dev/null
+++ b/src/DotXxlJob.Core/JobDispatcher.cs
@@ -0,0 +1,130 @@
+using System;
+using System.Collections.Concurrent;
+using DotXxlJob.Core.Model;
+using Microsoft.Extensions.Logging;
+
+namespace DotXxlJob.Core
+{
+ ///
+ /// 负责实际的JOB轮询
+ ///
+ public class JobDispatcher
+ {
+ private readonly TaskExecutorFactory _executorFactory;
+ private readonly CallbackTaskQueue _callbackTaskQueue;
+
+ private readonly ConcurrentDictionary RUNNING_QUEUE = new ConcurrentDictionary();
+
+
+ private readonly ILogger _jobQueueLogger;
+ private readonly ILogger _logger;
+ public JobDispatcher(
+ TaskExecutorFactory executorFactory,
+ CallbackTaskQueue callbackTaskQueue,
+ ILoggerFactory loggerFactory
+ )
+ {
+ this. _executorFactory = executorFactory;
+ this. _callbackTaskQueue = callbackTaskQueue;
+
+
+ this._jobQueueLogger = loggerFactory.CreateLogger();
+ this._logger = loggerFactory.CreateLogger();
+ }
+
+
+ ///
+ /// 尝试移除JobTask
+ ///
+ ///
+ ///
+ ///
+ public bool TryRemoveJobTask(int jobId)
+ {
+ if (RUNNING_QUEUE.TryGetValue(jobId, out var jobQueue))
+ {
+ jobQueue.Stop();
+ return true;
+ }
+ return false;
+ }
+
+ ///
+ /// 执行队列,并快速返回结果
+ ///
+ ///
+ ///
+ ///
+ public ReturnT Execute(TriggerParam triggerParam)
+ {
+
+ var executor = this._executorFactory.GetTaskExecutor(triggerParam.GlueType);
+ if (executor == null)
+ {
+ return ReturnT.Failed($"glueType[{triggerParam.GlueType}] is not supported ");
+ }
+
+ // 1. 根据JobId 获取 TaskQueue; 用于判断是否有正在执行的任务
+ if (RUNNING_QUEUE.TryGetValue(triggerParam.JobId, out var taskQueue))
+ {
+ if (taskQueue.Executor != executor) //任务执行器变更
+ {
+ return ChangeJobQueue(triggerParam, executor);
+ }
+ }
+
+ if (taskQueue != null) //旧任务还在执行,判断执行策略
+ {
+ //丢弃后续的
+ if (Constants.ExecutorBlockStrategy.DISCARD_LATER == triggerParam.ExecutorBlockStrategy)
+ {
+ return ReturnT.Failed($"block strategy effect:{triggerParam.ExecutorBlockStrategy}");
+ }
+ //覆盖较早的
+ if (Constants.ExecutorBlockStrategy.COVER_EARLY == triggerParam.ExecutorBlockStrategy)
+ {
+ return taskQueue.Replace(triggerParam);
+ }
+ }
+
+ return PushJobQueue(triggerParam, executor);
+
+ }
+
+
+ ///
+ /// 等待检查
+ ///
+ ///
+ ///
+ public ReturnT IdleBeat(int jobId)
+ {
+ return RUNNING_QUEUE.ContainsKey(jobId) ?
+ new ReturnT(ReturnT.FAIL_CODE, "job thread is running or has trigger queue.")
+ : ReturnT.SUCCESS;
+ }
+
+
+ private ReturnT PushJobQueue(TriggerParam triggerParam, ITaskExecutor executor)
+ {
+ JobQueue jobQueue = new JobQueue ( executor, this._callbackTaskQueue,this._jobQueueLogger);
+ if (RUNNING_QUEUE.TryAdd(triggerParam.JobId, jobQueue))
+ {
+ jobQueue.Push(triggerParam);
+ }
+ return ReturnT.Failed("add running queue executor error");
+ }
+
+ private ReturnT ChangeJobQueue(TriggerParam triggerParam, ITaskExecutor executor)
+ {
+
+ JobQueue jobQueue = new JobQueue ( executor, this._callbackTaskQueue,this._jobQueueLogger);
+ if (RUNNING_QUEUE.TryUpdate(triggerParam.JobId, jobQueue, null))
+ {
+ return jobQueue.Push(triggerParam);
+ }
+ return ReturnT.Failed(" replace running queue executor error");
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/src/DotXxlJob.Core/TaskExcutor.cs b/src/DotXxlJob.Core/JobLogger.cs
similarity index 61%
rename from src/DotXxlJob.Core/TaskExcutor.cs
rename to src/DotXxlJob.Core/JobLogger.cs
index 67851a8..e5133da 100644
--- a/src/DotXxlJob.Core/TaskExcutor.cs
+++ b/src/DotXxlJob.Core/JobLogger.cs
@@ -1,6 +1,6 @@
namespace DotXxlJob.Core
{
- public class TaskExcutor
+ public class JobLogger
{
}
diff --git a/src/DotXxlJob.Core/LogResult.cs b/src/DotXxlJob.Core/LogResult.cs
new file mode 100644
index 0000000..42ba8c9
--- /dev/null
+++ b/src/DotXxlJob.Core/LogResult.cs
@@ -0,0 +1,7 @@
+namespace DotXxlJob.Core
+{
+ public class LogResult
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/src/DotXxlJob.Core/Model/CallbackParam.cs b/src/DotXxlJob.Core/Model/CallbackParam.cs
new file mode 100644
index 0000000..24aa640
--- /dev/null
+++ b/src/DotXxlJob.Core/Model/CallbackParam.cs
@@ -0,0 +1,10 @@
+namespace DotXxlJob.Core.Model
+{
+ public class CallbackParam
+ {
+ public CallbackParam(TriggerParam triggerParam, ReturnT result)
+ {
+ throw new System.NotImplementedException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/DotXxlJob.Core/Model/HessianArrayList.cs b/src/DotXxlJob.Core/Model/HessianArrayList.cs
new file mode 100644
index 0000000..a3c3ba7
--- /dev/null
+++ b/src/DotXxlJob.Core/Model/HessianArrayList.cs
@@ -0,0 +1,11 @@
+using System.Collections.Generic;
+using System.Runtime.Serialization;
+
+namespace DotXxlJob.Core.Model
+{
+ [DataContract(Name = "hessianArrayList")]
+ public class HessianArrayList:List