using NCC;
using NCC.Common.Core.Manager;
using NCC.Common.Enum;
using NCC.Common.Extension;
using NCC.Common.Filter;
using NCC.Dependency;
using NCC.DynamicApiController;
using NCC.FriendlyException;
using NCC.JsonSerialization;
using NCC.LinqBuilder;
using NCC.RemoteRequest.Extensions;
using NCC.System.Interfaces.System;
using NCC.TaskScheduler;
using NCC.TaskScheduler.Entitys.Dto.TaskScheduler;
using NCC.TaskScheduler.Entitys.Entity;
using NCC.TaskScheduler.Entitys.Model;
using NCC.TaskScheduler.Interfaces.TaskScheduler;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using SqlSugar;
using SqlSugar.IOC;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace NCC.TaskScheduler.TaskScheduler
{
///
/// 定时任务
/// 版 本:V1.20.15
/// 版 权:Wesley(https://www.NCCsoft.com)
/// 作 者:NCC开发平台组
/// 日 期:2022-03-16
///
[ApiDescriptionSettings(Tag = "TaskScheduler", Name = "scheduletask", Order = 220)]
[Route("api/[controller]")]
public class TimeTaskService : ITimeTaskService, IDynamicApiController, ITransient
{
private readonly ISqlSugarRepository _timeTaskRepository;
private readonly ISqlSugarRepository _timeTaskLogRepository;
private readonly IDbLinkService _dblikServer;
private readonly IDataBaseService _dataBaseService;
private readonly SqlSugarScope db;
private readonly IUserManager _userManager;
private readonly ISpareTimeListener _spareTimeListener;
///
/// 初始化一个类型的新实例
///
public TimeTaskService(ISqlSugarRepository timeTaskRepository,
ISqlSugarRepository timeTaskLogRepository,
IUserManager userManager, IDbLinkService dblikServer, IDataBaseService dataBaseService, ISpareTimeListener spareTimeListener)
{
_timeTaskRepository = timeTaskRepository;
_timeTaskLogRepository = timeTaskLogRepository;
db = timeTaskRepository.Context;
_userManager = userManager;
_dblikServer = dblikServer;
_dataBaseService = dataBaseService;
_spareTimeListener = spareTimeListener;
}
#region Get
///
/// 列表
///
/// 请求参数
///
[HttpGet("")]
public async Task GetList([FromQuery] PageInputBase input)
{
var queryWhere = LinqExpression.And().And(x => x.DeleteMark == null);
if (!string.IsNullOrEmpty(input.keyword))
queryWhere = queryWhere.And(m => m.FullName.Contains(input.keyword) || m.EnCode.Contains(input.keyword));
var list = await _timeTaskRepository.Entities.Where(queryWhere).OrderBy(x => x.CreatorTime, OrderByType.Desc).ToPagedListAsync(input.currentPage, input.pageSize);
var pageList = new SqlSugarPagedList()
{
list = list.list.Adapt>(),
pagination = list.pagination
};
return PageResult.SqlSugarPageResult(pageList);
}
///
/// 列表(执行记录)
///
/// 请求参数
/// 任务Id
///
[HttpGet("{id}/TaskLog")]
public async Task GetTaskLogList([FromQuery] TaskLogInput input, string id)
{
var whereLambda = LinqExpression.And().And(x => x.TaskId == id);
if (input.runResult.IsNotEmptyOrNull())
{
whereLambda = whereLambda.And(x => x.RunResult == input.runResult);
}
if (!input.startTime.IsNullOrEmpty() && !input.endTime.IsNullOrEmpty())
{
var start = Ext.GetDateTime(input.startTime.ToString());
var end = Ext.GetDateTime(input.endTime.ToString());
start = new DateTime(start.Year, start.Month, start.Day, 0, 0, 0, 0);
end = new DateTime(end.Year, end.Month, end.Day, 23, 59, 59, 999);
whereLambda = whereLambda.And(x => SqlFunc.Between(x.RunTime, start, end));
}
var list = await _timeTaskLogRepository.Entities.Where(whereLambda).OrderBy(x => x.RunTime, OrderByType.Desc).ToPagedListAsync(input.currentPage, input.pageSize);
var pageList = new SqlSugarPagedList()
{
list = list.list.Adapt>(),
pagination = list.pagination
};
return PageResult.SqlSugarPageResult(pageList);
}
///
/// 信息
///
/// 主键值
///
[HttpGet("Info/{id}")]
public async Task GetInfo_Api(string id)
{
var data = await GetInfo(id);
var output = data.Adapt();
return output;
}
#endregion
#region Post
///
/// 新建
///
/// 实体对象
///
[HttpPost("")]
public async Task Create([FromBody] TimeTaskCrInput input)
{
if (await _timeTaskRepository.AnyAsync(x => x.EnCode == input.enCode && x.DeleteMark == null) || await _timeTaskRepository.AnyAsync(x => x.FullName == input.fullName && x.DeleteMark == null))
throw NCCException.Oh(ErrorCode.COM1004);
var comtentModel = input.executeContent.Deserialize();
var entity = input.Adapt();
entity.ExecuteCycleJson = comtentModel.cron;
var result = await Create(entity);
_ = result ?? throw NCCException.Oh(ErrorCode.COM1000);
// 添加到任务调度里
AddTimerJob(result);
}
///
/// 更新
///
/// 主键值
/// 实体对象
///
[HttpPut("{id}")]
public async Task Update(string id, [FromBody] TimeTaskUpInput input)
{
if (await _timeTaskRepository.AnyAsync(x => x.Id != id && x.EnCode == input.enCode && x.DeleteMark == null) || await _timeTaskRepository.AnyAsync(x => x.Id != id && x.FullName == input.fullName && x.DeleteMark == null))
throw NCCException.Oh(ErrorCode.COM1004);
var entityOld = await GetInfo(id);
// 先从调度器里取消
SpareTime.Cancel(entityOld.Id + entityOld.EnCode);
var entityNew = input.Adapt();
var isOk = await Update(entityNew);
if (isOk < 1)
throw NCCException.Oh(ErrorCode.COM1001);
var comtentModel = entityNew.ExecuteContent.Deserialize();
// 再添加到任务调度里
if (entityOld.EnabledMark == 1)
{
AddTimerJob(entityNew);
}
}
///
/// 删除
///
/// 主键值
///
[HttpDelete("{id}")]
public async Task Delete(string id)
{
var entity = await GetInfo(id);
if (entity == null)
throw NCCException.Oh(ErrorCode.COM1005);
var isOk = await Delete(entity);
if (isOk < 1)
throw NCCException.Oh(ErrorCode.COM1002);
// 从调度器里取消
SpareTime.Cancel(entity.Id);
}
///
/// 停止
///
/// 主键值
///
[HttpPut("{id}/Actions/Stop")]
public async Task Stop(string id)
{
var entity = await GetInfo(id);
entity.EnabledMark = 0;
var isOk = await Update(entity);
if (isOk < 1)
throw NCCException.Oh(ErrorCode.COM1003);
SpareTime.Stop(entity.Id);
}
///
/// 启动
///
/// 主键值
///
[HttpPut("{id}/Actions/Enable")]
public async Task Enable(string id)
{
var entity = await GetInfo(id);
entity.EnabledMark = 1;
var isOk = await Update(entity);
if (isOk < 1)
throw NCCException.Oh(ErrorCode.COM1003);
if (SpareTime.AnyTask(id))
{
SpareTime.Start(entity.Id);
}
else
{
AddTimerJob(entity);
}
}
#endregion
#region PublicMethod
///
/// 新增定时任务
///
///
[NonAction]
public void AddTimerJob(TimeTaskEntity input)
{
input.ExecuteCycleJson = input.ExecuteContent.Deserialize().cron;
Action action = async (timer, count) =>
{
var msg = await PerformJob(input.ExecuteType, input.ExecuteContent.Deserialize(), input.Id, null);
var nextRunTime = ((DateTimeOffset)SpareTime.GetCronNextOccurrence(input.ExecuteCycleJson)).DateTime;
DbScoped.SugarScope.Updateable().SetColumns(x => new TimeTaskEntity()
{
RunCount = x.RunCount + 1,
LastRunTime = DateTime.Now,
NextRunTime = nextRunTime,
LastModifyUserId = "admin",
LastModifyTime = DateTime.Now
}
).Where(x => x.Id == input.Id).ExecuteCommand();
var status = msg.IsNullOrEmpty() ? 2 : 3;
var spareTimerExecuter = new SpareTimerExecuter(timer, status, msg);
await _spareTimeListener.OnListener(spareTimerExecuter);
};
//创建定时任务
SpareTime.Do(input.ExecuteCycleJson, action, input.Id, input.Description, true, executeType: SpareTimeExecuteTypes.Parallel);
}
///
/// 启动自启动任务
///
[NonAction]
public void StartTimerJob()
{
var list = _timeTaskRepository.Entities.Where(x => x.DeleteMark == null && x.EnabledMark.Equals(1)).ToList();
//查询数据库现有开启的定时任务列表
list.ForEach(AddTimerJob);
}
///
/// 详情
///
///
///
///
[NonAction]
public async Task GetInfo(string id, Dictionary tenantDic = null)
{
return await _timeTaskRepository.FirstOrDefaultAsync(x => x.Id == id && x.DeleteMark == null);
}
///
/// 列表
///
///
[NonAction]
public async Task> GetList()
{
return await _timeTaskRepository.Entities.Where(x => x.DeleteMark == null).ToListAsync();
}
///
/// 新增
///
///
///
[NonAction]
public async Task Create(TimeTaskEntity entity)
{
return await _timeTaskRepository.Context.Insertable(entity).CallEntityMethod(m => m.Creator()).ExecuteReturnEntityAsync();
}
///
/// 新增日志
///
///
///
///
[NonAction]
public async Task CreateTaskLog(TimeTaskLogEntity entity, Dictionary tenantDic = null)
{
return await _timeTaskLogRepository.InsertAsync(entity);
}
///
/// 删除
///
///
///
[NonAction]
public async Task Delete(TimeTaskEntity entity)
{
return await _timeTaskRepository.Context.Updateable(entity).IgnoreColumns(ignoreAllNullColumns: true).CallEntityMethod(m => m.Delete()).ExecuteCommandAsync();
}
///
/// 修改
///
///
///
///
[NonAction]
public async Task Update(TimeTaskEntity entity, Dictionary tenantDic = null)
{
return await _timeTaskRepository.Context.Updateable(entity).IgnoreColumns(ignoreAllNullColumns: true).CallEntityMethod(m => m.LastModify()).ExecuteCommandAsync();
}
#endregion
#region PrivateMethod
///
/// 根据类型执行任务
///
///
///
///
///
private async Task PerformJob(string type, ContentModel model, string id, Dictionary tenantDic)
{
var msg = "";
if (type == "1")
{
msg = await Connector(model, id);
}
else
{
msg = Storage(model, id, tenantDic);
}
return msg;
}
///
/// 接口
///
///
///
private async Task Connector(ContentModel model, string id)
{
try
{
var parameters = new Dictionary();
var headersString = App.HttpContext != null && _userManager != null ? string.Format("{\"{0}\":\"{1}\"}", "Authorization", _userManager.ToKen) : null;
var headers = string.IsNullOrEmpty(headersString)
? null
: JSON.Deserialize>(headersString);
foreach (var item in model.storedParameter)
{
parameters.Add(item.Key, item.Value);
}
switch (model.interfaceType.ToLower())
{
case "get":
await model.interfaceUrl.SetHeaders(headers).SetQueries(parameters).GetAsStringAsync();
break;
case "post":
await model.interfaceUrl.SetHeaders(headers).SetBody(parameters).PostAsStringAsync();
break;
default:
break;
}
return "";
}
catch (Exception ex)
{
return ex.Message;
}
}
///
/// 存储过程
///
///
///
///
public string Storage(ContentModel model, string id, Dictionary tenantDic)
{
try
{
List parameters = new List();
foreach (var item in model.storedParameter)
{
SugarParameter sugarParameter = new SugarParameter("@" + item.Key, item.Value);
parameters.Add(sugarParameter);
}
if (!model.database.Equals("0"))
{
if (!db.IsAnyConnection(model.database))
{
var link = _dblikServer.GetInfo(model.database).Result;
_dataBaseService.AddConnection(link);
}
var otherDB = db.GetConnection(model.database);
otherDB.Ado.UseStoredProcedure().GetDataTable(model.stored, parameters);
}
else
{
db.Ado.UseStoredProcedure().GetDataTable(model.stored, parameters);
}
return "";
}
catch (Exception ex)
{
return ex.Message;
}
}
#endregion
}
}