Example #1
0
        public void Execute(IJobExecutionContext context)
        {
            try
            {
                JobInfo jobInfo = context.JobDetail.JobDataMap.Get("jobInfo") as JobInfo ?? new JobInfo();
                //从job池中查找逻辑job
                JobRuntimeInfo jobRuntimeInfo = SchedulerManager.Singleton.GetJobFromPool(jobInfo.Id);

                try
                {
                    if (jobRuntimeInfo != null)
                    {
                        try
                        {
                            bool runRes = jobRuntimeInfo.Job.Run();
                            if (runRes == false)
                            {
                                Exception ex = new Exception("作业内部发生异常");
                                LogWriter.WriteLog(ex, $"作业名称 : {jobInfo.JobName}");
                            }
                        }
                        //如果因为某种原因 appdomain 被卸载会进入catch块,重新创建 appdomain
                        catch (AppDomainUnloadedException ex)
                        {
                            LogWriter.WriteLog(ex, "appdomain 被卸载,准备重新加载");
                            SchedulerManager.Singleton.ReplaceJobRuntimeInfo(jobRuntimeInfo);
                        }
                    }
                    //如果job池没有该job
                    //TODO:注意,逻辑走到这里一般都是宕机了,因为job池是在内存中,所以重启调度服务后,肯定是没有的.而jobDetail和trigger是在数据库中,用的是官方的持久化方案.
                    else
                    {
                        try
                        {
                            bool creRes = SchedulerManager.Singleton.CreateJob(jobInfo);
                            //重新创建job成功后,需要手动执行一次.
                            if (creRes == true)
                            {
                                jobRuntimeInfo = SchedulerManager.Singleton.GetJobFromPool(jobInfo.Id);
                                jobRuntimeInfo.Job.Run();
                            }
                        }
                        catch (Exception ex)
                        {
                            LogWriter.WriteLog(ex, $"重新创建job失败:{JsonConvert.SerializeObject(jobInfo)}");
                        }
                    }
                }
                catch (Exception ex)
                {
                    //写日志,job调用失败,或者job执行的wcf程序抛出异常
                    LogWriter.WriteLog(ex, $"job执行失败 : {JsonConvert.SerializeObject(jobInfo)}");
                }
            }
            catch (Exception ex)
            {
                //TODO:调用的时候失败属于系统级错误,非常重要,写日志!
                LogWriter.WriteLog(ex, $"系统级错误,{nameof(Execute)}");
            }
        }
Example #2
0
 /// <summary>
 /// 更换版本
 /// </summary>
 /// <param name="jobInfo"></param>
 /// <returns></returns>
 public bool Upgrade(JobInfo jobInfo)
 {
     lock (Locker)
     {
         Remove(jobInfo);
         JobRuntimeInfo jobRuntimeInfo = CreateJobRuntimeInfo(jobInfo);
         return(Add(jobRuntimeInfo));
     }
 }
Example #3
0
        /// <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:记录日志
            }
        }
Example #4
0
        /// <summary>
        /// job池没有该job时,创建 job,并开始调度
        /// TODO:注意,虽然job池没有该job,但是trigger和jobDetail是有的
        /// </summary>
        /// <param name="jobInfo"></param>
        public bool CreateJob(JobInfo jobInfo)
        {
            if (jobInfo == null)
            {
                return(false);
            }
            if (JobPool.ContainsKey(jobInfo.Id))
            {
                return(false);
            }
            lock (Locker)
            {
                if (JobPool.ContainsKey(jobInfo.Id))
                {
                    return(false);
                }

                JobRuntimeInfo jobRuntimeInfo = CreateJobRuntimeInfo(jobInfo);
                return(Add(jobRuntimeInfo));
            }
        }
Example #5
0
 /// <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);
     }
 }
Example #6
0
        /// <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);
            }
        }
Example #7
0
        /// <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;
                }
            }
        }