策略引擎触发器

蓝图:https://blueprints.launchpad.net/congress/+spec/policy-engine-trigger

目前,没有将策略定义的表中的更改视为事件(即触发器)的机制。将策略定义的表中的更改视为事件很有用,因为这使我们能够,例如,(i) 在消息总线上发布这些更改 (ii) 设置响应式执行,无论是用代码编写还是用策略编写 (iii) 启动到其他策略引擎的转换。

问题描述

本规范旨在提供一个用于触发器的编程接口。程序员将注册一个事件处理程序,以便在表的更改发生时运行。然后,框架将定期(例如,在插入/删除发生时)计算表的更新并运行注册的事件处理程序。

提议的变更

我们将创建一个触发器注册接口,使程序员能够指定一个函数,以便在给定表的內容发生更改时运行。

程序员视角

程序员将注册的函数具有如下签名。

def respond_to_trigger(oldtable, newtable, delta)

程序员将在特定的理论和特定的表上注册此处理程序。在此示例中,我们注册上面的函数,以便每次在策略/理论“th”中表“p”发生更改时运行。

# congress/policy/runtime.py 实例:th = engine.policy(“alice_policy”) # 在该策略上注册 ‘respond_to_trigger’ 用于表 ‘p’ th.register_trigger(“p”, respond_to_trigger)

从程序员的角度来看,每次在名为“alice_policy”的理论中表“p”的内容发生更改时,都会运行函数 respond_to_trigger,并将其作为参数传递原始表、新表和两者的差异。

实现

‘register_trigger’ 函数将在 congress/policy/runtime.py:Theory 类中实现。我们还将有一个 ‘unregister_trigger’ 函数调用。Theory 类将被扩展,包含一个哈希表 ‘self.triggers’,该哈希表将每个表名映射到已为该表注册的函数集合。‘register_trigger’ 和 ‘unregister_trigger’ 更改该哈希表的内容。

然后,将对 NonrecursiveRuleTheory、MaterializedViewTheory 和 Database 进行更改以实现触发器:每次调用 update() 时,该理论将 (i) 计算具有已注册触发器的每个表的内容,(ii) 应用通常的 update() 逻辑,(iii) 计算具有已注册触发器的每个表的内容(再次),(iv) 计算具有触发器的每个表的增量 (v) 对于具有非空增量的每个表 t,调用为 t 注册的所有触发器,并将参数 (i)、(iii)、(iv) 传递给它们

显然,触发器可能很昂贵,因为它们需要在每次更改数据时进行 2 次查询。理想情况下,我们将利用策略分析仅在更新数据可能更改这些表的内容时才查询这些表。

例如,假设我们为表 p 注册了一个触发器,并且我们有 2 条规则

p(x) :- q(x) r(x) :- t(x)

对表 t 的更新永远不会更改 p 的内容,但对表 q 的更新可能会更改 p 的内容。因此,触发器实现仅在传入的更新更改 q 时才对 p 运行查询。

备选方案

程序员可以为需要此功能的每个功能编写自己的触发器逻辑。好处是程序员可以自定义功能以完全符合她的目的。缺点是用户需要了解所有 Theory 子类的内部结构。

策略

策略操作

数据源

数据模型影响

REST API 影响

安全影响

通知影响

其他最终用户影响

性能影响

此附加功能可能或可能不会带来性能成本。

NonrecursiveRuleTheory 将会产生性能成本,因为目前我们不在插入/删除时评估表,但更改后我们需要进行更多的查询评估。

MaterializedViewTheory 不会产生性能成本,因为它已经在每次插入/删除时评估所有表。

其他部署者影响

开发者影响

在 Congress 之外没有影响。如果他们愿意,开发人员可以忽略新的接口。

实现

负责人

主要负责人

Tim Hinrichs

工作项

  • 向理论基类添加事件处理程序注册表

  • 向所有理论子类添加事件处理程序实现

依赖项

测试

单元测试:注册事件处理程序,插入/删除策略数据,检查事件处理程序是否实际执行

文档影响

参考资料