您正在寻找stream mode 和negative patterns。这些链接指向 Drools 官方文档。
流模式是 Drools 中的两种事件模式之一。默认为“云”模式,您可以在其中预先了解所有事实并自动做出决策。另一种模式“流”模式用于处理时间流,这听起来很像您的“ping”应用程序。在流模式下,Drools 会在每个事实进入时对其进行评估,并知道时间——即其他事实何时进入。
流模式中的否定模式是not 关键字的逻辑时间扩展。正如您正确指出的那样,在云模式下,它只是否定一个条件(例如,“工作记忆中没有与此条件匹配的条件。”)但是,在流模式下,您可以更新这些模式以在一段时间内生效时间。
Drools 文档提供了这个例子:
rule "Sound the alarm"
when
$h: Heartbeat() from entry-point "MonitoringStream"
not(Heartbeat(this != $h, this after[0s,10s] $h) from entry-point "MonitoringStream")
then
// Sound the alarm.
end
“when”子句中的第一行标识了一个心跳实例 ($h)。第二个标识在 10 秒内未收到心跳的情况。如果两个条件都为真,则执行规则——在这种情况下会触发警报。
这与您应用于规则的模式相同。
rule "Tag has not been in Room 1 for 5 minutes"
when
// Tag with ID 1, present in Room 1 -- First instance
$tag: ComponentModel( tagId == 1, roomId == 1 ) from entry-point "TrackingStream"
// Trigger if this condition hasn't been met a second time within 5 minutes
not( ComponentModel(
this != $tag,
tagId == 1,
roomId == 1,
this after[0s, 5m] $tag ) from entry-point "TrackingStream")
then
// Do whatever it is you need to do for this condition
end
在这种情况下,我使用了 after 时间运算符(链接到 Drools 文档。)
基本上就是这样工作的--
$tag: ComponentModel( tagId == 1, roomId == 1 ) from entry-point "TrackingStream"
第一个条件标识场景,在这种情况下,房间 1 中存在 ID 1。它标识了我们正在跟踪的那个场景的当前实例。由于这是一个时间流,因此很容易将其视为“标记实体 (1) 刚刚进入房间 1。”
not( ComponentModel(
this != $tag,
tagId == 1,
roomId == 1,
this after[0s, 5m] $tag
) from entry-point "TrackingStream")
这就是魔法发生的地方,语法需要一点时间来适应。第二个条件是等待 next 时间然后检查条件。检查的条件是:
时间约束 (this after[0s, 5m] $tag) 表示等待检查此条件。如果在$tag 之后的此时间范围内收到第二个 ComponentModel,则规则不会触发,并且场景将重复等待最多 5 分钟。由于时间范围[0s, 5m] 立即开始检查,我们需要在not(...) 子句的匹配中明确排除$tag(this != $tag。)
为了说明,这就是它的执行方式(简化):
- 0m:00s - 事件 A ~ 已收到(id = 1,房间 = 1)。
$tag = 事件 A。我们开始检查传入流的第二个条件。
- 0m:30s - 事件 B ~ 收到(id = 2,房间 = 1)。身份不匹配;忽略。
- 0m:45s - 事件 C ~ 收到(id = 1,房间 = 1)。事件规则匹配“已取消”。现在检查
$tag = 事件 C。
- 5m:45s - 在 5 分钟窗口内未收到匹配事件,事件 C 的规则触发右侧。