简体   繁体   English

Drools:时间限制规则

[英]Drools: Time restricted rule

Drools documentation mentions that rules can use attributes like date-effective and date-expires to specify an absolute rule validity period. Drools 文档提到规则可以使用诸如date-effectivedate-expires类的属性来指定绝对规则有效期。

For example 例如

rule "Date-restricted rule"
    date-effective "20.2.2013 8:00"      # 8 AM
    date-expires   "20.2.2013 16:00"     # 4 PM
    when
    then
end

Drools also supports periodically repeated rules with interval as timer(int:) and cron as timer(cron:) but it means that the rule is fired in such points. Drools还支持定期重复的规则,其中interval为timer(int:) ,cron为timer(cron:)但这意味着规则在这些点被触发。

Question: 题:

I am interested if there is any option how to specify periodically available (not fired) rules with time restriction. 如果有任何选项如何指定具有时间限制的定期可用(未触发)规则,我感兴趣。 For example let's image the business hours in some company - the operation can be performed only during official working period but not after hours. 例如,让我们想象某个公司的营业时间 - 只能在正式工作期间而不是在工作时间之后执行操作。

I would like something like this, but it is not Drools valid rule 我想要这样的东西,但这不是Drools的有效规则

rule "Time-restricted rule"
    time-effective "8:00"      # 8 AM
    time-expires   "16:00"     # 4 PM
    when
    then
end

Would be possible to extend such rule to be active only Monday to Friday 8 AM to 4 PM? 是否可以将此规则延长至周一至周五上午8点至下午4点?


Solution (by Esteban Aliverti): 解决方案(由Esteban Aliverti提供):

Drools doesn't have a direct support for time-based keywords, but they provide much more powerful calendar mechanism using Quartz library. Drools没有直接支持基于时间的关键字,但它们使用Quartz库提供了更强大的日历机制。 StatefulSession or WorkingMemory created by StatelessSession has methods to define these calendars which can restrict date and time when the rule can be fired. StatelessSession创建的StatefulSessionWorkingMemory具有定义这些日历的方法,这些日历可以限制可以触发规则的日期和时间。

Example: Rule definition 示例:规则定义

rule "Business hours only"
    calendars "business-hours"
    when
        SomeAttachedClass()
    then
        System.out.println("Rule is fired");
end

Calendar definition 日历定义

import org.quartz.impl.calendar.DailyCalendar;

// stateless session and working memory or directly stateful session
StatefulKnowledgeSession memory = session.newWorkingMemory(); 
// interested time range is 8-16, also there is many Calendar implementation, not just Daily
DailyCalendar businessHours = new DailyCalendar( 8, 0, 0, 0, 16, 0, 0, 0 );
// by default, defined time is EXCLUDED, the inversion makes it INCLUDED and excludes the rest
businessHours.setInvertTimeRange( true );
//convert the calendar into a org.drools.time.Calendar
org.drools.time.Calendar businessHoursCalendar = QuartzHelper.quartzCalendarAdapter( businessHours );
//Register the calendar in the session with a name. You must use this name in your rules.
memory.getCalendars().set( "business-hours", businessHoursCalendar );

A better approach is to use calendar instead of timer(cron:) . 更好的方法是使用calendar而不是timer(cron:) I managed to do something similar to what you are looking for following these steps: 我设法按照以下步骤执行类似于您要查找的操作:

When you create the session you have to create and configure a Quartz calendar: 创建会话时,您必须创建和配置Quartz日历:

//in this case I'm using a DailyCalendar but you can use whatever implementation of Calendar you want
org.quartz.impl.calendar.DailyCalendar businessHours = new org.quartz.impl.calendar.DailyCalendar("business-hours", 8, 0, 0, 0, 16, 0, 0, 0);
businessHours.setInvertTimeRange(true);

//convert the calendar into a org.drools.time.Calendar
org.drools.time.Calendar businessHoursCalendar = QuartzHelper.quartzCalendarAdapter(businessHours);

//Register the calendar in the session with a name. You must use this name in your rules.
ksession.getCalendars().set( "business-hours", businessHoursCalendar );

Then in your rule you have to write something like this: 然后在你的规则中你必须写这样的东西:

rule "Rule X"
    calendars "business-hours"
when
    ...
then
    ...
end

Hope it helps, 希望能帮助到你,

Here's another solution. 这是另一种解决方案。 Maybe a bit of a hack, but it works: 也许有点黑客,但它有效:

You can create a simple Java class encapsulating the current time and add an instance of this class to the working memory. 您可以创建一个封装当前时间的简单Java类,并将此类的实例添加到工作内存中。 This class, call it TimeFact , has methods like update(long time): void , getDay(): String and getTime(): String . 这个类称为TimeFact ,它有像update(long time): void这样的方法update(long time): voidgetDay(): StringgetTime(): String This fact can then be used in the when part of a rule, like this: 然后可以在规则的when部分使用此事实,如下所示:

rule "Foo"
when
    TimeFact(day in ("Monday", "Thursday"), time > "16:00:00" && < "17:00:00")
    [more conditions]
then
    [do stuff]
end

You will need to update the TimeFact (and notify the rule engine of this update) before firing your rules. 在触发规则之前,您需要更新TimeFact (并通知此更新的规则引擎)。 Still, it has the advantage that rule activation times can be described in the rules themselves, without having to define a possibly large number of calendars , thus making this approach much more flexible. 尽管如此,它的优点是规则激活时间可以在规则本身中描述,而不必定义可能大量的calendars ,从而使这种方法更加灵活。

Of course, if you have only a few such timed conditions, like "office hours", then the solution using calendars is preferable. 当然,如果你只有几个这样的时间条件,比如“办公时间”,那么使用calendars的解决方案更可取。

According to the documentation, you could use cron expressions as timers. 根据文档,您可以使用cron表达式作为计时器。 So, you could probably use something like this: 所以,你可以使用这样的东西:

timer(cron: * 8-16 * * 1-5 *) 

Disclaimer: I didn't test this! 免责声明:我没有测试过这个!

Hope it helps, 希望能帮助到你,

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM