using JLHHJSvr.BLL; using JLHHJSvr.Com.Model; using LJLib.SQLEX; using System; using System.Collections.Generic; using System.Data.SqlClient; using System.Diagnostics; using System.Text; namespace JLHHJSvr.Helper { internal sealed class ScheduleTaskHelper { public const string TaskTypeMattressRecalc = "mattress_recalc"; public const string TaskTypeBatchModifyMattressInterfaceConfig = "batch_modify_mattress_interface_config"; private readonly object _runLock = new object(); private bool _running; public static string GetTaskTypeName(string taskType) { switch (taskType) { case TaskTypeMattressRecalc: return "重算报价"; case TaskTypeBatchModifyMattressInterfaceConfig: return "批量批改配置"; default: return taskType ?? string.Empty; } } public static int CreateTaskLog(SqlCommand cmd, u_task_log info) { var taskid = BllHelper.GetID(cmd, "u_task_log"); cmd.CommandText = @" INSERT INTO u_task_log (taskid, task_type, run_mode, schedule_time, status, total_count, success_count, fail_count, skip_count, request_json, log_msg, create_emp, create_time, start_time) VALUES (@taskid, @task_type, @run_mode, @schedule_time, @status, @total_count, 0, 0, 0, @request_json, '', @create_emp, GETDATE(), " + (info.start_time.HasValue ? "GETDATE()" : "NULL") + ")"; cmd.Parameters.Clear(); cmd.Parameters.AddWithValue("@taskid", taskid); cmd.Parameters.AddWithValue("@task_type", info.task_type ?? string.Empty); cmd.Parameters.AddWithValue("@run_mode", info.run_mode); cmd.Parameters.AddWithValue("@schedule_time", (object)info.schedule_time ?? DBNull.Value); cmd.Parameters.AddWithValue("@status", info.status); cmd.Parameters.AddWithValue("@total_count", info.total_count); cmd.Parameters.AddWithValue("@request_json", info.request_json ?? string.Empty); cmd.Parameters.AddWithValue("@create_emp", info.create_emp ?? string.Empty); cmd.ExecuteNonQuery(); return taskid; } public static void InsertTaskLogItems(SqlCommand cmd, int taskid, List items) { foreach (var item in items) { cmd.CommandText = @" INSERT INTO u_task_log_mx (taskid, printid, biz_id, biz_code, biz_name, status, result_json, err_msg, start_time) VALUES (@taskid, @printid, @biz_id, @biz_code, @biz_name, @status, '', '', " + (item.start_time.HasValue ? "GETDATE()" : "NULL") + ")"; cmd.Parameters.Clear(); cmd.Parameters.AddWithValue("@taskid", taskid); cmd.Parameters.AddWithValue("@printid", item.printid); cmd.Parameters.AddWithValue("@biz_id", item.biz_id); cmd.Parameters.AddWithValue("@biz_code", item.biz_code ?? string.Empty); cmd.Parameters.AddWithValue("@biz_name", item.biz_name ?? string.Empty); cmd.Parameters.AddWithValue("@status", item.status); cmd.ExecuteNonQuery(); } } public static void UpdateTaskLogItemResults(SqlCommand cmd, int taskid, List items) { foreach (var item in items) { cmd.CommandText = @" UPDATE u_task_log_mx SET status = @status, result_json = @result_json, err_msg = @err_msg, start_time = ISNULL(start_time, GETDATE()), end_time = GETDATE() WHERE taskid = @taskid AND printid = @printid"; cmd.Parameters.Clear(); cmd.Parameters.AddWithValue("@status", item.status); cmd.Parameters.AddWithValue("@result_json", item.result_json ?? string.Empty); cmd.Parameters.AddWithValue("@err_msg", LimitValue(item.err_msg, 4000)); cmd.Parameters.AddWithValue("@taskid", taskid); cmd.Parameters.AddWithValue("@printid", item.printid); cmd.ExecuteNonQuery(); } } public static void FinishTaskLog(SqlCommand cmd, int taskid, int totalCount, int successCount, int failCount, int skipCount, string logMsg) { var status = failCount > 0 && (successCount > 0 || skipCount > 0) ? 4 : (failCount > 0 ? 3 : 2); cmd.CommandText = @" UPDATE u_task_log SET status = @status, total_count = @total_count, success_count = @success_count, fail_count = @fail_count, skip_count = @skip_count, log_msg = @log_msg, end_time = GETDATE() WHERE taskid = @taskid"; cmd.Parameters.Clear(); cmd.Parameters.AddWithValue("@status", status); cmd.Parameters.AddWithValue("@total_count", totalCount); cmd.Parameters.AddWithValue("@success_count", successCount); cmd.Parameters.AddWithValue("@fail_count", failCount); cmd.Parameters.AddWithValue("@skip_count", skipCount); cmd.Parameters.AddWithValue("@log_msg", LimitValue(logMsg, 8000)); cmd.Parameters.AddWithValue("@taskid", taskid); cmd.ExecuteNonQuery(); } public void ExecuteDueTasks() { lock (_runLock) { if (_running) return; _running = true; } try { var taskIds = GetDueTaskIds(); foreach (var taskid in taskIds) { ExecuteTask(taskid); } } catch (Exception ex) { Trace.Write(ex); } finally { lock (_runLock) { _running = false; } } } private List GetDueTaskIds() { var ids = new List(); using (var con = GlobalVar.ConnectionString.NewSqlConnection()) using (var cmd = con.CreateCommand()) { con.Open(); cmd.CommandText = @" SELECT taskid FROM u_task_log WITH (NOLOCK) WHERE run_mode = 2 AND status = 0 AND schedule_time <= GETDATE() ORDER BY schedule_time, taskid"; using (var reader = cmd.ExecuteReader()) { while (reader.Read()) { ids.Add(Convert.ToInt32(reader["taskid"])); } } } return ids; } private void ExecuteTask(int taskid) { var taskType = string.Empty; var createEmp = string.Empty; using (var con = GlobalVar.ConnectionString.NewSqlConnection()) using (var cmd = con.CreateCommand()) { con.Open(); cmd.CommandText = @" UPDATE u_task_log SET status = 1, start_time = GETDATE() WHERE taskid = @taskid AND run_mode = 2 AND status = 0"; cmd.Parameters.Clear(); cmd.Parameters.AddWithValue("@taskid", taskid); if (cmd.ExecuteNonQuery() == 0) return; cmd.CommandText = "SELECT task_type, create_emp FROM u_task_log WHERE taskid = @taskid"; cmd.Parameters.Clear(); cmd.Parameters.AddWithValue("@taskid", taskid); using (var reader = cmd.ExecuteReader()) { if (reader.Read()) { taskType = Convert.ToString(reader["task_type"]); createEmp = Convert.ToString(reader["create_emp"]); } } } var success = 0; var fail = 0; var taskTypeName = GetTaskTypeName(taskType); var log = new StringBuilder(); foreach (var item in GetPendingItems(taskid)) { var errMsg = string.Empty; var isSuccess = false; using (var con = GlobalVar.ConnectionString.NewSqlConnection()) using (var cmd = con.CreateCommand()) { con.Open(); using (cmd.Transaction = con.BeginTransaction()) { try { UpdateItemRunning(cmd, taskid, item.printid); ExecuteOne(cmd, taskType, createEmp, item); UpdateItemResult(cmd, taskid, item.printid, 2, string.Empty); cmd.Transaction.Commit(); isSuccess = true; } catch (Exception ex) { cmd.Transaction.Rollback(); errMsg = ex.Message; Trace.Write(ex); } } } if (isSuccess) { success++; log.AppendLine($"任务类型:{taskTypeName} 单据:{item.biz_code} 执行成功"); } else { fail++; SaveItemFail(taskid, item.printid, errMsg); log.AppendLine($"任务类型:{taskTypeName} 单据:{item.biz_code} 执行失败,错误:{errMsg}"); } UpdateTaskProgress(taskid, success, fail); } FinishTask(taskid, success, fail, log.ToString()); } private void ExecuteOne(SqlCommand cmd, string taskType, string createEmp, u_schedule_task_mx item) { if (taskType == TaskTypeMattressRecalc) { var helper = HelperBase.GetHelper(cmd, new HelperBase.Context { tokendata = new TokenData { username = createEmp }, opdate = DateTime.Now }); helper.RecalculateOne(new u_mattress { mattressid = item.biz_id }); return; } throw new NotSupportedException("Unsupported task type:" + taskType); } private List GetPendingItems(int taskid) { var list = new List(); using (var con = GlobalVar.ConnectionString.NewSqlConnection()) using (var cmd = con.CreateCommand()) { con.Open(); cmd.CommandText = @" SELECT taskid, printid, biz_id, biz_code, biz_name, request_json FROM u_task_log_mx WHERE taskid = @taskid AND status = 0 ORDER BY printid"; cmd.Parameters.Clear(); cmd.Parameters.AddWithValue("@taskid", taskid); using (var reader = cmd.ExecuteReader()) { while (reader.Read()) { list.Add(new u_schedule_task_mx { taskid = Convert.ToInt32(reader["taskid"]), printid = Convert.ToInt32(reader["printid"]), biz_id = Convert.ToInt32(reader["biz_id"]), biz_code = Convert.ToString(reader["biz_code"]), biz_name = Convert.ToString(reader["biz_name"]), request_json = Convert.ToString(reader["request_json"]) }); } } } return list; } private void UpdateItemRunning(SqlCommand cmd, int taskid, int printid) { cmd.CommandText = @" UPDATE u_task_log_mx SET status = 1, start_time = GETDATE(), err_msg = '' WHERE taskid = @taskid AND printid = @printid"; cmd.Parameters.Clear(); cmd.Parameters.AddWithValue("@taskid", taskid); cmd.Parameters.AddWithValue("@printid", printid); cmd.ExecuteNonQuery(); } private void UpdateItemResult(SqlCommand cmd, int taskid, int printid, int status, string errMsg) { cmd.CommandText = @" UPDATE u_task_log_mx SET status = @status, err_msg = @err_msg, start_time = ISNULL(start_time, GETDATE()), end_time = GETDATE() WHERE taskid = @taskid AND printid = @printid"; cmd.Parameters.Clear(); cmd.Parameters.AddWithValue("@status", status); cmd.Parameters.AddWithValue("@err_msg", Limit(errMsg, 4000)); cmd.Parameters.AddWithValue("@taskid", taskid); cmd.Parameters.AddWithValue("@printid", printid); cmd.ExecuteNonQuery(); } private void SaveItemFail(int taskid, int printid, string errMsg) { using (var con = GlobalVar.ConnectionString.NewSqlConnection()) using (var cmd = con.CreateCommand()) { con.Open(); UpdateItemResult(cmd, taskid, printid, 3, errMsg); } } private void UpdateTaskProgress(int taskid, int success, int fail) { using (var con = GlobalVar.ConnectionString.NewSqlConnection()) using (var cmd = con.CreateCommand()) { con.Open(); cmd.CommandText = @" UPDATE u_task_log SET success_count = @success_count, fail_count = @fail_count WHERE taskid = @taskid"; cmd.Parameters.Clear(); cmd.Parameters.AddWithValue("@success_count", success); cmd.Parameters.AddWithValue("@fail_count", fail); cmd.Parameters.AddWithValue("@taskid", taskid); cmd.ExecuteNonQuery(); } } private void FinishTask(int taskid, int success, int fail, string logMsg) { using (var con = GlobalVar.ConnectionString.NewSqlConnection()) using (var cmd = con.CreateCommand()) { con.Open(); cmd.CommandText = @" UPDATE u_task_log SET status = @status, success_count = @success_count, fail_count = @fail_count, log_msg = @log_msg, end_time = GETDATE() WHERE taskid = @taskid"; cmd.Parameters.Clear(); cmd.Parameters.AddWithValue("@status", fail > 0 && success > 0 ? 4 : (fail > 0 ? 3 : 2)); cmd.Parameters.AddWithValue("@success_count", success); cmd.Parameters.AddWithValue("@fail_count", fail); cmd.Parameters.AddWithValue("@log_msg", logMsg ?? string.Empty); cmd.Parameters.AddWithValue("@taskid", taskid); cmd.ExecuteNonQuery(); } } private string Limit(string value, int maxLength) { return LimitValue(value, maxLength); } private static string LimitValue(string value, int maxLength) { if (string.IsNullOrEmpty(value)) return string.Empty; return value.Length <= maxLength ? value : value.Substring(0, maxLength); } } }