Quartz应用
背景:公司要上代发业务
需要突破点:
1.销售端根据不同的国家需要采用不同的销售策略
2.不同代发平台数据格式不一致,并且同一个产品同一个代发平台不同的国家sku不一样
3.同一个sku不同起运地库存数据不一致
.....
综合考虑,放弃api方式,以控制台+Quartz实现
private static string BuildModel = ConfigurationManager.AppSettings["BuildModel"];
private static string Countrys = ConfigurationManager.AppSettings["Countrys"];
static void Main(string[] args)
{
if (string.IsNullOrEmpty(BuildModel)) { Console.WriteLine("检查BuildModel是否正确"); return; }
if (BuildModel == "1")
{
#region 动态创建任务
if (!string.IsNullOrEmpty(Countrys))
{
string[] countrys = Countrys.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
foreach (var country in countrys)
{
if (country.ToLower() == "upload2wms") continue;
string c1 = country.Split(new char[] { '_' })[0];
string c2 = country.Split(new char[] { '_' })[1];
File.Delete($@"{Path.GetFullPath("../..")}\VidaxlJob_{c1}_{c2}.cs");
CodeCompileUnit unit = new CodeCompileUnit();
CodeNamespace ns = new CodeNamespace("QuartzNet");
ns.Imports.Add(new CodeNamespaceImport("Quartz"));
CodeTypeDeclaration cls = new CodeTypeDeclaration($"VidaxlJob_{c1}_{c2}") { IsClass = true };
cls.TypeAttributes = TypeAttributes.Public;
ns.Types.Add(cls);
unit.Namespaces.Add(ns);
CodeMemberMethod method = new CodeMemberMethod();
method.Name = "Execute";
method.Attributes = MemberAttributes.Public | MemberAttributes.Final;
method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(IJobExecutionContext), "context"));
method.Statements.Add(new CodeSnippetStatement($" StartExecute(\"QuartzNet_{c1}_{c2}\", \"VidaxlJob_{c1}_{c2}\",\"{c1}\",\"{c2}\"); "));
cls.Members.Add(method);
CodeTypeDeclaration dec1 = new CodeTypeDeclaration("VidaxlJob") { IsClass = true };
CodeTypeDeclaration dec2 = new CodeTypeDeclaration("IJob") { IsInterface = true };
cls.BaseTypes.Add(new CodeTypeReference(dec1.Name));
cls.BaseTypes.Add(new CodeTypeReference(dec2.Name));
cls.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeTypeReference(typeof(DisallowConcurrentExecutionAttribute))));
CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
CodeGeneratorOptions options = new CodeGeneratorOptions();
options.BracingStyle = "C";
options.BlankLinesBetweenMembers = true;
string scFile = $@"{Path.GetFullPath("../..")}\VidaxlJob_{c1}_{c2}.cs";
using (System.IO.StreamWriter sw = new System.IO.StreamWriter(scFile))
{
provider.GenerateCodeFromCompileUnit(unit, sw, options);
}
}
}
Console.WriteLine("第一步:动态创建任务成功,请先包含文件然后前往app.config修改BuildModel运行模式为'2'执行第二步");
Console.ReadKey();
#endregion
}
else if (BuildModel == "2")
{
#region 动态注册任务
if (!string.IsNullOrEmpty(Countrys))
{
CodeCompileUnit scUnit = new CodeCompileUnit();
CodeNamespace scNs = new CodeNamespace("QuartzNet");
scNs.Imports.Add(new CodeNamespaceImport("Quartz"));
scNs.Imports.Add(new CodeNamespaceImport("Quartz.Impl"));
scNs.Imports.Add(new CodeNamespaceImport("System.Configuration"));
CodeTypeDeclaration schedulerCls = new CodeTypeDeclaration($"Scheduler") { IsClass = true };
schedulerCls.TypeAttributes = TypeAttributes.Public;
scNs.Types.Add(schedulerCls);
scUnit.Namespaces.Add(scNs);
CodeMemberMethod schedulerMethod = new CodeMemberMethod();
schedulerMethod.Name = "Start";
schedulerMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final | MemberAttributes.Static;
schedulerMethod.Statements.Add(new CodeSnippetStatement($@"
IScheduler scheduler = StdSchedulerFactory.GetDefaultScheduler();
scheduler.Start(); "));
string[] countrys = Countrys.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
foreach (var country in countrys)
{
string c1 = country.Split(new char[] { '_' })[0];
string c2 = country.Split(new char[] { '_' })[1];
schedulerMethod.Statements.Add(new CodeSnippetStatement($@"
IJobDetail job_{c1}_{c2} = JobBuilder.Create<VidaxlJob_{c1}_{c2}>().Build();
ITrigger trigger_{c1}_{c2} = TriggerBuilder.Create()
.WithIdentity(""trigger_{c1}_{c2}"", ""group_{c1}_{c2}"")
.WithCronSchedule(ConfigurationManager.AppSettings[""Cron_{c1}_{c2}""])
.Build();
scheduler.ScheduleJob(job_{c1}_{c2}, trigger_{c1}_{c2}); "));
}
schedulerCls.Members.Add(schedulerMethod);
CodeDomProvider scProvider = CodeDomProvider.CreateProvider("CSharp");
CodeGeneratorOptions scOptions = new CodeGeneratorOptions();
scOptions.BracingStyle = "C";
scOptions.BlankLinesBetweenMembers = true;
string outputFile = $@"{Path.GetFullPath("../..")}\Scheduler.cs";
using (System.IO.StreamWriter sw = new System.IO.StreamWriter(outputFile))
{
scProvider.GenerateCodeFromCompileUnit(scUnit, sw, scOptions);
}
}
Console.WriteLine("第二步:动态注册任务成功,请先包含文件然后前往app.config修改BuildModel运行模式为'3'执行第三步");
Console.ReadKey();
#endregion
}
else if (BuildModel == "3")
{
Console.WriteLine("第三步:正式自动调度任务");
Scheduler.Start();
Console.ReadKey();
}
}
VidaxlJob.cs统一处理不同的代发供应商数据
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace QuartzNet
{
[DisallowConcurrentExecution]
public class VidaxlJob
{
private static VidaxlManager VidaxlManager = new VidaxlManager();
private static string JobTimeout = ConfigurationManager.AppSettings["JobTimeout"];
public void StartExecute(string log, string jobName, string supplierId, string countryShort)
{
byte[] buffer = Guid.NewGuid().ToByteArray();
string BatchId = BitConverter.ToInt64(buffer, 0).ToString();
string str = $"{DateTime.Now},任务:{jobName},批次号:{BatchId},countryShort:{countryShort},开始执行";
Console.WriteLine(str);
ExceptionlessManager.WriteExceptionLog(log, str, null, "", "");
string path = "";
ReturnMsg msg = null;
if (supplierId == "V4787")
{
TimeSpan ts = TimeSpan.FromMilliseconds(Convert.ToDouble(new DataTable().Compute(JobTimeout, "")));
CancellationTokenSource source = new CancellationTokenSource();
Task t = Task.Run(() => { msg = VidaxlManager.DownloadVidaxlInfo(countryShort, BatchId, ref path); }, source.Token);
if (!t.Wait(ts))
{
str = $"{DateTime.Now},任务:{jobName},批次号:{BatchId},线程超时,等待下次自动重试";
Console.WriteLine(str);
ExceptionlessManager.WriteExceptionLog(log, str, null, "", "");
Console.WriteLine();
source.Cancel();
return;
}
if (msg.Status == 200)
{
msg = VidaxlManager.InitVidaxlInfo(path, countryShort, BatchId);
}
}
else if (supplierId == "V4353")
{
msg = VidaxlManager.RequestGigaInfo(BatchId, countryShort);
}
else if (supplierId == "V5046")
{
msg = VidaxlManager.InitBigBuyProductInfo(countryShort, BatchId);
}
str = $"{DateTime.Now},任务:{jobName},批次号:{BatchId},countryShort:{countryShort},执行状态:{msg.Status},执行结果:{msg.Msg}";
Console.WriteLine(str);
ExceptionlessManager.WriteExceptionLog(log, str, null, "", "");
Console.WriteLine();
}
}
}