跳到主要内容

因果传播网络

事件需要裁决,事实需要传播。

因果层的本质是时间的隐喻,事件是因果层的最小单位。

在这个闭环中,事件是输入,事实是输出,传播让输出成为下一轮输入。因果层通过不断运转这个循环,把外部世界的无序变化,整理成系统内部可追溯、可解释的历史。


事件与事实

事件是尚未被世界接受的变化请求。它可以来自外部输入,也可以来自因果层内部的传播。

事实是事件经过裁决之后,被正式承认进入历史的关系变化。

两者的区别至关重要:

  • 事件可以冲突、可以无效、可以被丢弃
  • 事实一旦成立,就不会被原地改写,后续变化只能以新事实追加

这意味着因果层维护的不是「当前状态」,而是一条持续增长的历史链。状态只是这条链在当前时刻的投影。

状态模型: 因果模型:
hp = 100 damage_taken
hp = 80 hp_depleted
hp = 0 entity_dead

参见因果层


裁决与传播

因果层通过两类规则运行:

  • 裁决规则:决定事件能否成为事实。从应用层视角看,它就是一条计算规则:

    (event, history) => Fact | null

    它包含两个环节:

    • 资格审查:检查事件是否满足生效条件;
    • 事实生成:根据输入生成事实内容。
  • 传播规则:决定事实会产生哪些新事件,推动下一轮循环。

裁决规则本质上是无状态的纯函数。给定一个事件和当前事实历史,它输出新事实或拒绝。事件何时到达、是否并发、是否冲突,都不是它需要关心的事。

从时间观上看,因果层不承认"同时"。所有看似同时发生的事件,在进入裁决前都已被排序机制整理成一条序列;裁决规则看到的永远是一个接一个的输入,而不是并发。这与函数式编程的世界观相通:没有真正的同时,只有输入到输出的映射。

锁、CAS 等并发原语,诞生于冯诺依曼的共享内存模型:多个执行流同时读写同一块内存,必须用它们来保护这块内存不被破坏。但是在面向因果的视角中,竞争与顺序由系统排序机制处理,这部分并发原语是不需要的,只要在应用层,不应该暴露具体的并发原语。

工程实现细节

排序机制的实现层次:

  • 冯诺依曼架构层面:重新设计硬件原生支持事件排序,理想情况无锁。
  • 语言 / 运行时层面:单线程事件循环天然无锁;多线程运行时内部可能仍需锁。
  • 分布式层面:通过消息队列和共识协议达成全局顺序。

应用层应该保持始终无锁;底层是否无锁取决于实现。这种事件驱动结构与 Actor 模型相似,但 Actor 规则分散在每个 Actor 中,双世界理论强调统一事实历史与最终因果一致性。工程上可以用来参考。

以游戏里的一次攻击为例:

玩家按下攻击键

attack_requested(事件)

裁决规则(计算规则):
├── 资格审查:目标在范围内?技能冷却?敌人闪避判定?
└── 事实生成:攻击力 × Buff加成 − 敌人防御力 = 伤害值

damage_applied(事实)

传播:death_check_requested(事件)
↓裁决规则(计算规则):
├── 资格审查:hp 是否小于 0?是否免疫致命伤害?是否可以复活?
└── 事实生成:确定死亡事实与相关派生值

entity_dead(事实)

传播:触发亡语、QTE、生成掉落物、更新任务、获取经验、触发升级、触发新剧情(新事件)

裁决与传播的关系:

裁决把不确定性收敛成事实;传播让事实重新打开不确定性。


工程约定

层次职责实现者
业务规则层计算规则、传播规则、感知层业务开发者
因果运行时层原子排序机制、规则调度框架 / 中间件

因果传播网络

没有时间,世界只是静态关系图;引入时间,静态结构就变成因果传播网络

因果传播网络是因果层的核心数据模型,可以看作一个不断产生变化的因果图。它要处理六类基本拓扑:

备注

排序机制保证事件进入网络的顺序,但它本身不是网络拓扑。 竞争与时序由排序机制处理,不应被当作变化如何连接与流动的问题。

六类基本拓扑

1. 分叉(Branching)

一个事实影响多个未来事件:

Fact
/ | \
v v v
A B C

2. 合并(Merging)

多个事实共同产生新的变化:

Fact A Fact B
\ /
v v
Event C

3. 循环(Feedback)

传播重新影响自身:

A → B → C
↑ |
└───────┘

4. 抢占(Preemption)

新的事件打断已有传播:

A → B → C

X (新事件中断 B→C)

5. 延迟(Delay)

事实的影响发生在未来:

订单创建
|
30分钟

订单超时

6. 计算(Computation)

多个输入通过确定性规则共同产生一个事实。计算规则本身无时间、无并发、无冲突,只关注结果正确性:

Event A Event B Fact D
\ / /
v v /
[计算规则] ←──────
|
v
Fact C

拓扑的工程映射

因果复杂性软件工程中的表现典型技术方案
分叉一个变化影响多个模块事件总线、发布订阅、Observer、消息队列
合并多个条件共同决定行为状态机、规则引擎、CEP、Workflow
循环变化不断相互影响反馈控制系统核心、事务边界、最大迭代次数、资源限制
延迟未来某个时间发生变化Timer、Scheduler、Job Queue、Cron、Timeout
抢占新事件打断旧过程中断、取消令牌、事务回滚、状态机切换
计算多输入经确定性规则产生事实纯函数、公式系统、类型安全的规则引擎、确定性状态机

对象、状态、模块只是传播路径的空间容器。软件工程里那些看似不相关的领域——并发、分布式、事务、中断、超时、反馈控制——本质上都是同一个因果传播网络在不同约束下的表现。


核心性质

因果层要可靠运转,必须具备四个性质:

可裁决性:冲突不能永远悬而不决,系统必须给出明确事实版本。

确定性:相同的历史事实、事件和规则,必须得到相同结果。

可追溯性:每个事实都能追溯完整因果链,而不是孤立地表现为 Enemy.dead = true

收敛性:任何有限范围内的因果传播必须在有限时间内结束。

其中收敛性最为重要,前三个只是为了保障收敛而设立的,它是世界能稳定运转的根本保证,参见最终因果一致性


总结

因果层是世界事实的唯一生成通道。它通过「事件 → 裁决 → 事实 → 传播」的循环,把持续变化整理成稳定、可解释、可追溯的历史。