我们正在开发一个资源预订系统,在该系统中,我们将获得在任意时间(从5分钟到2小时不等)内预订资源的请求。没有预定义的插槽。
我们尝试使用Drools(Fusion)ver。 7.12.0.Final,编写规则以确保新的预订请求不会覆盖已确认的现有请求。
为达到上述目的,我们创建了以下两个对象:
declare ReservationRequest
@role ( event )
@duration (reservationDuration )
@timestamp ( pickupTime )
id : int
pickupTime : Date
reservationDuration : long
reserved : String
deliveryEnd : Date
end
和
declare Reservation
reservation : ReservationRequest
end
'ReservationRequest'被视为事件,因此我们可以使用时间运算符来评估新请求不与已确认的请求重叠(捕获为推断的“ Reservation”事实。
我们编写了以下规则来检查重叠部分并插入相应的“保留”事实:
rule "Ensure no overlaped reservations using inferred facts"
enabled true
when
reservationRequest : ReservationRequest( )
not Reservation ( reservation == reservationRequest )
reservations : Reservation()
not ReservationRequest( this overlaps reservations.reservation )
not ReservationRequest( this overlappedby reservations.reservation )
not ReservationRequest( this includes reservations.reservation )
then
insert( new Reservation ( reservationRequest ) );
end
不幸的是,如果WM中存在“保留”事实,则上述规则将无法运行。我收到以下错误:
java.lang.RuntimeException: Conversion to long not supported from com.sample.ReservationRequest
at org.drools.core.base.extractors.BaseObjectClassFieldReader.getLongValue(BaseObjectClassFieldReader.java:133)
at org.drools.core.base.ClassFieldReader.getLongValue(ClassFieldReader.java:198)
at org.drools.core.rule.VariableRestriction$TemporalVariableContextEntry.updateFromTuple(VariableRestriction.java:641)
at org.drools.core.common.SingleBetaConstraints.updateFromTuple(SingleBetaConstraints.java:116)
at org.drools.core.phreak.PhreakNotNode.doLeftInserts(PhreakNotNode.java:108)
at org.drools.core.phreak.PhreakNotNode.doNode(PhreakNotNode.java:85)
at org.drools.core.phreak.RuleNetworkEvaluator.switchOnDoBetaNode(RuleNetworkEvaluator.java:571)
at org.drools.core.phreak.RuleNetworkEvaluator.evalBetaNode(RuleNetworkEvaluator.java:552)
at org.drools.core.phreak.RuleNetworkEvaluator.evalNode(RuleNetworkEvaluator.java:379)
at org.drools.core.phreak.RuleNetworkEvaluator.innerEval(RuleNetworkEvaluator.java:339)
at org.drools.core.phreak.RuleNetworkEvaluator.outerEval(RuleNetworkEvaluator.java:175)
at org.drools.core.phreak.RuleNetworkEvaluator.evaluateNetwork(RuleNetworkEvaluator.java:133)
at org.drools.core.phreak.RuleExecutor.reEvaluateNetwork(RuleExecutor.java:212)
at org.drools.core.phreak.RuleExecutor.evaluateNetworkAndFire(RuleExecutor.java:87)
at org.drools.core.concurrent.AbstractRuleEvaluator.internalEvaluateAndFire(AbstractRuleEvaluator.java:34)
at org.drools.core.concurrent.SequentialRuleEvaluator.evaluateAndFire(SequentialRuleEvaluator.java:43)
at org.drools.core.common.DefaultAgenda.fireLoop(DefaultAgenda.java:1067)
at org.drools.core.common.DefaultAgenda.internalFireAllRules(DefaultAgenda.java:1014)
at org.drools.core.common.DefaultAgenda.fireAllRules(DefaultAgenda.java:1006)
at org.drools.core.impl.StatefulKnowledgeSessionImpl.internalFireAllRules(StatefulKnowledgeSessionImpl.java:1337)
at org.drools.core.impl.StatefulKnowledgeSessionImpl.fireAllRules(StatefulKnowledgeSessionImpl.java:1328)
at org.drools.core.impl.StatefulKnowledgeSessionImpl.fireAllRules(StatefulKnowledgeSessionImpl.java:1312)
at com.sample.DroolsTest.main(DroolsTest.java:24)
在其他情况下,我们已广泛使用推断的事实,但这是我们第一次将其与事件一起使用。因此,我们不确定是否支持此功能(根据相关事件推断事实)。
如果不支持此功能,那么“保存”所需事件的最佳方法是什么,同时允许其他事件从WM撤出/撤回。我们可以使用“标志”标记要保留的事件,但如果可能的话,我们希望避免使用这种方法。
谢谢
答案 0 :(得分:0)
我非常喜欢Drools,为什么不创建带有start_datetime和end_datetime以及“ before insert on”触发器的SQL表,该触发器检查插入的值是否不与任何现有(已确认)值重叠在数据库中。如果触发器在插入过程中引发异常,则可以捕获它,并且知道存在重叠。
答案 1 :(得分:0)
我建议在变量名称前添加$号,这样您可以更好地区分字段和变量。
如果将方法boolean isOverlap(ReservationRequest)
添加到ReservationRequest
类中,则可以编写如下内容:
when
$reservationRequest : ReservationRequest( )
not Reservation ( this.reservation.isOverlap($reservationRequest) )
then
insert( new Reservation ( $reservationRequest ) );
这应该足够了。我还强烈建议您在引用ReservationRequest时使用变量名“ reservationRequest”,这非常令人困惑。