public void RemoveSchedule(Schedule schedule) { var triggerKey = new TriggerKey(schedule.Id.ToString(), schedule.CommandId.ToString()); var jobKey = new JobKey(schedule.Id.ToString(), schedule.CommandId.ToString()); scheduler.UnscheduleJob(triggerKey); scheduler.DeleteJob(jobKey); }
public JobInfo(JobKey id, JobDetailImpl job) { Id = id; Job = job; Triggers = new TriggerInfo[0]; TriggerCount = 0; }
public void ShouldDisposeScopeAfterJobCompletion() { var key = new JobKey("disposable", "grp2"); var job1 = JobBuilder.Create<SampleJob>().WithIdentity(key).StoreDurably(true) .Build(); var trigger = TriggerBuilder.Create().WithSimpleSchedule(s => s.WithIntervalInSeconds(1).WithRepeatCount(1)).Build(); var scopesCreated = 0; var scopesDisposed = 0; DisposableDependency dependency = null; _lifetimeScope.ChildLifetimeScopeBeginning += (sender, args) => { scopesCreated++; dependency = args.LifetimeScope.Resolve<DisposableDependency>(); args.LifetimeScope.CurrentScopeEnding += (o, eventArgs) => { scopesDisposed++; }; }; _scheduler.ScheduleJob(job1, trigger); _scheduler.Start(); Thread.Sleep(3.Seconds()); _jobFactory.RunningJobs.Should().BeEmpty("Scope was not disposed after job completion"); dependency.Disposed.Should().BeTrue("Dependency must be disposed"); scopesDisposed.Should().Be(scopesCreated, "All scopes must be disposed"); }
public static void ScheduleJob(this IScheduler scheduler, JobKey jobKey, string scheduleText, TimeZoneInfo timeZone) { TextToScheduleFactory factory = new TextToScheduleFactory(); var english = factory.CreateEnglishParser(); var results = english.Parse(scheduleText, timeZone); results.ScheduleWithJobKey(scheduler, jobKey); }
public JobSchedule GetSchedule() { var jobKey = new JobKey(JobName, JobGroup); var trigger = Instance.GetTriggersOfJob(jobKey).FirstOrDefault(); var js = new JobSchedule(); if (trigger != null) { js.Name = trigger.Key.Name; js.Group = trigger.Key.Group; js.Description = trigger.Description; js.Priority = trigger.Priority; js.TriggerType = trigger.GetType().Name; js.TriggerState = Instance.GetTriggerState(trigger.Key).ToString(); DateTimeOffset? startTime = trigger.StartTimeUtc; js.StartTime = TimeZone.CurrentTimeZone.ToLocalTime(startTime.Value.DateTime); var nextFireTime = trigger.GetNextFireTimeUtc(); if (nextFireTime.HasValue) { js.NextFire = TimeZone.CurrentTimeZone.ToLocalTime(nextFireTime.Value.DateTime); } var previousFireTime = trigger.GetPreviousFireTimeUtc(); if (previousFireTime.HasValue) { js.LastFire = TimeZone.CurrentTimeZone.ToLocalTime(previousFireTime.Value.DateTime); } } return js; }
public void ExceptionPolicyNoRestartImmediately() { sched.Start(); JobKey jobKey = new JobKey("ExceptionPolicyNoRestartJob", "ExceptionPolicyNoRestartGroup"); JobDetailImpl exceptionJob = new JobDetailImpl(jobKey.Name, jobKey.Group, typeof (ExceptionJob)); exceptionJob.Durable = true; sched.AddJob(exceptionJob, false); ExceptionJob.ThrowsException = true; ExceptionJob.Refire = false; ExceptionJob.UnscheduleAllTriggers = false; ExceptionJob.UnscheduleFiringTrigger = false; ExceptionJob.LaunchCount = 0; sched.TriggerJob(jobKey); int i = 10; while ((i > 0) && (ExceptionJob.LaunchCount <= 1)) { i--; Thread.Sleep(200); if (ExceptionJob.LaunchCount > 1) { break; } } sched.DeleteJob(jobKey); Assert.AreEqual(1, ExceptionJob.LaunchCount, "The job should NOT have been refired after exception"); }
public void JobDeleted(JobKey jobKey) { foreach (ISchedulerListener listener in listeners) { listener.JobDeleted(jobKey); } }
public void AddRepeatingJob(Type aType, string aName, string aGroup, int aSecondsToSleep, params JobItem[] aItems) { JobKey key = new JobKey(aName, aGroup); if (Scheduler.GetJobDetail(key) != null) { Log.Error("AddRepeatingJob(" + aType.Name + ", " + aName + ", " + aGroup + ") already exists"); return; } Log.Info("AddRepeatingJob(" + aType.Name + ", " + aName + ", " + aGroup + ", " + aSecondsToSleep + ")"); _scheduledJobs.Add(key); var data = new JobDataMap(); foreach (JobItem item in aItems) { data.Add(item.Key, item.Value); } IJobDetail job = JobBuilder.Create(aType) .WithIdentity(key) .UsingJobData(data) .Build(); ITrigger trigger = TriggerBuilder.Create() .WithIdentity(aName, aGroup) .WithSimpleSchedule(x => x.WithIntervalInSeconds(aSecondsToSleep).RepeatForever()) .Build(); Scheduler.ScheduleJob(job, trigger); }
public JobDetailsData GetJobDetailsData(JobKey jobKey) { var scheduler = _schedulerProvider.Scheduler; if (scheduler.IsShutdown) { return null; } var job = scheduler.GetJobDetail(jobKey); if (job == null) { return null; } var detailsData = new JobDetailsData { PrimaryData = GetJobData(scheduler, jobKey) }; foreach (var key in job.JobDataMap.Keys) { detailsData.JobDataMap.Add(key, job.JobDataMap[key]); } detailsData.JobProperties.Add("Description", job.Description); detailsData.JobProperties.Add("Full name", job.Key.Name); detailsData.JobProperties.Add("Job type", job.JobType); detailsData.JobProperties.Add("Durable", job.Durable); //detailsData.JobProperties.Add("Volatile", job.); return detailsData; }
public object Deserialize(global::MongoDB.Bson.IO.BsonReader bsonReader, Type nominalType, Type actualType, IBsonSerializationOptions options) { if (nominalType != typeof(JobKey) || actualType != typeof(JobKey)) { var message = string.Format("Can't deserialize a {0} from {1}.", nominalType.FullName, this.GetType().Name); throw new BsonSerializationException(message); } var bsonType = bsonReader.CurrentBsonType; if (bsonType == BsonType.Document) { JobKey item; bsonReader.ReadStartDocument(); item = new JobKey( bsonReader.ReadString("Name"), bsonReader.ReadString("Group")); bsonReader.ReadEndDocument(); return item; } else if (bsonType == BsonType.Null) { bsonReader.ReadNull(); return null; } else { var message = string.Format("Can't deserialize a {0} from BsonType {1}.", nominalType.FullName, bsonType); throw new BsonSerializationException(message); } }
public HttpResponseMessage PostTriggerJob(string id) { JobKey jobKey = new JobKey(id); _scheduler.TriggerJob(jobKey); return new HttpResponseMessage(); }
private static IEnumerable<TriggerWithState> GetTriggers(ISchedulerWrapper scheduler, JobKey jobKey) { var triggers = scheduler.GetTriggersOfJob(jobKey); if (triggers == null) return null; return triggers.Select(t => { var state = scheduler.GetTriggerState(t.Key); return new TriggerWithState(t, state); }); }
public JobModel(IScheduler scheduler, JobKey jobKey) { foreach (ITrigger trigger in scheduler.GetTriggersOfJob(jobKey)) { _triggersForJob.Add(new TriggerModel(trigger)); } MapValuesFromJobDetail(scheduler.GetJobDetail(jobKey)); }
private bool IsBelongsToGroup(JobKey jobKey) { var jobDetail = _scheduler.GetJobDetail(jobKey); if (jobDetail.JobDataMap == null || !jobDetail.JobDataMap.Contains("data")) return false; var data = JsonConvert.DeserializeObject<SendCreativePackagesWithIntervalTask.Data>((string) jobDetail.JobDataMap["data"]); return data.Group == Group; }
/// <summary> /// 删除现有任务 /// </summary> /// <param name="JobKey"></param> public static void DeleteJob(string JobKey) { JobKey jk = new JobKey(JobKey); if (scheduler.CheckExists(jk)) { //任务已经存在则删除 scheduler.DeleteJob(jk); LogHelper.WriteLog(string.Format("任务“{0}”已经删除", JobKey)); } }
private static ICronTrigger CreateTrigger(DepotSchedule depotSchedule, Depot depot, JobKey jobKey) { var expression = CronExpressionConverter.ConvertToCronExpression(depotSchedule.DaysOfTheWeek, depotSchedule.Hour, depotSchedule.Minutes); //This is for debugging purposes //var result = CronExpression.IsValidExpression(expression); var timezone = TimeZoneInfo.GetSystemTimeZones().Single(tz => tz.Id == depot.TimeZoneId); var cronScheduleBuilder = CronScheduleBuilder.CronSchedule(expression).InTimeZone(timezone).WithMisfireHandlingInstructionFireAndProceed(); return (ICronTrigger) TriggerBuilder.Create().ForJob(jobKey).WithSchedule(cronScheduleBuilder).Build(); }
public static Response Execute(RelativeUri url, Func<ISchedulerWrapper> getScheduler) { var scheduler = getScheduler(); var querystring = url.ParseQueryString(); var highlight = querystring["highlight"]; var group = querystring["group"]; var job = querystring["job"]; var jobKey = new JobKey(job, group); var triggers = GetTriggers(scheduler, jobKey); var m = new TriggersByJobModel(triggers, url.PathAndQuery, group, job, highlight); return new Response.XDocumentResponse(Helpers.XHTML(Views.Views.TriggersByJob(m))); }
/// <summary> /// Schedules the Triggers with a given job key. /// </summary> /// <param name="sched">The sched.</param> /// <param name="jobKey">The job key.</param> public void ScheduleWithJobKey(IScheduler sched, JobKey jobKey) { RegisterCalendars(sched); foreach (var group in RegisterGroups) { group.TriggerBuilder.ForJob(jobKey); ITrigger trigger = group.TriggerBuilder.Build(); sched.ScheduleJob(trigger); } }
public static void Execute(HttpContextBase context, Func<ISchedulerWrapper> getScheduler) { var scheduler = getScheduler(); var highlight = context.Request.QueryString["highlight"]; var group = context.Request.QueryString["group"]; var job = context.Request.QueryString["job"]; var jobKey = new JobKey(job, group); var triggers = GetTriggers(scheduler, jobKey); var thisUrl = context.Request.RawUrl; var m = new TriggersByJobModel(triggers, thisUrl, group, job, highlight); context.Response.Html(Helpers.XHTML(Views.Views.TriggersByJob(m))); }
/// <summary> /// 删除 /// </summary> /// <param name="scheduler"></param> /// <param name="dellist"></param> public static void deleteJob(Quartz.IScheduler scheduler, List<Config> dellist) { IList<JobKey> jlist = new List<Quartz.JobKey>(); foreach (var it in dellist) { JobKey key = new JobKey(it.jobname, it.groupname); jlist.Add(key); } scheduler.DeleteJobs(jlist); }
/// <summary> /// Add a chain mapping - when the Job identified by the first key completes /// the job identified by the second key will be triggered. /// </summary> /// <param name="firstJob">a JobKey with the name and group of the first job</param> /// <param name="secondJob">a JobKey with the name and group of the follow-up job</param> public void AddJobChainLink(JobKey firstJob, JobKey secondJob) { if (firstJob == null || secondJob == null) { throw new ArgumentException("Key cannot be null!"); } if (firstJob.Name == null || secondJob.Name == null) { throw new ArgumentException("Key cannot have a null name!"); } chainLinks.Add(firstJob, secondJob); }
private void ScheduleGreetingJob() { var key = new JobKey("GreetingJob"); var jobDetail = JobBuilder.Create<IGreetingJob>() .WithIdentity(key) .Build(); var trigger = TriggerBuilder.Create() .WithIdentity("GreetingTrigger") .StartAt(new DateTimeOffset(new DateTime(2016, 5, 5, 7, 45, 0))) .ForJob(jobDetail) .Build(); scheduler.ScheduleJob(jobDetail, trigger); }
public static void Execute(HttpContextBase context, Func<IScheduler> getScheduler) { var scheduler = getScheduler(); var group = context.Request.QueryString["group"]; var job = context.Request.QueryString["job"]; var jobKey = new JobKey(job, group); var thisUrl = context.Request.RawUrl; var triggers = scheduler.GetTriggersOfJob(jobKey) .Select(t => { var state = scheduler.GetTriggerState(t.Key); return new TriggerWithState(t, state); }); var highlight = context.Request.QueryString["highlight"]; var m = new TriggersByJobModel(triggers, thisUrl, group, job, highlight); context.Response.Html(Helpers.XHTML(Views.Views.TriggersByJob(m))); }
private void ScheduleAwardFinesFromReactionJob() { var key = new JobKey("AwardFinesFromReactionJob"); var jobDetail = JobBuilder.Create<IAwardFinesFromReactionJob>() .WithIdentity(key) .Build(); var trigger = TriggerBuilder.Create() .WithIdentity("AwardFinesFromReactionTrigger") //.StartNow() .StartAt(DateBuilder.TodayAt(18, 0, 0)) .WithSimpleSchedule(x => x .WithIntervalInHours(24) .RepeatForever()) .Build(); scheduler.ScheduleJob(jobDetail, trigger); }
/// <summary> /// 修改 /// </summary> /// <param name="scheduler"></param> /// <param name="modilist"></param> public static void modiJob(Quartz.IScheduler scheduler, List<Config> modilist) { // scheduler.GetTrigger(new TriggerKey( foreach (var item in modilist) { //var old = scheduler.GetTrigger(new TriggerKey(item.jobname + "trigger", "触发器组")); //if (old == null) // return; //var newtrigger = addTriger(item).Build(); //scheduler.RescheduleJob(old.Key, newtrigger); JobKey key = new JobKey(item.jobname, item.groupname); scheduler.DeleteJob(key); addjob(scheduler, item); } }
public void Start() { using (var context = new QuartzDbContext()) { var depots = context.Depots.ToList(); var schedules = context.DepotSchedules.ToList(); foreach (var depot in depots) { var schedule = schedules.Single(s => s.DepotId == depot.Id); var jobKey = new JobKey(depot.Id.ToString(), "Depot Supply Schedule"); var jobDetail = JobBuilder.Create<CustomJob>().WithIdentity(jobKey).Build(); var trigger = CreateTrigger(schedule, depot, jobKey); scheduler.ScheduleJob(jobDetail, trigger); } } Console.WriteLine("Job Has been Setup"); }
public object ExecuteJob(JobKey jobKey) { IJobDetail detail = Scheduler.GetJobDetail(jobKey); if (detail == null) { return null; } try { using (var instance = (CronshopJob) Activator.CreateInstance(detail.JobType)) { return instance.ExecuteJob(null); } } catch { return null; } }
public void ExceptionPolicyRestartImmediately() { sched.Start(); JobKey jobKey = new JobKey("ExceptionPolicyRestartJob", "ExceptionPolicyRestartGroup"); IJobDetail exceptionJob = JobBuilder.Create<ExceptionJob>() .WithIdentity(jobKey) .StoreDurably() .Build(); sched.AddJob(exceptionJob, false); ExceptionJob.ThrowsException = true; ExceptionJob.Refire = true; ExceptionJob.UnscheduleAllTriggers = false; ExceptionJob.UnscheduleFiringTrigger = false; ExceptionJob.LaunchCount = 0; sched.TriggerJob(jobKey); int i = 10; while ((i > 0) && (ExceptionJob.LaunchCount <= 1)) { i--; Thread.Sleep(200); if (ExceptionJob.LaunchCount > 1) { break; } } // to ensure job will not be refired in consequent tests // in fact, it would be better to have a separate class ExceptionJob.ThrowsException = false; Thread.Sleep(1000); sched.DeleteJob(jobKey); Thread.Sleep(1000); Assert.Greater(ExceptionJob.LaunchCount, 1, "The job should have been refired after exception"); }
/// <summary> /// Called by the <see cref="IScheduler" /> when a <see cref="ITrigger" /> /// fires that is associated with the <see cref="IJob" />. /// </summary> public virtual void Execute(IJobExecutionContext context) { jobKey = context.JobDetail.Key; log.InfoFormat("---- {0} executing at {1}", jobKey, DateTime.Now.ToString("r")); try { // main job loop... see the JavaDOC for InterruptableJob for discussion... // do some work... in this example we are 'simulating' work by sleeping... :) for (int i = 0; i < 4; i++) { try { Thread.Sleep(10 * 1000); } catch (Exception ignore) { Console.WriteLine(ignore.StackTrace); } // periodically check if we've been interrupted... if (interrupted) { log.InfoFormat("--- {0} -- Interrupted... bailing out!", jobKey); return ; // could also choose to throw a JobExecutionException // if that made for sense based on the particular // job's responsibilities/behaviors } } } finally { log.InfoFormat("---- {0} completed at {1}", jobKey, DateTime.Now.ToString("r")); } }
/// <summary> /// Calls the equivalent method on the 'proxied' <see cref="QuartzScheduler" />. /// </summary> public virtual Task <IReadOnlyList <ITrigger> > GetTriggersOfJob(JobKey jobKey) { return(CallInGuard(x => x.GetTriggersOfJob(jobKey))); }
/// <summary> /// 添加一个工作调度 /// </summary> /// <param name="entity"></param> /// <returns></returns> public async Task <ResultValue> AddScheduleJobAsync(ScheduleEntity entity) { var result = new ResultValue(); try { //检查任务是否已存在 var jobKey = new JobKey(entity.JobName, entity.JobGroup); if (await Scheduler.CheckExists(jobKey)) { result.MsgCode = 3; result.Msg = "任务已存在"; return(result); } ////加载程序集(dll文件地址),使用Assembly类 //var asstypes = Assembly.Load("BusDataExchan").GetTypes() // .Where(t => t.GetInterfaces().Contains(typeof(IJob))) // .ToArray(); if (entity.TargetCall.IndexOf(",") < 0) { result.MsgCode = 3; result.Msg = "对象名称格式不符合Job-Type"; return(result); } var Assemblys = entity.TargetCall.Split(','); string dllname = Assemblys[1]; string jobname = Assemblys[0]; //获取类型,参数(名称空间+类) Type _ijob = null; try { _ijob = Assembly.Load(dllname).GetType(jobname); } catch (Exception err) { //日志err result.MsgCode = 3; result.Msg = "未找到描述的对象"; return(result); } //配置 var DataDir = new Dictionary <string, string>() { { Constant.TARGETCALL, entity.TargetCall }, { Constant.TARGETTYPE, entity.TargetType }, //{ Constant.MAILMESSAGE, ((int)entity.MailMessage).ToString()}, }; if (_ijob == null) { result.MsgCode = 3; result.Msg = "未找到调度器"; return(result); } // 定义这个工作,并将其绑定到我们的IJob实现类 IJobDetail job = JobBuilder.Create(_ijob) .SetJobData(new JobDataMap(DataDir)) .WithDescription(entity.Description) .WithIdentity(entity.JobName, entity.JobGroup) .Build(); // 创建触发器 ITrigger trigger; entity.TriggerType = TriggerTypeEnum.Cron; //校验是否正确的执行周期表达式 if (entity.TriggerType == TriggerTypeEnum.Cron)//CronExpression.IsValidExpression(entity.Cron)) { trigger = CreateCronTrigger(entity); } else { trigger = CreateSimpleTrigger(entity); } // 告诉Quartz使用我们的触发器来安排作业 await Scheduler.ScheduleJob(job, trigger); result.MsgCode = 1; result.Msg = "添加成功"; } catch (Exception ex) { result.MsgCode = 3; result.Msg = ex.Message; } return(result); }
public override void JobDeleted(JobKey jobKey) { }
/// <summary> /// Calls the equivalent method on the 'proxied' <see cref="QuartzScheduler" />. /// </summary> public virtual Task <bool> CheckExists(JobKey jobKey) { return(CallInGuard(x => x.CheckExists(jobKey))); }
/// <summary> /// Pause the <see cref="T:Quartz.IJobDetail"/> with the given /// key - by pausing all of its current <see cref="T:Quartz.ITrigger"/>s. /// </summary> public void PauseJob(JobKey jobKey) { _scheduler.PauseJob(jobKey); }
/// <summary> /// Trigger the identified <see cref="T:Quartz.IJobDetail"/> /// (Execute it now). /// </summary> public void TriggerJob(JobKey jobKey) { _scheduler.TriggerJob(jobKey); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddLogging(builder => { builder.AddFile(opts => opts.LogDirectory = LogFolderPath); }); services.AddOptions(); services.AddHealthChecks().AddCheck <DasBlogHealthChecks>("health_check"); services.AddMemoryCache(); services.Configure <TimeZoneProviderOptions>(Configuration); services.Configure <SiteConfig>(Configuration); services.Configure <MetaTags>(Configuration); services.AddSingleton <AppVersionInfo>(); services.Configure <ConfigFilePathsDataOption>(options => { options.SiteConfigFilePath = Path.Combine(hostingEnvironment.ContentRootPath, SiteConfigPath); options.MetaConfigFilePath = Path.Combine(hostingEnvironment.ContentRootPath, MetaConfigPath); options.SecurityConfigFilePath = Path.Combine(hostingEnvironment.ContentRootPath, SiteSecurityConfigPath); options.IISUrlRewriteFilePath = Path.Combine(hostingEnvironment.ContentRootPath, IISUrlRewriteConfigPath); options.ThemesFolder = ThemeFolderPath; options.BinaryFolder = BinariesPath; options.BinaryUrlRelative = string.Format("{0}/", BinariesUrlRelativePath); }); services.Configure <ActivityRepoOptions>(options => options.Path = LogFolderPath); //Important if you're using Azure, hosting on Nginx, or behind any reverse proxy services.Configure <ForwardedHeadersOptions>(options => { options.ForwardedHeaders = ForwardedHeaders.All; options.AllowedHosts = Configuration.GetValue <string>("AllowedHosts")?.Split(';').ToList <string>(); }); // Add identity types services .AddIdentity <DasBlogUser, DasBlogRole>() .AddDefaultTokenProviders(); services.Configure <IdentityOptions>(options => { // Password settings options.Password.RequireDigit = true; options.Password.RequiredLength = 8; options.Password.RequireNonAlphanumeric = false; options.Password.RequireUppercase = true; options.Password.RequireLowercase = false; options.Password.RequiredUniqueChars = 6; // Lockout settings options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30); options.Lockout.MaxFailedAccessAttempts = 10; options.Lockout.AllowedForNewUsers = true; // User settings options.User.RequireUniqueEmail = true; }); services.ConfigureApplicationCookie(options => { options.LoginPath = "/account/login"; // If the LoginPath is not set here, ASP.NET Core will default to /Account/Login options.LogoutPath = "/account/logout"; // If the LogoutPath is not set here, ASP.NET Core will default to /Account/Logout options.AccessDeniedPath = "/account/accessdenied"; // If the AccessDeniedPath is not set here, ASP.NET Core will default to /Account/AccessDenied options.SlidingExpiration = true; options.ExpireTimeSpan = TimeSpan.FromSeconds(10000); options.Cookie = new CookieBuilder { HttpOnly = true }; }); services.AddResponseCaching(); services.Configure <RazorViewEngineOptions>(rveo => { rveo.ViewLocationExpanders.Add(new DasBlogLocationExpander(Configuration.GetSection("Theme").Value)); }); services.AddSession(options => { options.IdleTimeout = TimeSpan.FromSeconds(1000); }); services .AddHttpContextAccessor(); services .AddTransient <IDasBlogSettings, DasBlogSettings>() .AddTransient <IUserStore <DasBlogUser>, DasBlogUserStore>() .AddTransient <IRoleStore <DasBlogRole>, DasBlogUserRoleStore>() .AddTransient <IPrincipal>(provider => provider.GetService <IHttpContextAccessor>().HttpContext.User) .AddTransient <ISiteRepairer, SiteRepairer>(); services.AddScoped <IRichEditBuilder>(SelectRichEditor) .AddScoped <IBlogPostViewModelCreator, BlogPostViewModelCreator>(); services .AddSingleton(hostingEnvironment.ContentRootFileProvider) .AddSingleton <IBlogManager, BlogManager>() .AddSingleton <IArchiveManager, ArchiveManager>() .AddSingleton <ICategoryManager, CategoryManager>() .AddSingleton <ISiteSecurityManager, SiteSecurityManager>() .AddSingleton <IXmlRpcManager, XmlRpcManager>() .AddSingleton <ISiteManager, SiteManager>() .AddSingleton <IHttpContextAccessor, HttpContextAccessor>() .AddSingleton <IFileSystemBinaryManager, FileSystemBinaryManager>() .AddSingleton <IUserDataRepo, UserDataRepo>() .AddSingleton <ISiteSecurityConfig, SiteSecurityConfig>() .AddSingleton <IUserService, UserService>() .AddSingleton <IActivityService, ActivityService>() .AddSingleton <IActivityRepoFactory, ActivityRepoFactory>() .AddSingleton <IEventLineParser, EventLineParser>() .AddSingleton <ITimeZoneProvider, TimeZoneProvider>() .AddSingleton <ISubscriptionManager, SubscriptionManager>() .AddSingleton <IConfigFileService <MetaTags>, MetaConfigFileService>() .AddSingleton <IConfigFileService <SiteConfig>, SiteConfigFileService>() .AddSingleton <IConfigFileService <SiteSecurityConfigData>, SiteSecurityConfigFileService>(); services .AddAutoMapper((serviceProvider, mapperConfig) => { mapperConfig.AddProfile(new ProfilePost(serviceProvider.GetService <IDasBlogSettings>())); mapperConfig.AddProfile(new ProfileDasBlogUser(serviceProvider.GetService <ISiteSecurityManager>())); mapperConfig.AddProfile(new ProfileSettings()); }) .AddMvc() .AddXmlSerializerFormatters(); services .AddControllersWithViews() .AddRazorRuntimeCompilation(); services.AddRecaptcha(options => { options.SiteKey = RecaptchaSiteKey; options.SecretKey = RecaptchaSecretKey; }); services.Configure <CookiePolicyOptions>(options => { bool.TryParse(Configuration.GetSection("CookieConsentEnabled").Value, out var flag); options.CheckConsentNeeded = context => flag; options.MinimumSameSitePolicy = SameSiteMode.None; }); services.AddQuartz(q => { q.SchedulerId = "Scheduler-Core"; q.UseMicrosoftDependencyInjectionJobFactory(options => { // if we don't have the job in DI, allow fallback to configure via default constructor options.AllowDefaultConstructor = true; }); q.UseSimpleTypeLoader(); q.UseInMemoryStore(); q.UseDefaultThreadPool(tp => { tp.MaxConcurrency = 10; }); var jobKey = new JobKey("key1", "main-group"); q.AddJob <SiteEmailReport>(j => j .StoreDurably() .WithIdentity(jobKey) .WithDescription("Site report job") ); q.AddTrigger(t => t .WithIdentity("Simple Trigger") .ForJob(jobKey) .StartNow() .WithSchedule(CronScheduleBuilder.DailyAtHourAndMinute(23, 45)) .WithDescription("my awesome simple trigger") ); }); services.AddQuartzServer(options => { options.WaitForJobsToComplete = true; }); }
/// <summary> /// Get all <see cref="T:Quartz.ITrigger"/> s that are associated with the /// identified <see cref="T:Quartz.IJobDetail"/>. /// </summary> /// <remarks> /// The returned Trigger objects will be snap-shots of the actual stored /// triggers. If you wish to modify a trigger, you must re-store the /// trigger afterward (e.g. see <see cref="M:Quartz.IScheduler.RescheduleJob(Quartz.TriggerKey,Quartz.ITrigger)"/>). /// </remarks> public IList <ITrigger> GetTriggersOfJob(JobKey jobKey) { return(_scheduler.GetTriggersOfJob(jobKey)); }
/// <summary> /// 立即执行 /// </summary> /// <param name="jobKey"></param> /// <returns></returns> public async Task <bool> TriggerJobAsync(JobKey jobKey) { await Scheduler.TriggerJob(jobKey); return(true); }
public Task JobDeleted(JobKey jobKey, CancellationToken cancellationToken = default(CancellationToken)) { return(Task.WhenAll(listeners.Select(l => l.JobDeleted(jobKey, cancellationToken)))); }
/// <summary> /// 获取job日志 /// </summary> /// <param name="jobKey"></param> /// <returns></returns> public async Task <List <string> > GetJobLogsAsync(JobKey jobKey) { var jobDetail = await Scheduler.GetJobDetail(jobKey); return(jobDetail.JobDataMap[Constant.LOGLIST] as List <string>); }
/// <summary> /// 添加一个计划任务(映射程序集指定IJob实现类) /// </summary> /// <typeparam name="T"></typeparam> /// <param name="tasksQz"></param> /// <returns></returns> public async Task <MessageModel <string> > AddScheduleJobAsync(TasksQz tasksQz) { var result = new MessageModel <string>(); if (tasksQz != null) { try { JobKey jobKey = new JobKey(tasksQz.Id.ToString(), tasksQz.JobGroup); if (await _scheduler.Result.CheckExists(jobKey)) { result.success = false; result.msg = $"该任务计划已经在执行:【{tasksQz.Name}】,请勿重复启动!"; return(result); } #region 设置开始时间和结束时间 if (tasksQz.BeginTime == null) { tasksQz.BeginTime = DateTime.Now; } DateTimeOffset starRunTime = DateBuilder.NextGivenSecondDate(tasksQz.BeginTime, 1);//设置开始时间 if (tasksQz.EndTime == null) { tasksQz.EndTime = DateTime.MaxValue.AddDays(-1); } DateTimeOffset endRunTime = DateBuilder.NextGivenSecondDate(tasksQz.EndTime, 1);//设置暂停时间 #endregion #region 通过反射获取程序集类型和类 Assembly assembly = Assembly.Load(new AssemblyName(tasksQz.AssemblyName)); Type jobType = assembly.GetType(tasksQz.AssemblyName + "." + tasksQz.ClassName); #endregion //判断任务调度是否开启 if (!_scheduler.Result.IsStarted) { await StartScheduleAsync(); } //传入反射出来的执行程序集 IJobDetail job = new JobDetailImpl(tasksQz.Id.ToString(), tasksQz.JobGroup, jobType); job.JobDataMap.Add("JobParam", tasksQz.JobParams); ITrigger trigger; #region 泛型传递 //IJobDetail job = JobBuilder.Create<T>() // .WithIdentity(sysSchedule.Name, sysSchedule.JobGroup) // .Build(); #endregion if (tasksQz.Cron != null && CronExpression.IsValidExpression(tasksQz.Cron) && tasksQz.TriggerType > 0) { trigger = CreateCronTrigger(tasksQz); ((CronTriggerImpl)trigger).MisfireInstruction = MisfireInstruction.CronTrigger.DoNothing; } else { trigger = CreateSimpleTrigger(tasksQz); } // 告诉Quartz使用我们的触发器来安排作业 await _scheduler.Result.ScheduleJob(job, trigger); //await Task.Delay(TimeSpan.FromSeconds(120)); //await Console.Out.WriteLineAsync("关闭了调度器!"); //await _scheduler.Result.Shutdown(); result.success = true; result.msg = $"启动任务:【{tasksQz.Name}】成功"; return(result); } catch (Exception ex) { result.success = false; result.msg = $"任务计划异常:【{ex.Message}】"; return(result); } } else { result.success = false; result.msg = $"任务计划不存在:【{tasksQz?.Name}】"; return(result); } }
/// <summary> /// 添加任务 /// </summary> /// <param name="entity"></param> /// <param name="start">是否立即启动</param> /// <returns></returns> private async Task <IResultModel> AddJob(TaskEntity entity, bool start = false) { var jobClassType = Type.GetType(entity.ClassName); if (jobClassType == null) { return(ResultModel.Failed($"任务类({entity.ClassName})不存在")); } var jobKey = new JobKey(entity.TaskCode, entity.Group); var job = JobBuilder.Create(jobClassType).WithIdentity(jobKey) .UsingJobData("id", entity.Id.ToString()).Build(); var triggerBuilder = TriggerBuilder.Create().WithIdentity(entity.TaskCode, entity.Group) .EndAt(entity.EndDate.ToUniversalTime()) .WithDescription(entity.TaskName); //如果开始日期小于等于当前日期则立即启动 if (entity.BeginDate <= DateTime.Now) { triggerBuilder.StartNow(); } else { triggerBuilder.StartAt(entity.BeginDate.ToUniversalTime()); } if (entity.TriggerType == 1) { //简单任务 triggerBuilder.WithSimpleSchedule(builder => { builder.WithIntervalInSeconds(entity.IntervalInSeconds); if (entity.RepeatCount > 0) { builder.WithRepeatCount(entity.RepeatCount - 1); } else { builder.RepeatForever(); } }); } else { if (!CronExpression.IsValidExpression(entity.Cron)) { return(ResultModel.Failed("CRON表达式无效")); } //CRON任务 triggerBuilder.WithCronSchedule(entity.Cron); } var trigger = triggerBuilder.Build(); try { await _quartzServer.AddJob(job, trigger); if (!start) { //先暂停 await _quartzServer.PauseJob(jobKey); } return(ResultModel.Success()); } catch (Exception ex) { _logger.LogError("任务调度添加任务失败{@ex}", ex); } return(ResultModel.Failed()); }
/// <summary> /// Request the interruption, within this Scheduler instance, of all /// currently executing instances of the identified <see cref="T:Quartz.IJob"/>, which /// must be an implementor of the <see cref="T:Quartz.IInterruptableJob"/> interface. /// </summary> /// <remarks> /// <para> /// If more than one instance of the identified job is currently executing, /// the <see cref="M:Quartz.IInterruptableJob.Interrupt"/> method will be called on /// each instance. However, there is a limitation that in the case that /// <see cref="M:Quartz.IScheduler.Interrupt(Quartz.JobKey)"/> on one instances throws an exception, all /// remaining instances (that have not yet been interrupted) will not have /// their <see cref="M:Quartz.IScheduler.Interrupt(Quartz.JobKey)"/> method called. /// </para> /// <para> /// If you wish to interrupt a specific instance of a job (when more than /// one is executing) you can do so by calling /// <see cref="M:Quartz.IScheduler.GetCurrentlyExecutingJobs"/> to obtain a handle /// to the job instance, and then invoke <see cref="M:Quartz.IScheduler.Interrupt(Quartz.JobKey)"/> on it /// yourself. /// </para> /// <para> /// This method is not cluster aware. That is, it will only interrupt /// instances of the identified InterruptableJob currently executing in this /// Scheduler instance, not across the entire cluster. /// </para> /// </remarks> /// <returns> /// true is at least one instance of the identified job was found and interrupted. /// </returns> /// <seealso cref="T:Quartz.IInterruptableJob"/><seealso cref="M:Quartz.IScheduler.GetCurrentlyExecutingJobs"/> public bool Interrupt(JobKey jobKey) { return(_scheduler.Interrupt(jobKey)); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddLogging(loggingBuilder => { loggingBuilder.ClearProviders(); loggingBuilder.AddSerilog(dispose: true); }); services.AddRazorPages(); // base configuration for DI services.AddQuartz(q => { // handy when part of cluster or you want to otherwise identify multiple schedulers q.SchedulerId = "Scheduler-Core"; // we take this from appsettings.json, just show it's possible // q.SchedulerName = "Quartz ASP.NET Core Sample Scheduler"; // hooks LibLog to Microsoft logging without allowing it to detect concrete implementation // if you are using NLog, SeriLog or log4net you shouldn't need this // LibLog will be removed in Quartz 4 and Microsoft Logging will become the default q.UseMicrosoftLogging(); // we could leave DI configuration intact and then jobs need to have public no-arg constructor // the MS DI is expected to produce transient job instances q.UseMicrosoftDependencyInjectionJobFactory(options => { // if we don't have the job in DI, allow fallback to configure via default constructor options.AllowDefaultConstructor = true; }); // or // q.UseMicrosoftDependencyInjectionScopedJobFactory(); // these are the defaults q.UseSimpleTypeLoader(); q.UseInMemoryStore(); q.UseDefaultThreadPool(tp => { tp.ThreadCount = 10; }); // configure jobs with code var jobKey = new JobKey("awesome job", "awesome group"); q.AddJob <ExampleJob>(j => j .StoreDurably() .WithIdentity(jobKey) .WithDescription("my awesome job") ); q.AddTrigger(t => t .WithIdentity("Simple Trigger") .ForJob(jobKey) .StartNow() .WithSimpleSchedule(x => x.WithInterval(TimeSpan.FromSeconds(10)).RepeatForever()) .WithDescription("my awesome simple trigger") ); q.AddTrigger(t => t .WithIdentity("Cron Trigger") .ForJob(jobKey) .StartAt(DateBuilder.EvenSecondDate(DateTimeOffset.UtcNow.AddSeconds(3))) .WithCronSchedule("0/3 * * * * ?") .WithDescription("my awesome cron trigger") ); q.AddTrigger(t => t .WithIdentity("Daily Trigger") .ForJob(jobKey) .StartAt(DateBuilder.EvenSecondDate(DateTimeOffset.UtcNow.AddSeconds(5))) .WithDailyTimeIntervalSchedule(x => x.WithInterval(10, IntervalUnit.Second)) .WithDescription("my awesome daily time interval trigger") ); // also add XML configuration and poll it for changes q.UseXmlSchedulingConfiguration(x => { x.Files = new[] { "~/quartz_jobs.config" }; x.ScanInterval = TimeSpan.FromSeconds(2); x.FailOnFileNotFound = true; x.FailOnSchedulingError = true; }); // convert time zones using converter that can handle Windows/Linux differences q.UseTimeZoneConverter(); // add some listeners q.AddSchedulerListener <SampleSchedulerListener>(); q.AddJobListener <SampleJobListener>(GroupMatcher <JobKey> .GroupEquals(jobKey.Group)); q.AddTriggerListener <SampleTriggerListener>(); // example of persistent job store using JSON serializer as an example /* * q.UsePersistentStore(s => * { * s.UseProperties = true; * s.RetryInterval = TimeSpan.FromSeconds(15); * s.UseSqlServer(sqlServer => * { * sqlServer.ConnectionString = "some connection string"; * // this is the default * sqlServer.TablePrefix = "QRTZ_"; * }); * s.UseJsonSerializer(); * s.UseClustering(c => * { * c.CheckinMisfireThreshold = TimeSpan.FromSeconds(20); * c.CheckinInterval = TimeSpan.FromSeconds(10); * }); * }); */ }); // ASP.NET Core hosting services.AddQuartzServer(options => { // when shutting down we want jobs to complete gracefully options.WaitForJobsToComplete = true; }); services .AddHealthChecksUI() .AddInMemoryStorage(); }
/// <summary> /// Get the <see cref="T:Quartz.IJobDetail"/> for the <see cref="T:Quartz.IJob"/> /// instance with the given key . /// </summary> /// <remarks> /// The returned JobDetail object will be a snap-shot of the actual stored /// JobDetail. If you wish to modify the JobDetail, you must re-store the /// JobDetail afterward (e.g. see <see cref="M:Quartz.IScheduler.AddJob(Quartz.IJobDetail,System.Boolean)"/>). /// </remarks> public IJobDetail GetJobDetail(JobKey jobKey) { return(_scheduler.GetJobDetail(jobKey)); }
public async Task <ResultValue> JobDelete([FromBody] JobKey job) { return(await scheduler.StopOrDelScheduleJobAsync(job.Group, job.Name, true)); }
/// <summary> /// Resume (un-pause) the <see cref="T:Quartz.IJobDetail"/> with /// the given key. /// </summary> /// <remarks> /// If any of the <see cref="T:Quartz.IJob"/>'s<see cref="T:Quartz.ITrigger"/> s missed one /// or more fire-times, then the <see cref="T:Quartz.ITrigger"/>'s misfire /// instruction will be applied. /// </remarks> public void ResumeJob(JobKey jobKey) { _scheduler.ResumeJob(jobKey); }
public async Task <ResultValue> ResumeJob([FromBody] JobKey job) { return(await scheduler.ResumeJobAsync(job.Group, job.Name)); }
/// <summary> /// Trigger the identified <see cref="T:Quartz.IJobDetail"/> (Execute it now). /// </summary> /// <param name="data">the (possibly <see langword="null"/>) JobDataMap to be /// associated with the trigger that fires the job immediately. /// </param><param name="jobKey">The <see cref="T:Quartz.JobKey"/> of the <see cref="T:Quartz.IJob"/> to be executed. /// </param> public void TriggerJob(JobKey jobKey, JobDataMap data) { _scheduler.TriggerJob(jobKey, data); }
public async Task <bool> TriggerJob([FromBody] JobKey job) { await scheduler.TriggerJobAsync(job); return(true); }
/// <summary> /// Delete the identified <see cref="T:Quartz.IJob"/> from the Scheduler - and any /// associated <see cref="T:Quartz.ITrigger"/>s. /// </summary> /// <returns> /// true if the Job was found and deleted. /// </returns> public bool DeleteJob(JobKey jobKey) { return(_scheduler.DeleteJob(jobKey)); }
public Task JobResumed(JobKey jobKey, CancellationToken cancellationToken = default(CancellationToken)) { return(Task.Run(() => LogsAppendersManager.Instance.Debug(this.GetType(), MethodBase.GetCurrentMethod(), jobKey.Name))); }
public void Test(IScheduler scheduler, bool clearJobs, bool scheduleJobs) { try { if (clearJobs) { scheduler.Clear(); } if (scheduleJobs) { ICalendar cronCalendar = new CronCalendar("0/5 * * * * ?"); ICalendar holidayCalendar = new HolidayCalendar(); // QRTZNET-86 ITrigger t = scheduler.GetTrigger(new TriggerKey("NonExistingTrigger", "NonExistingGroup")); Assert.IsNull(t); AnnualCalendar cal = new AnnualCalendar(); scheduler.AddCalendar("annualCalendar", cal, false, true); IOperableTrigger calendarsTrigger = new SimpleTriggerImpl("calendarsTrigger", "test", 20, TimeSpan.FromMilliseconds(5)); calendarsTrigger.CalendarName = "annualCalendar"; JobDetailImpl jd = new JobDetailImpl("testJob", "test", typeof(NoOpJob)); scheduler.ScheduleJob(jd, calendarsTrigger); // QRTZNET-93 scheduler.AddCalendar("annualCalendar", cal, true, true); scheduler.AddCalendar("baseCalendar", new BaseCalendar(), false, true); scheduler.AddCalendar("cronCalendar", cronCalendar, false, true); scheduler.AddCalendar("dailyCalendar", new DailyCalendar(DateTime.Now.Date, DateTime.Now.AddMinutes(1)), false, true); scheduler.AddCalendar("holidayCalendar", holidayCalendar, false, true); scheduler.AddCalendar("monthlyCalendar", new MonthlyCalendar(), false, true); scheduler.AddCalendar("weeklyCalendar", new WeeklyCalendar(), false, true); scheduler.AddCalendar("cronCalendar", cronCalendar, true, true); scheduler.AddCalendar("holidayCalendar", holidayCalendar, true, true); Assert.IsNotNull(scheduler.GetCalendar("annualCalendar")); JobDetailImpl lonelyJob = new JobDetailImpl("lonelyJob", "lonelyGroup", typeof(SimpleRecoveryJob)); lonelyJob.Durable = true; lonelyJob.RequestsRecovery = true; scheduler.AddJob(lonelyJob, false); scheduler.AddJob(lonelyJob, true); string schedId = scheduler.SchedulerInstanceId; int count = 1; JobDetailImpl job = new JobDetailImpl("job_" + count, schedId, typeof(SimpleRecoveryJob)); // ask scheduler to re-Execute this job if it was in progress when // the scheduler went down... job.RequestsRecovery = true; IOperableTrigger trigger = new SimpleTriggerImpl("trig_" + count, schedId, 20, TimeSpan.FromSeconds(5)); trigger.JobDataMap.Add("key", "value"); trigger.EndTimeUtc = DateTime.UtcNow.AddYears(10); trigger.StartTimeUtc = DateTime.Now.AddMilliseconds(1000L); scheduler.ScheduleJob(job, trigger); // check that trigger was stored ITrigger persisted = scheduler.GetTrigger(new TriggerKey("trig_" + count, schedId)); Assert.IsNotNull(persisted); Assert.IsTrue(persisted is SimpleTriggerImpl); count++; job = new JobDetailImpl("job_" + count, schedId, typeof(SimpleRecoveryJob)); // ask scheduler to re-Execute this job if it was in progress when // the scheduler went down... job.RequestsRecovery = (true); trigger = new SimpleTriggerImpl("trig_" + count, schedId, 20, TimeSpan.FromSeconds(5)); trigger.StartTimeUtc = (DateTime.Now.AddMilliseconds(2000L)); scheduler.ScheduleJob(job, trigger); count++; job = new JobDetailImpl("job_" + count, schedId, typeof(SimpleRecoveryStatefulJob)); // ask scheduler to re-Execute this job if it was in progress when // the scheduler went down... job.RequestsRecovery = (true); trigger = new SimpleTriggerImpl("trig_" + count, schedId, 20, TimeSpan.FromSeconds(3)); trigger.StartTimeUtc = (DateTime.Now.AddMilliseconds(1000L)); scheduler.ScheduleJob(job, trigger); count++; job = new JobDetailImpl("job_" + count, schedId, typeof(SimpleRecoveryJob)); // ask scheduler to re-Execute this job if it was in progress when // the scheduler went down... job.RequestsRecovery = (true); trigger = new SimpleTriggerImpl("trig_" + count, schedId, 20, TimeSpan.FromSeconds(4)); trigger.StartTimeUtc = (DateTime.Now.AddMilliseconds(1000L)); scheduler.ScheduleJob(job, trigger); count++; job = new JobDetailImpl("job_" + count, schedId, typeof(SimpleRecoveryJob)); // ask scheduler to re-Execute this job if it was in progress when // the scheduler went down... job.RequestsRecovery = (true); trigger = new SimpleTriggerImpl("trig_" + count, schedId, 20, TimeSpan.FromMilliseconds(4500)); scheduler.ScheduleJob(job, trigger); count++; job = new JobDetailImpl("job_" + count, schedId, typeof(SimpleRecoveryJob)); // ask scheduler to re-Execute this job if it was in progress when // the scheduler went down... job.RequestsRecovery = (true); IOperableTrigger ct = new CronTriggerImpl("cron_trig_" + count, schedId, "0/10 * * * * ?"); ct.JobDataMap.Add("key", "value"); ct.StartTimeUtc = DateTime.Now.AddMilliseconds(1000); scheduler.ScheduleJob(job, ct); count++; job = new JobDetailImpl("job_" + count, schedId, typeof(SimpleRecoveryJob)); // ask scheduler to re-Execute this job if it was in progress when // the scheduler went down... job.RequestsRecovery = (true); var timeZone1 = TimeZoneUtil.FindTimeZoneById("Central European Standard Time"); var timeZone2 = TimeZoneUtil.FindTimeZoneById("Mountain Standard Time"); DailyTimeIntervalTriggerImpl nt = new DailyTimeIntervalTriggerImpl("nth_trig_" + count, schedId, new TimeOfDay(1, 1, 1), new TimeOfDay(23, 30, 0), IntervalUnit.Hour, 1); nt.StartTimeUtc = DateTime.Now.Date.AddMilliseconds(1000); nt.TimeZone = timeZone1; scheduler.ScheduleJob(job, nt); var loadedNt = (IDailyTimeIntervalTrigger)scheduler.GetTrigger(nt.Key); Assert.That(loadedNt.TimeZone.Id, Is.EqualTo(timeZone1.Id)); nt.TimeZone = timeZone2; scheduler.RescheduleJob(nt.Key, nt); loadedNt = (IDailyTimeIntervalTrigger)scheduler.GetTrigger(nt.Key); Assert.That(loadedNt.TimeZone.Id, Is.EqualTo(timeZone2.Id)); DailyTimeIntervalTriggerImpl nt2 = new DailyTimeIntervalTriggerImpl(); nt2.Key = new TriggerKey("nth_trig2_" + count, schedId); nt2.StartTimeUtc = DateTime.Now.Date.AddMilliseconds(1000); nt2.JobKey = job.Key; scheduler.ScheduleJob(nt2); // GitHub issue #92 scheduler.GetTrigger(nt2.Key); // GitHub issue #98 nt2.StartTimeOfDay = new TimeOfDay(1, 2, 3); nt2.EndTimeOfDay = new TimeOfDay(2, 3, 4); scheduler.UnscheduleJob(nt2.Key); scheduler.ScheduleJob(nt2); var triggerFromDb = (IDailyTimeIntervalTrigger)scheduler.GetTrigger(nt2.Key); Assert.That(triggerFromDb.StartTimeOfDay.Hour, Is.EqualTo(1)); Assert.That(triggerFromDb.StartTimeOfDay.Minute, Is.EqualTo(2)); Assert.That(triggerFromDb.StartTimeOfDay.Second, Is.EqualTo(3)); Assert.That(triggerFromDb.EndTimeOfDay.Hour, Is.EqualTo(2)); Assert.That(triggerFromDb.EndTimeOfDay.Minute, Is.EqualTo(3)); Assert.That(triggerFromDb.EndTimeOfDay.Second, Is.EqualTo(4)); job.RequestsRecovery = (true); CalendarIntervalTriggerImpl intervalTrigger = new CalendarIntervalTriggerImpl( "calint_trig_" + count, schedId, DateTime.UtcNow.AddMilliseconds(300), DateTime.UtcNow.AddMinutes(1), IntervalUnit.Second, 8); intervalTrigger.JobKey = job.Key; scheduler.ScheduleJob(intervalTrigger); // custom time zone const string CustomTimeZoneId = "Custom TimeZone"; var webTimezone = TimeZoneInfo.CreateCustomTimeZone( CustomTimeZoneId, TimeSpan.FromMinutes(22), null, null); TimeZoneUtil.CustomResolver = id => { if (id == CustomTimeZoneId) { return(webTimezone); } return(null); }; var customTimeZoneTrigger = TriggerBuilder.Create() .WithIdentity("customTimeZoneTrigger") .WithCronSchedule("0/5 * * * * ?", x => x.InTimeZone(webTimezone)) .StartNow() .ForJob(job) .Build(); scheduler.ScheduleJob(customTimeZoneTrigger); var loadedCustomTimeZoneTrigger = (ICronTrigger)scheduler.GetTrigger(customTimeZoneTrigger.Key); Assert.That(loadedCustomTimeZoneTrigger.TimeZone.BaseUtcOffset, Is.EqualTo(TimeSpan.FromMinutes(22))); // bulk operations var info = new Dictionary <IJobDetail, Collection.ISet <ITrigger> >(); IJobDetail detail = new JobDetailImpl("job_" + count, schedId, typeof(SimpleRecoveryJob)); ITrigger simple = new SimpleTriggerImpl("trig_" + count, schedId, 20, TimeSpan.FromMilliseconds(4500)); var triggers = new Collection.HashSet <ITrigger>(); triggers.Add(simple); info[detail] = triggers; scheduler.ScheduleJobs(info, true); Assert.IsTrue(scheduler.CheckExists(detail.Key)); Assert.IsTrue(scheduler.CheckExists(simple.Key)); // QRTZNET-243 scheduler.GetJobKeys(GroupMatcher <JobKey> .GroupContains("a").DeepClone()); scheduler.GetJobKeys(GroupMatcher <JobKey> .GroupEndsWith("a").DeepClone()); scheduler.GetJobKeys(GroupMatcher <JobKey> .GroupStartsWith("a").DeepClone()); scheduler.GetJobKeys(GroupMatcher <JobKey> .GroupEquals("a").DeepClone()); scheduler.GetTriggerKeys(GroupMatcher <TriggerKey> .GroupContains("a").DeepClone()); scheduler.GetTriggerKeys(GroupMatcher <TriggerKey> .GroupEndsWith("a").DeepClone()); scheduler.GetTriggerKeys(GroupMatcher <TriggerKey> .GroupStartsWith("a").DeepClone()); scheduler.GetTriggerKeys(GroupMatcher <TriggerKey> .GroupEquals("a").DeepClone()); scheduler.Start(); Thread.Sleep(TimeSpan.FromSeconds(3)); scheduler.PauseAll(); scheduler.ResumeAll(); scheduler.PauseJob(new JobKey("job_1", schedId)); scheduler.ResumeJob(new JobKey("job_1", schedId)); scheduler.PauseJobs(GroupMatcher <JobKey> .GroupEquals(schedId)); Thread.Sleep(TimeSpan.FromSeconds(1)); scheduler.ResumeJobs(GroupMatcher <JobKey> .GroupEquals(schedId)); scheduler.PauseTrigger(new TriggerKey("trig_2", schedId)); scheduler.ResumeTrigger(new TriggerKey("trig_2", schedId)); scheduler.PauseTriggers(GroupMatcher <TriggerKey> .GroupEquals(schedId)); Assert.AreEqual(1, scheduler.GetPausedTriggerGroups().Count); Thread.Sleep(TimeSpan.FromSeconds(3)); scheduler.ResumeTriggers(GroupMatcher <TriggerKey> .GroupEquals(schedId)); Assert.IsNotNull(scheduler.GetTrigger(new TriggerKey("trig_2", schedId))); Assert.IsNotNull(scheduler.GetJobDetail(new JobKey("job_1", schedId))); Assert.IsNotNull(scheduler.GetMetaData()); Assert.IsNotNull(scheduler.GetCalendar("weeklyCalendar")); var genericjobKey = new JobKey("genericJob", "genericGroup"); var genericJob = JobBuilder.Create <GenericJobType <string> >() .WithIdentity(genericjobKey) .StoreDurably() .Build(); scheduler.AddJob(genericJob, false); genericJob = scheduler.GetJobDetail(genericjobKey); Assert.That(genericJob, Is.Not.Null); scheduler.TriggerJob(genericjobKey); Thread.Sleep(TimeSpan.FromSeconds(20)); Assert.That(GenericJobType <string> .TriggeredCount, Is.EqualTo(1)); scheduler.Standby(); CollectionAssert.IsNotEmpty(scheduler.GetCalendarNames()); CollectionAssert.IsNotEmpty(scheduler.GetJobKeys(GroupMatcher <JobKey> .GroupEquals(schedId))); CollectionAssert.IsNotEmpty(scheduler.GetTriggersOfJob(new JobKey("job_2", schedId))); Assert.IsNotNull(scheduler.GetJobDetail(new JobKey("job_2", schedId))); scheduler.DeleteCalendar("cronCalendar"); scheduler.DeleteCalendar("holidayCalendar"); scheduler.DeleteJob(new JobKey("lonelyJob", "lonelyGroup")); scheduler.DeleteJob(job.Key); scheduler.GetJobGroupNames(); scheduler.GetCalendarNames(); scheduler.GetTriggerGroupNames(); TestMatchers(scheduler); } } finally { scheduler.Shutdown(false); } }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { #region Logging // make sure you configure logging and open telemetry before quartz services services.AddLogging(loggingBuilder => { loggingBuilder.ClearProviders(); loggingBuilder.AddSerilog(dispose: true); }); services.AddRazorPages(); #endregion Logging #region Quartz // base configuration for DI services.Configure <QuartzOptions>(Configuration.GetSection("Quartz")); services.AddQuartz(q => { // handy when part of cluster or you want to otherwise identify multiple schedulers q.SchedulerId = "Scheduler-Core"; #region DI Job Factory // this is default configuration if you don't alter it q.UseMicrosoftDependencyInjectionJobFactory(options => { // if we don't have the job in DI, allow fallback to configure via default constructor options.AllowDefaultConstructor = true; // set to true if you want to inject scoped services like Entity Framework's DbContext options.CreateScope = false; }); #endregion DI Job Factory #region Default Config -- For InMemory Store -- Comment if uses Persist Store -- Commented // these are the defaults //q.UseSimpleTypeLoader(); //q.UseInMemoryStore(); //q.UseDefaultThreadPool(tp => //{ // tp.MaxConcurrency = 10; //}); #endregion Default Config -- For InMemory Store -- Comment if uses Persist Store -- Commented #region Simple Trigger //// Create a job with Single Trigger //q.ScheduleJob<FirstSample>(trigger => trigger // .WithIdentity("SomeTrigger") // .StartAt(DateBuilder.EvenSecondDate(DateTimeOffset.UtcNow.AddSeconds(5))) // .WithDailyTimeIntervalSchedule(x => x.WithInterval(10, IntervalUnit.Second)) // .WithDescription("Say somethign Trigger configured for a SaySomethingJob with single call") // ); #endregion Simple Trigger #region Configure Individual Jobs And Trigger -- Commented // you can also configure individual jobs and triggers with code // this allows you to associated multiple triggers with same job // (if you want to have different job data map per trigger for example) //q.AddJob<ExampleJob>(j => j // .StoreDurably() // we need to store durably if no trigger is associated // .WithDescription("my awesome job") //); #endregion Configure Individual Jobs And Trigger -- Commented #region Second Sample Job with SampleTrigger and CronTrigger var secondSampleJobKey = new JobKey("Second Sample Job", "Sample Job Group"); q.AddJob <SecondSample>(secondSampleJobKey, j => j.WithDescription("My Second Sample Job")); // Sample Trigger for Second Sample Job q.AddTrigger(trigger => trigger .WithIdentity("SecondSample Sample Trigger") .ForJob(secondSampleJobKey) .StartNow() .WithSimpleSchedule(x => x.WithInterval(TimeSpan.FromSeconds(7)).RepeatForever()) .WithDescription("My Second Sample Trigger") ); // Cron Trigger for Second Sample Job q.AddTrigger(trigger => trigger .WithIdentity("My Second Sample Cron Trigger") .ForJob(secondSampleJobKey) .StartAt(DateBuilder.EvenSecondDate(DateTimeOffset.UtcNow.AddSeconds(3))) .WithCronSchedule("0/17 * * * * ?") .WithDescription("My Second Cron Trigger") ); #endregion Second Sample Job with SampleTrigger and CronTrigger #region TimeConverter q.UseTimeZoneConverter(); #endregion TimeConverter #region Sample Listener // Add Second Sample Listener q.AddJobListener <SecondSampleJobListener>(GroupMatcher <JobKey> .GroupEquals(secondSampleJobKey.Group)); q.AddTriggerListener <SecondSampleTriggerListener>(); q.AddSchedulerListener <SecondSampleSchedulerListener>(); #endregion Sample Listener #region Job Using Data var dataJobKey = new JobKey("AuthorInfo", "Using Data Group"); q.AddJob <UsingDataJob>(options => options.WithIdentity(dataJobKey) .UsingJobData("Name", "Nguyen Minh Van") .UsingJobData("Age", "24") .UsingJobData("Address", "District 12, Ho Chi Minh City") ); q.AddTrigger(options => options.ForJob(dataJobKey) .WithIdentity("DataJob-Trigger") .WithCronSchedule("0/5 * * * * ?")); #endregion Job Using Data #region Calender //const string calendarName = "myHolidayCalendar"; //q.AddCalendar<HolidayCalendar>( // name: calendarName, // replace: true, // updateTriggers: true, // x => x.AddExcludedDate(new DateTime(2020, 5, 15)) //); //q.AddTrigger(t => t // .WithIdentity("Daily Trigger") // .ForJob(jobKey) // .StartAt(DateBuilder.EvenSecondDate(DateTimeOffset.UtcNow.AddSeconds(5))) // .WithDailyTimeIntervalSchedule(x => x.WithInterval(10, IntervalUnit.Second)) // .WithDescription("my awesome daily time interval trigger") // .ModifiedByCalendar(calendarName) //); // convert time zones using converter that can handle Windows/Linux differences //q.UseTimeZoneConverter(); #endregion Calender }); #endregion Quartz #region Quartz Options // we can use options pattern to support hooking your own configuration with Quartz's // because we don't use service registration api, we need to manally ensure the job is present in DI //services.AddTransient<ExampleJob>(); //services.Configure<SampleOptions>(Configuration.GetSection("Sample")); //services.AddOptions<QuartzOptions>() // .Configure<IOptions<SampleOptions>>((options, dep) => // { // if (!string.IsNullOrWhiteSpace(dep.Value.CronSchedule)) // { // var jobKey = new JobKey("options-custom-job", "custom"); // options.AddJob<ExampleJob>(j => j.WithIdentity(jobKey)); // options.AddTrigger(trigger => trigger // .WithIdentity("options-custom-trigger", "custom") // .ForJob(jobKey) // .WithCronSchedule(dep.Value.CronSchedule)); // } // }); #endregion Quartz Options #region Quartz Server // ASP.NET Core hosting services.AddQuartzServer(options => { // when shutting down we want jobs to complete gracefully options.WaitForJobsToComplete = true; }); #endregion Quartz Server #region Other Services services .AddHealthChecksUI() .AddInMemoryStorage(); #endregion Other Services }
/// <summary> /// Calls the equivalent method on the 'proxied' <see cref="QuartzScheduler" />. /// </summary> public virtual Task <IJobDetail> GetJobDetail(JobKey jobKey) { return(CallInGuard(x => x.GetJobDetail(jobKey))); }
/// <summary> /// Determine whether a <see cref="T:Quartz.IJob"/> with the given identifier already /// exists within the scheduler. /// </summary> /// <param name="jobKey">the identifier to check for</param> /// <returns> /// true if a Job exists with the given identifier /// </returns> public bool CheckExists(JobKey jobKey) { return(_scheduler.CheckExists(jobKey)); }
public Task JobInterrupted(JobKey jobKey, CancellationToken cancellationToken = new CancellationToken()) { return(Task.FromResult(true)); }
/// <summary> /// 触发新增、删除、修改、暂停、启用、立即执行事件 /// </summary> /// <param name="schedulerFactory"></param> /// <param name="taskName"></param> /// <param name="groupName"></param> /// <param name="action"></param> /// <param name="taskOptions"></param> /// <returns></returns> public async Task TriggerAction(string taskName, string groupName, JobAction action, AddScheduleInput scheduleInput = null) { if (string.IsNullOrEmpty(taskName) || string.IsNullOrEmpty(groupName)) { throw new BusinessException($"任务名或组名不能为空"); } var scheduler = _scheduler; var jobKey = new JobKey(taskName, groupName); var triggerKey = new TriggerKey(taskName, groupName); if (!await scheduler.CheckExists(jobKey)) { throw new BusinessException($"未发现任务"); } if (!await scheduler.CheckExists(triggerKey)) { throw new BusinessException($"未发现触发器"); } switch (action) { case JobAction.除: case JobAction.修改: await scheduler.PauseTrigger(triggerKey); await scheduler.UnscheduleJob(triggerKey); // 移除触发器 await scheduler.DeleteJob(jobKey); if (action == JobAction.修改) { await AddJobAsync(scheduleInput); $">>>>{triggerKey}修改成功".WriteSuccessLine(); } break; case JobAction.暂停: await scheduler.PauseTrigger(triggerKey); $">>>>{triggerKey}暂停".WriteSuccessLine(); break; case JobAction.停止: await scheduler.Shutdown(); $">>>>{triggerKey}停止".WriteSuccessLine(); break; case JobAction.开启: await scheduler.ResumeTrigger(triggerKey); $">>>>{triggerKey}开启".WriteSuccessLine(); break; case JobAction.立即执行: await scheduler.TriggerJob(jobKey); $">>>>{triggerKey}立即执行".WriteSuccessLine(); break; } }
/// <summary> /// Set the identity of the Job which should be fired by the produced /// Trigger, by extracting the JobKey from the given job. /// </summary> /// <remarks> /// </remarks> /// <param name="jobDetail">the Job to fire.</param> /// <returns>the updated TriggerBuilder</returns> /// <seealso cref="ITrigger.JobKey" /> public TriggerBuilder ForJob(IJobDetail jobDetail) { JobKey k = jobDetail.Key; if (k.Name == null) { throw new ArgumentException("The given job has not yet had a name assigned to it."); } jobKey = k; return this; }
public Task JobResumed(JobKey jobKey, CancellationToken cancellationToken) { return(Task.FromResult(true)); }