首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Quartz.net RFC 2445或RFC 5545代替CRON

Quartz.net RFC 2445或RFC 5545代替CRON
EN

Stack Overflow用户
提问于 2021-03-16 14:06:01
回答 1查看 548关注 0票数 1

我们有一个运行在.NET中的web服务器,它使用Quartz来调度作业。作业的触发器以RFC 2445格式提供,但是Quartz使用CRON格式。我现在想

  • A:找一个可以将我的RFC 2445规则转换成CRON规则的库。
  • 相反,把RFC规则交给Quartz吧。

在后一种情况下,我发现了一些Java库,但不是针对.NET的。

我也试着写我自己的图书馆,但我被时间所困。使用RFC2445规则可以定义双周作业(或每三周作业或n-weekly作业)。

FREQ=WEEKLY;BYDAY=MO;INTERVAL=2

也就是说,每隔一个星期一。然而,CRON似乎没有这种功能。

EN

回答 1

Stack Overflow用户

发布于 2021-04-13 22:06:44

我有一个类似的要求,我找不到一个符合RFC 5545的库来与Quartz调度程序一起工作,最后我按照这一建议实现了一个自定义触发器

在我的例子中,我们使用控件来填充RRULE,但是您也可以对iCal.Net库进行同样的操作。这里并不是完整的实现,但它将使您开始工作,代码是未测试的

另一个注意事项:如果尝试使用Telerik RecurrenceRule解析它,"FREQ=WEEKLY;BYDAY=MO;INTERVAL=2“可能会失败,因为它缺少DTSTART、DTEND等。这是一个不会失败的重复规则字符串的示例:"DTSTART:20210309T050000Z\r\nDTEND:20210309T060000Z\r\nRRULE:FREQ=WEEKLY;BYDAY=TU;INTERVAL=1"

您需要实现ITrigger接口。其中许多内容可以从CroneTriggerImpl类中复制和修改。

代码语言:javascript
复制
public interface IRRuleTrigger : ITrigger
{
    string RecurrenceRuleString { get; set; }
} 

然后,您需要从AbstractTrigger继承的实现类。

代码语言:javascript
复制
public class MyTriggerImpl: AbstractTrigger, IRRuleTrigger
{
   //implement all members here. Look at CronTriggerImpl class in Quartz.Net source. I'm pasting some of the implementation code but not all.
   //...

    private RecurrenceRule rRule;

    /// <summary>
    /// Gets or sets the RRULE expression string.
    /// </summary>
    /// <value>The expression string.</value>
    public string RecurrenceRuleString
    {
        set
        {
            TimeZoneInfo originalTimeZone = TimeZone;
            var success = RecurrenceRule.TryParse(value, out var parsedRule);
            if(success) rRule = parsedRule ;// RecurrenceRule(value!);
        }
        get => rRule?.ToString();
    }


    /// <summary>
    /// Gets or sets the RRULE expression string.
    /// </summary>
    /// <value>The expression string like RRULE:FREQ=WEEKLY;BYDAY=MO;INTERVAL=2.</value>
    public string RecurrenceRuleString
    {
        set
        {
            TimeZoneInfo originalTimeZone = TimeZone;
            var success = RecurrenceRule.TryParse(value, out var parsedRule);
            if(success) rRule = parsedRule ;// RecurrenceRule(value!);
        }
        get => rRule?.ToString();
    }

    ////////////////////////////////////////////////////////////////////////////
    //
    // Computation Functions
    //
    ////////////////////////////////////////////////////////////////////////////

    /// <summary>
    /// Gets the next time to fire after the given time.
    /// </summary>
    /// <param name="afterTime">The time to compute from.</param>
    /// <returns></returns>
    protected DateTimeOffset? GetTimeAfter(DateTimeOffset afterTime)
    {
        return rRule?.HasOccurrences == true ?
            rRule?.Occurrences.Where(o => o > afterTime).Min()
            : null;
    }

    /// <summary>
    /// Returns the time before the given time
    /// that this <see cref="IRRuleTrigger" /> will fire.
    /// </summary>
    /// <param name="date">The date.</param>
    /// <returns></returns>
    protected DateTimeOffset? GetTimeBefore(DateTimeOffset? date)
    {
        return rRule?.HasOccurrences == true ? 
            rRule?.Occurrences.Where(o=> o < date).Max()
            : null;
    }
}

public class RRuleScheduleBuilder : ScheduleBuilder<IRRuleTrigger>
{
    private int misfireInstruction = MisfireInstruction.SmartPolicy;
    private RecurrenceRule recurrenceRule;

    public override IMutableTrigger Build()
    {
        MyTriggerImpl myTriggerImpl = new MyTriggerImpl();


        myTriggerImpl.MisfireInstruction = misfireInstruction;
        myTriggerImpl.RecurrenceRuleString = this.recurrenceRule.ToString();
        return myTriggerImpl;
    }
    /// <summary>
    /// Create a RRuleScheduleBuilder with the given string expression - which
    /// is presumed to be valid expression (and hence only a RuntimeException
    /// will be thrown if it is not).
    /// </summary>
    /// <remarks>
    /// </remarks>
    /// <param name="recurrenceRuleString">the RRule expression to base the schedule on.</param>
    /// <returns>the new RRuleScheduleBuilder</returns>
    public static RRuleScheduleBuilder RecurrenceRuleSchedule(string recurrenceRuleString)
    {
        var success = RecurrenceRule.TryParse(recurrenceRuleString, out var rRule);
        if(!success) throw new ArgumentException($"Recurrence Rule String ({recurrenceRuleString}) is invalid.");
        return new RRuleScheduleBuilder(rRule);
    }

    protected RRuleScheduleBuilder(RecurrenceRule rule)
    {
        this.recurrenceRule = rule ?? throw new ArgumentNullException(nameof(rule), "recurrenceRule cannot be null");
    }
}
/// <summary>
/// Extension methods that attach <see cref="RRuleScheduleBuilder" /> to <see cref="TriggerBuilder" />.
/// </summary>
public static class RRuleScheduleTriggerBuilderExtensions
{
    public static TriggerBuilder WithRRuleSchedule(this TriggerBuilder triggerBuilder, string recurrenceRuleString)
    {
        RRuleScheduleBuilder builder = RRuleScheduleBuilder.RecurrenceRuleSchedule(recurrenceRuleString);
        return triggerBuilder.WithSchedule(builder);
    }

    public static TriggerBuilder WithRRuleSchedule(this TriggerBuilder triggerBuilder, string recurrenceRuleString, Action<RRuleScheduleBuilder> action)
    {
        RRuleScheduleBuilder builder = RRuleScheduleBuilder.RecurrenceRuleSchedule(recurrenceRuleString);
        action(builder);
        return triggerBuilder.WithSchedule(builder);
    }
}

实现之后,您可以像这样创建和使用触发器:

代码语言:javascript
复制
        // Grab the Scheduler instance from the Factory
        StdSchedulerFactory factory = new StdSchedulerFactory();
        var scheduler = await factory.GetScheduler();
        await scheduler.Start();

        var job = JobBuilder.Create<MyBusinessClassThatImplementsIJobInterface>()
            .WithIdentity("someIdentity", "someGroupName")
            .Build();

        var trigger = (IRRuleTrigger)TriggerBuilder.Create()
            .WithIdentity("someName", "myGroup")
            .WithRRuleSchedule(rule.ToString())
            .Build();

        await scheduler.ScheduleJob(job, trigger);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66656860

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档