增加克隆功能完成

This commit is contained in:
大石头 2020-01-11 18:48:20 +08:00
parent 9bce1132bc
commit 4b9bb75a29
13 changed files with 110 additions and 25 deletions

View File

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
@ -238,6 +238,7 @@ namespace AntJob.Data.Entity
return new JobModel
{
Name = Name,
ClassName = ClassName,
Enable = Enable,
Start = Start,

View File

@ -40,6 +40,14 @@ namespace AntJob.Data.Entity
[BindColumn("Name", "名称", "", Master = true)]
public String Name { get { return _Name; } set { if (OnPropertyChanging(__.Name, value)) { _Name = value; OnPropertyChanged(__.Name); } } }
private String _ClassName;
/// <summary>类名。支持该作业的处理器实现</summary>
[DisplayName("类名")]
[Description("类名。支持该作业的处理器实现")]
[DataObjectField(false, false, true, 50)]
[BindColumn("ClassName", "类名。支持该作业的处理器实现", "")]
public String ClassName { get { return _ClassName; } set { if (OnPropertyChanging(__.ClassName, value)) { _ClassName = value; OnPropertyChanged(__.ClassName); } } }
private String _DisplayName;
/// <summary>显示名</summary>
[DisplayName("显示名")]
@ -326,6 +334,7 @@ namespace AntJob.Data.Entity
case __.ID : return _ID;
case __.AppID : return _AppID;
case __.Name : return _Name;
case __.ClassName : return _ClassName;
case __.DisplayName : return _DisplayName;
case __.Mode : return _Mode;
case __.Topic : return _Topic;
@ -370,6 +379,7 @@ namespace AntJob.Data.Entity
case __.ID : _ID = value.ToInt(); break;
case __.AppID : _AppID = value.ToInt(); break;
case __.Name : _Name = Convert.ToString(value); break;
case __.ClassName : _ClassName = Convert.ToString(value); break;
case __.DisplayName : _DisplayName = Convert.ToString(value); break;
case __.Mode : _Mode = (JobModes)value.ToInt(); break;
case __.Topic : _Topic = Convert.ToString(value); break;
@ -423,6 +433,9 @@ namespace AntJob.Data.Entity
/// <summary>名称</summary>
public static readonly Field Name = FindByName(__.Name);
/// <summary>类名。支持该作业的处理器实现</summary>
public static readonly Field ClassName = FindByName(__.ClassName);
/// <summary>显示名</summary>
public static readonly Field DisplayName = FindByName(__.DisplayName);
@ -540,6 +553,9 @@ namespace AntJob.Data.Entity
/// <summary>名称</summary>
public const String Name = "Name";
/// <summary>类名。支持该作业的处理器实现</summary>
public const String ClassName = "ClassName";
/// <summary>显示名</summary>
public const String DisplayName = "DisplayName";
@ -658,6 +674,9 @@ namespace AntJob.Data.Entity
/// <summary>名称</summary>
String Name { get; set; }
/// <summary>类名。支持该作业的处理器实现</summary>
String ClassName { get; set; }
/// <summary>显示名</summary>
String DisplayName { get; set; }

View File

@ -97,6 +97,7 @@
<Column Name="ID" DataType="Int32" Identity="True" PrimaryKey="True" Description="编号" />
<Column Name="AppID" DataType="Int32" Description="应用" />
<Column Name="Name" DataType="String" Master="True" Description="名称" />
<Column Name="ClassName" DataType="String" Description="类名。支持该作业的处理器实现" />
<Column Name="DisplayName" DataType="String" Description="显示名" />
<Column Name="Mode" DataType="Int32" Description="调度模式" Type="JobModes" />
<Column Name="Topic" DataType="String" Description="主题。消息调度时消费的主题" />

View File

@ -186,15 +186,14 @@ namespace AntJob.Server
#region
/// <summary>获取指定名称的作业</summary>
/// <param name="names"></param>
/// <returns></returns>
[Api(nameof(GetJobs))]
public AntJob.Data.IJob[] GetJobs(String[] names)
public AntJob.Data.IJob[] GetJobs()
{
var app = Session["App"] as App;
var jobs = Job.FindAllByAppID(app.ID);
if (names != null && names.Length > 0) jobs = jobs.Where(e => names.Contains(e.Name)).ToList();
//if (names != null && names.Length > 0) jobs = jobs.Where(e => names.Contains(e.Name)).ToList();
return jobs.Select(e => e.ToModel()).ToArray();
}
@ -236,6 +235,7 @@ namespace AntJob.Server
if (item.Mode > 0) jb.Mode = item.Mode;
if (!item.DisplayName.IsNullOrEmpty()) jb.DisplayName = item.DisplayName;
if (!item.Description.IsNullOrEmpty()) jb.Description = item.Description;
if (!item.ClassName.IsNullOrEmpty()) jb.ClassName = item.ClassName;
if (jb.Mode == JobModes.Message || jb.Mode == JobModes.Alarm)
{

View File

@ -5,6 +5,7 @@ using System.Threading.Tasks;
using AntJob.Data.Entity;
using Microsoft.AspNetCore.Mvc;
using NewLife.Cube;
using NewLife.Security;
using NewLife.Web;
using XCode.Membership;
@ -151,5 +152,27 @@ namespace AntJob.Web.Areas.Ant.Controllers
return JsonRefresh("操作成功!");
}
/// <summary>克隆一个作业</summary>
/// <param name="id"></param>
/// <returns></returns>
[EntityAuthorize(PermissionFlags.Update)]
public ActionResult Clone(Int32 id)
{
var job = Job.FindByID(id);
if (job == null) return Index();
// 拷贝一次对象,避免因为缓存等原因修改原来的数据
job = job.Clone() as Job;
// 随机名称,插入新行
job.ID = 0;
job.Name = Rand.NextString(8);
job.Enable = false;
job.Insert();
// 跳转到编辑页这里时候已经得到新的自增ID
return Edit(job.ID + "");
}
}
}

View File

@ -45,6 +45,7 @@
<th class="text-center">任务</th>
<th class="text-center">统计</th>
<th class="text-center">错误</th>
<th class="text-center">克隆</th>
@if (this.Has(PermissionFlags.Detail, PermissionFlags.Update, PermissionFlags.Delete))
{
<th class="text-center">操作</th>
@ -120,6 +121,7 @@
<td class="text-center"><a href="JobTask?JobID=@entity.ID">任务</a></td>
<td class="text-center"><a href="JobStat?JobID=@entity.ID">统计</a></td>
<td class="text-center"><a href="JobError?JobID=@entity.ID">错误</a></td>
<td class="text-center">@Html.ActionLink("克隆", "Clone", "Job", new { id = entity.ID })</td>
@if (this.Has(PermissionFlags.Detail, PermissionFlags.Update, PermissionFlags.Delete))
{
<td class="text-center">

View File

@ -8,6 +8,9 @@ namespace AntJob.Data
/// <summary>名称</summary>
String Name { get; set; }
/// <summary>类名。支持该作业的处理器实现</summary>
String ClassName { get; set; }
/// <summary>是否启用</summary>
Boolean Enable { get; set; }

View File

@ -11,6 +11,10 @@ namespace AntJob.Data
[XmlAttribute]
public String Name { get; set; }
/// <summary>类名。支持该作业的处理器实现</summary>
[XmlAttribute]
public String ClassName { get; set; }
/// <summary>是否启用</summary>
[XmlAttribute]
public Boolean Enable { get; set; }

View File

@ -109,14 +109,8 @@ namespace AntJob.Providers
#region
/// <summary>获取指定名称的作业</summary>
/// <param name="names"></param>
/// <returns></returns>
public IJob[] GetJobs(String[] names)
{
if (names == null) names = new String[0];
return Invoke<JobModel[]>(nameof(GetJobs), new { names });
}
public IJob[] GetJobs() => Invoke<JobModel[]>(nameof(GetJobs));
/// <summary>批量添加作业</summary>
/// <param name="jobs"></param>

View File

@ -73,9 +73,8 @@ namespace AntJob.Providers
}
/// <summary>获取所有作业名称</summary>
/// <param name="names">名称列表</param>
/// <returns></returns>
public override IJob[] GetJobs(String[] names)
public override IJob[] GetJobs()
{
var jf = _File = JobFile.Current;
@ -84,7 +83,8 @@ namespace AntJob.Providers
{
foreach (var item in jf.Jobs)
{
if (names.Contains(item.Name)) list.Add(item);
/*if (names.Contains(item.Name))*/
list.Add(item);
}
}

View File

@ -18,9 +18,8 @@ namespace AntJob.Providers
void Stop();
/// <summary>获取所有作业。调度器定期获取以更新作业参数</summary>
/// <param name="names">名称列表</param>
/// <returns></returns>
IJob[] GetJobs(String[] names);
IJob[] GetJobs();
/// <summary>申请任务</summary>
/// <param name="job">作业</param>
@ -60,7 +59,7 @@ namespace AntJob.Providers
/// <summary>获取所有作业名称</summary>
/// <returns></returns>
public abstract IJob[] GetJobs(String[] names);
public abstract IJob[] GetJobs();
/// <summary>申请任务</summary>
/// <param name="job">作业</param>

View File

@ -72,6 +72,7 @@ namespace AntJob.Providers
var job = handler.Job ?? new JobModel();
job.Name = handler.Name;
job.ClassName = handler.GetType().FullName;
job.Mode = handler.Mode;
// 描述
@ -104,9 +105,8 @@ namespace AntJob.Providers
private IJob[] _jobs;
private DateTime _NextGetJobs;
/// <summary>获取所有作业名称</summary>
/// <param name="names">名称列表</param>
/// <returns></returns>
public override IJob[] GetJobs(String[] names)
public override IJob[] GetJobs()
{
// 周期性获取,避免请求过快
var now = TimerX.Now;
@ -114,7 +114,7 @@ namespace AntJob.Providers
{
_NextGetJobs = now.AddSeconds(5);
_jobs = Ant.GetJobs(names);
_jobs = Ant.GetJobs();
}
return _jobs;

View File

@ -1,9 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using AntJob.Data;
using AntJob.Providers;
using NewLife;
using NewLife.Log;
using NewLife.Reflection;
using NewLife.Threading;
namespace AntJob
@ -51,7 +53,7 @@ namespace AntJob
if (prv.Schedule == null) prv.Schedule = this;
prv.Start();
var jobs = prv.GetJobs(bs.Select(e => e.Name).ToArray());
var jobs = prv.GetJobs();
if (jobs == null || jobs.Length == 0)
{
XTrace.WriteLine("没有可用作业");
@ -106,13 +108,16 @@ namespace AntJob
// 查询所有处理器和被依赖的作业
var bs = Jobs;
var names = bs.Select(e => e.Name).ToList();
names = names.Distinct().ToList();
//var names = bs.Select(e => e.Name).ToList();
//names = names.Distinct().ToList();
// 拿到处理器对应的作业
var jobs = prv.GetJobs(names.ToArray());
var jobs = prv.GetJobs();
if (jobs == null) return false;
// 运行时动态往集合里面加处理器为了配合Sql+C#
CheckHandlers(prv, jobs, bs);
var flag = false;
// 遍历处理器,给空闲的增加任务
foreach (var handler in bs)
@ -158,6 +163,40 @@ namespace AntJob
return flag;
}
private void CheckHandlers(IJobProvider provider, IList<IJob> jobs, IList<Handler> handlers)
{
foreach (var job in jobs)
{
var handler = handlers.FirstOrDefault(e => e.Name == job.Name);
if (handler == null && job.Enable && !job.ClassName.IsNullOrEmpty())
{
XTrace.WriteLine("发现未知作业[{0}]@[{1}]", job.Name, job.ClassName);
try
{
// 实例化一个处理器
var type = Type.GetType(job.ClassName);
if (type != null)
{
handler = type.CreateInstance() as Handler;
if (handler != null)
{
XTrace.WriteLine("添加新作业[{0}]@[{1}]", job.Name, job.ClassName);
handler.Name = job.Name;
handler.Schedule = this;
handler.Provider = provider;
handler.Log = XTrace.Log;
handler.Start();
handlers.Add(handler);
}
}
}
catch { }
}
}
}
/// <summary>已完成</summary>
/// <param name="ctx"></param>
internal protected virtual void OnFinish(JobContext ctx) => _timer?.SetNext(-1);
@ -178,4 +217,4 @@ namespace AntJob
}
#endregion
}
}
}