/// <summary> /// 停止或者暂停项目 /// </summary> /// <param name="jobname"></param> /// <returns></returns> public string PauseOrRestartJob(string jobname) { try { using (var connection = JobStorage.Current.GetConnection()) { Dictionary <string, string> dictionary = connection.GetAllEntriesFromHash("recurring-job:" + jobname); if (dictionary == null || dictionary.Count == 0) { return("not found recurring-job:" + jobname); } if (!dictionary.TryGetValue(nameof(Job), out var jobDetail)) { return("not found recurring-job:" + jobname); } var RecurringJob = InvocationData.DeserializePayload(jobDetail).DeserializeJob(); var job = CodingUtil.FromJson <HttpJobItem>(RecurringJob.Args.FirstOrDefault()?.ToString()); if (job == null) { return("fail parse recurring-job:" + jobname); } using (var tran = connection.CreateWriteTransaction()) { //拿到所有的设置 var conts = connection.GetAllItemsFromSet($"JobPauseOf:{jobname}"); //有就先清掉 foreach (var pair in conts) { tran.RemoveFromSet($"JobPauseOf:{jobname}", pair); } var cron = conts.FirstOrDefault(r => r.StartsWith("Cron:")); if (!string.IsNullOrEmpty(cron)) { cron = cron.Replace("Cron:", ""); } //如果包含有true 的 说明已经设置了 暂停 要把改成 启动 并且拿到 Cron 进行更新 if (conts.Contains("true")) { tran.AddToSet($"JobPauseOf:{jobname}", "false"); if (!string.IsNullOrEmpty(cron)) { job.Cron = cron; AddHttprecurringjob(job); } } else { tran.AddToSet($"JobPauseOf:{jobname}", "true"); tran.AddToSet($"JobPauseOf:{jobname}", "Cron:" + job.Cron); job.Cron = ""; AddHttprecurringjob(job); } tran.Commit(); } } return(string.Empty); } catch (Exception ex) { Logger.ErrorException("HttpJobDispatcher.PauseOrRestartJob", ex); return(ex.Message); } }
private static void OnVerify(object state) { mDetectionTimer.Change(-1, -1); try { using (var connection = JobStorage.Current.GetConnection()) using (var lockStorage = connection.AcquireDistributedLock("JobAgentServer", TimeSpan.FromSeconds(30)))//防止多个server端竞争 { //拿到有上报的jobId集合 var jobIdList = connection.GetAllItemsFromSet(keyPrefix); if (!jobIdList.Any()) { return; } foreach (var jobId in jobIdList) { JobData jobData = connection.GetJobData(jobId); //拿到真正的运行结果 var hashKey = keyPrefix + jobId; var result = connection.GetAllEntriesFromHash(hashKey); using (var tran = connection.CreateWriteTransaction()) { //job已经不存在了 就直接删除set if (jobData == null) { tran.RemoveFromSet(keyPrefix, jobId); tran.Commit(); continue; } double totalMilliseconds = (DateTime.UtcNow - jobData.CreatedAt).TotalMilliseconds; long latency = (long)totalMilliseconds; //如果job存在 但是没有拿到hash数据 认为成功 if (result == null || !result.Any()) { tran.SetJobState(jobId, new SucceededState(jobId, latency, latency)); tran.RemoveFromSet(keyPrefix, jobId); tran.RemoveHash(hashKey); tran.Commit(); continue; } var resultOfAgent = result.First(); JobAgentResult resultData = CodingUtil.FromJson <JobAgentResult>(resultOfAgent.Value); //异常数据 认为成功 if (resultData == null) { tran.SetJobState(jobId, new SucceededState(jobId, latency, latency)); tran.RemoveFromSet(keyPrefix, jobId); tran.RemoveHash(hashKey); tran.Commit(); continue; } //jobagent实际上运行的时长 long.TryParse(resultOfAgent.Key, out var realTotalMilliseconds); if (realTotalMilliseconds < 1) { realTotalMilliseconds = latency; } var isSuccess = resultData.R == "ok"; tran.RemoveFromSet(keyPrefix, jobId); tran.RemoveHash(hashKey); // latency 代表的是 从开始调度 到 实际结束 总共的时长 // realTotalMilliseconds 代表的是 jobagent开始执行 到 实际结束的 总共的时长 if (isSuccess) { var currentState = connection.GetStateData(jobId); if (currentState != null && !string.IsNullOrEmpty(currentState.Name) && currentState.Name.Equals("Failed")) { tran.AddJobState(jobId, new SucceededState(null, latency, realTotalMilliseconds)); } else { new BackgroundJobClient().ChangeState(jobId, new SucceededState(null, latency, realTotalMilliseconds)); } } else { var jobItem = jobData.Job.Args.FirstOrDefault() as HttpJobItem; var ex = new AgentJobException(jobItem.AgentClass, resultData.E); new BackgroundJobClient().ChangeState(jobId, new FailedState(ex)); HttpJob.SendFail(jobId, jobItem, "AgentJobFail", ex); } //如果是stop上报过来的时候 记录这个job最后的执行id if (!string.IsNullOrEmpty(resultData.Action) && resultData.Action.Equals("stop") && !string.IsNullOrEmpty(resultData.RunId)) { var jobItem = jobData.Job.Args.FirstOrDefault() as HttpJobItem; var jobKeyName = $"recurring-job:{(!string.IsNullOrEmpty(jobItem.RecurringJobIdentifier) ? jobItem.RecurringJobIdentifier : jobItem.JobName)}"; tran.SetRangeInHash(jobKeyName, new List <KeyValuePair <string, string> > { new KeyValuePair <string, string>("LastJobId", resultData.RunId) }); } //出错的话 需要走通用的出错流程 tran.Commit(); } } } } catch (Exception e) { Logger.ErrorException("agent reporter fail", e); } finally { mDetectionTimer.Change(1000 * 2, 1000 * 2); } }