Skip to content

聚合根与关系

控制库的 41 张表围绕三个聚合根[1]组织。掌握这三个根,即可判定删除一行会连带删除哪些数据、哪些表属于独立事实。


三个聚合根

  • Node 是节点的聚合根。 一行 nodes 持有该节点的身份字段(node_id 主键、asnrouter_id、loopback、前缀)、base_template(DesiredState 中不来自子表的部分)与 current_generation(已发布的最新世代号)。它的子表(agent_tokenspeeringswg_interfacesbgp_sessionsgenerations)全部 cascade="all, delete-orphan",删节点连带删子行。
  • Peering 是网络对等关系的聚合根。 一条 peering 对应 0..1 条 WgInterface 与 0..N 条 BgpSession(均 cascade="all, delete-orphan")。local_node_id 指本端节点(CASCADE),remote_node_id 可空、指向另一个受管节点(SET NULL)——materializer 据此现取现填对端 WG 公钥并区分内外部互联。
  • DnsGroup 是共享模型,节点通过 Node.dns_group_id 订阅。DNS 不按节点保存;多个节点指向同一组即拿到同一份配置,也就是 anycast。组被删时 Node.dns_group_id 置 NULL(节点停跑 DNS,不连带删节点)。

聚合根之外的表分两类:

  • 观测与存档node_id 挂在 Node 上,全部 CASCADE——删除节点即清空其全部观测数据。
  • 独立事实不设外键,删除节点后仍然留存。最典型的是 flap_alerts:其 node_id 有意不设外键,因为告警属于历史事实,不应随节点删除而级联消失。

关系一览

表示外键指向,括号内为 ondelete

nodes (聚合根)
 ├─ agent_tokens.node_id             → nodes.node_id   (CASCADE)
 ├─ enrollment_tokens.node_id        → nodes.node_id   (SET NULL)
 ├─ generations.node_id              → nodes.node_id   (CASCADE)   UNIQUE(node_id, generation)
 ├─ node_wireguard_keys.node_id      → nodes.node_id   (CASCADE)   (PK)
 ├─ peerings.local_node_id           → nodes.node_id   (CASCADE)   UNIQUE(local_node_id, name)
 ├─ peerings.remote_node_id          → nodes.node_id   (SET NULL)
 ├─ wg_interfaces.node_id            → nodes.node_id   (CASCADE)   UNIQUE(node_id, name)
 │   └─ wg_interfaces.peering_id     → peerings.id     (SET NULL)
 ├─ bgp_sessions.node_id             → nodes.node_id   (CASCADE)   UNIQUE(node_id, name)
 │   └─ bgp_sessions.peering_id      → peerings.id     (SET NULL)
 ├─ node_status.node_id              → nodes.node_id   (CASCADE)   (PK)
 ├─ node_status_events.node_id       → nodes.node_id   (CASCADE)
 ├─ node_metrics_rollup.node_id      → nodes.node_id   (CASCADE)   (PK 复合)
 ├─ node_metrics_last.node_id        → nodes.node_id   (CASCADE)   (PK)
 ├─ node_routing.node_id             → nodes.node_id   (CASCADE)   (PK)
 ├─ node_route_entries.node_id       → nodes.node_id   (CASCADE)
 ├─ node_route_prefix_hashes.node_id → nodes.node_id   (CASCADE)   (PK)
 ├─ node_routing_events.node_id      → nodes.node_id   (CASCADE)
 ├─ node_traffic_rollup.node_id      → nodes.node_id   (CASCADE)   (PK 复合)
 ├─ node_traffic_last_sample.node_id → nodes.node_id   (CASCADE)   (PK)
 ├─ node_iface_traffic_rollup.node_id→ nodes.node_id   (CASCADE)   (PK 复合)
 ├─ node_iface_traffic_last.node_id  → nodes.node_id   (CASCADE)   (PK 复合)
 ├─ bgp_flap_state.node_id           → nodes.node_id   (CASCADE)   (PK 复合)
 ├─ bgp_flap_transitions.node_id     → nodes.node_id   (CASCADE)
 ├─ node_prefix_flaps.node_id        → nodes.node_id   (CASCADE)   (PK 复合)
 ├─ node_prefix_flap_meta.node_id    → nodes.node_id   (CASCADE)   (PK)
 ├─ node_prefix_flap_paths.node_id   → nodes.node_id   (CASCADE)   (PK 复合)
 ├─ prefix_flap_rate_rollup.node_id  → nodes.node_id   (CASCADE)   (PK 复合)
 ├─ autopeering_node_policies.node_id→ nodes.node_id   (CASCADE)   (PK)
 ├─ peering_requests.node_id         → nodes.node_id   (CASCADE)
 │   └─ peering_requests.peering_id  → peerings.id     (SET NULL)
 ├─ autopeer_route_rollup.node_id    → nodes.node_id   (CASCADE)   (PK 复合)
 └─ nodes.dns_group_id               → dns_groups.id   (SET NULL)

dns_groups (共享聚合根)
 └─ dns_group_zones.dns_group_id     → dns_groups.id       (CASCADE)  UNIQUE(dns_group_id, zone)
     └─ dns_records.dns_group_zone_id→ dns_group_zones.id  (CASCADE)

admin_users
 └─ admin_sessions.user_id           → admin_users.id  (CASCADE)

独立表(无外键,删节点不连带)
 port_pools                  全 fleet 统一的端口段位
 portal_login_transactions   登录事务(主路径已迁 L4)
 portal_sessions             门户会话
 flap_alerts                 node_id 有意不设外键:告警是历史事实
 flap_activity_rollup        fleet 级 60s 活跃度时间线,无节点维度
 admin_audit_log             审计

注意:SQLite(dev / CI)默认关闭外键,不开启则上述所有 ondelete 子句均不生效。引擎装配中每个新连接都会执行 PRAGMA foreign_keys=ON,见全局约定


  1. 聚合根(aggregate root):领域驱动设计中的概念,指一组相关对象的唯一外部入口。外部只能通过聚合根访问和修改其内部对象,聚合根的生命周期决定内部对象的生命周期——在本库中体现为 cascade="all, delete-orphan" 与外键的 ON DELETE CASCADE↩︎