/// <summary> /// 恢复job /// </summary> /// <param name="jobInfo"></param> public bool Resume(JobInfo jobInfo) { //TODO:这里有两种可能 /* * 1.调度服务正常状态时恢复 * 2.调度服务挂了,重启之后,恢复job.这种情况,job池是没有job的.但是jobDetail和trigger是有的,因为我们采用的是持久化调度器,因此要特殊处理.很重要 * */ lock (Locker) { //这是第2种情况,job池没有job,属于暂停后,宕机 JobRuntimeInfo jobRuntimeInfo = null; if (!JobPool.ContainsKey(jobInfo.Id)) { //如果调度任务中没有该jobDetail,那么直接返回 IJobDetail jobDetail = GetJobDetail(jobInfo, out JobKey jobKey); if (jobDetail == null) { return(false); } jobRuntimeInfo = CreateJobRuntimeInfo(jobInfo); //如果该job实例添加失败,卸载appdomain,然后返回. if (!JobPool.TryAdd(jobInfo.Id, jobRuntimeInfo)) { AppDomainLoader.UnLoad(jobRuntimeInfo.AppDomain); return(false); } else { //添加成功后,和下面那种情况一起操作了. } } //job池有job,这属于正常恢复,走下面的逻辑. //如果调度任务中没有该jobDetail 的 trigger,那么直接返回 ITrigger trigger = GetTrigger(jobInfo, out TriggerKey triKey); if (trigger == null) { return(false); } Scheduler.ResumeTrigger(triKey).Wait(); return(true); //TODO:记录日志 } }
/// <summary> /// 创建新的应用程序域,返回运行时的Job数据 /// </summary> /// <param name="jobInfo"></param> internal JobRuntimeInfo CreateJobRuntimeInfo(JobInfo jobInfo) { lock (Locker) { //JobRuntimeInfo jobRuntimeInfo = null; //if (JobPool.ContainsKey(jobInfo.Id)) //{ // jobRuntimeInfo = GetJobFromPool(jobInfo.Id); // return jobRuntimeInfo; //} AppDomain app = Thread.GetDomain(); BaseJob.BaseJob job = AppDomainLoader.Load(jobInfo.AssemblyPath, jobInfo.ClassType, out app); JobRuntimeInfo jobRuntimeInfo = new JobRuntimeInfo { JobInfo = jobInfo, Job = job, AppDomain = app, }; //TODO:日志记录 return(jobRuntimeInfo); } }
/// <summary> /// 线程池有job,但是该job的应用程序域已经卸载(一般都是宕机),替换job池中的jobRuntimeInfo,并重新调度该job /// </summary> /// <param name="jobRuntimeInfo"></param> /// <returns></returns> internal bool ReplaceJobRuntimeInfo(JobRuntimeInfo jobRuntimeInfo) { //TODO:有BUG,没有地方还原 _flag 的值 //if (_flag) //{ // return true; //} lock (Locker) { //if (_flag) //{ // return true; //} AppDomain app = Thread.GetDomain(); jobRuntimeInfo.Job = AppDomainLoader.Load(jobRuntimeInfo.JobInfo.AssemblyPath, jobRuntimeInfo.JobInfo.ClassType, out app); jobRuntimeInfo.AppDomain = app; JobPool[jobRuntimeInfo.JobInfo.Id] = jobRuntimeInfo; //_flag = true; return(true); } }
/// <summary> /// 从job池中移除某个job,同时卸载该job所在的AppDomain /// </summary> /// <param name="jobInfo"></param> /// <returns></returns> public bool Remove(JobInfo jobInfo) { lock (Locker) { ITrigger trigger = GetTrigger(jobInfo, out TriggerKey triKey); if (trigger == null) { return(true); } Scheduler.PauseTrigger(triKey); Scheduler.UnscheduleJob(triKey); Scheduler.DeleteJob(GetJobKey(jobInfo)); if (JobPool.ContainsKey(jobInfo.Id)) { JobPool.TryRemove(jobInfo.Id, out JobRuntimeInfo jobRuntimeInfo); AppDomainLoader.UnLoad(jobRuntimeInfo.AppDomain); } return(true); //TODO:记录日志 } }
/// <summary> /// 添加job到job池,同时加入到调度任务中. /// </summary> /// <param name="jobRuntimeInfo"></param> /// <returns></returns> internal bool Add(JobRuntimeInfo jobRuntimeInfo) { lock (Locker) { try { //如果该job实例添加失败,卸载该job的appdomain,然后返回. if (!JobPool.TryAdd(jobRuntimeInfo.JobInfo.Id, jobRuntimeInfo)) { AppDomainLoader.UnLoad(jobRuntimeInfo.AppDomain); return(false); } //如果调度任务中已经有该jobDetail,则直接删掉 IJobDetail jobDetail = GetJobDetail(jobRuntimeInfo.JobInfo, out JobKey jobKey); if (jobDetail != null) { Scheduler.DeleteJob(jobKey).Wait(); } jobDetail = CreateJobDetail(jobRuntimeInfo.JobInfo); ITrigger trigger = CreateTrigger(jobRuntimeInfo.JobInfo); Scheduler.ScheduleJob(jobDetail, trigger).Wait(); //TODO:记录日志 return(true); } catch (Exception ex) { //异常了,直接从job池移除该job,不再考虑移除失败的情况.考虑不到那么多了 if (JobPool.TryRemove(jobRuntimeInfo.JobInfo.Id, out JobRuntimeInfo jri)) { //成功移除后,再卸载掉应用程序域,失败则不移除,保留. AppDomainLoader.UnLoad(jobRuntimeInfo.AppDomain); } throw ex; } } }