// ===== 节点账本(blueprint: moonactor/erl_dist dist_account.mbt 移植;门 C 真件)=====
// 职责:monitor 账(我方 watcher 侧登记页)/被监视者了断通道/连接丢失事件源。
// 节点层裁形(解协议依赖——协议词住 beam-dist,本件零 ETF/DOP 词外泄):
// ref : EtfTerm → RefKey(不透明配对句柄——beam-dist 解码 ERef 后三元上抛);
// watched : EtfTerm → String(节点层账语义=具名进程/pid 文本句柄——真件
// A4 门 C 形=具名 atom 监视);AccountHooks/DopMsg(L3 接线口)裁掉——账面
// 方法直给(beam-dist 分派后调,节点层不接分派器)。
// 真源对位:net_kernel monitor_nodes/节点监视语义;on_conn_lost=本地判定
// (net_kernel.erl up_nodedown:controller-exit→delete_connection——不依赖
// 对端 EXIT 帧,对端死时发不出)。
///|
/// monitor 配对句柄(不透明键——demonitor/exit 按 ref 配对摘账;
/// 结构化三元=ERef(node 名序号/序号/creation)解码形,相等比较即配对)
pub(all) struct RefKey {
a : Int64
b : Int64
c : Int64
}
///|
pub fn RefKey::new(a~ : Int64, b~ : Int64 = 0, c~ : Int64 = 0) -> RefKey {
{ a, b, c, }
}
///|
fn RefKey::same(self : RefKey, other : RefKey) -> Bool {
self.a == other.a && self.b == other.b && self.c == other.c
}
///|
/// monitor 账页(我方 = watcher 侧登记)
pub(all) struct MonEntry {
key : RefKey // 会话引用(demonitor/exit 配对键;ref 是保留字——避名家法)
watched : String // 被监视者(具名进程/pid 文本句柄)
}
///|
/// 节点事件订阅面(门 C 第三监督者接线口——net_kernel:monitor_nodes 对应形;
/// 连接 FIN/读错→on_conn_lost→订阅者收 nodedown——本地判定语义)
pub(open) trait NodeEvents {
fn on_nodedown(self : Self, node : String) -> Unit
}
///|
/// 节点账本(单连接单账——多节点多账由 NodeRegistry 组装)
pub struct NodeAccount {
priv mut mons : Array[MonEntry]
priv mut exit_n : Int32 // 被监视者了断计数
priv mut lost_n : Int32 // 连接丢失计数(nodedown 事件面)
node : String // 本账所属对端节点名
}
///|
pub fn NodeAccount::new(node~ : String = "") -> NodeAccount {
{ mons: [], exit_n: 0, lost_n: 0, node, }
}
///|
/// monitor 账登记页数(直读)
pub fn NodeAccount::monitor_count(self : NodeAccount) -> Int32 {
self.mons.length()
}
///|
/// 被监视者了断计数(直读)
pub fn NodeAccount::exit_count(self : NodeAccount) -> Int32 {
self.exit_n
}
///|
/// monitor 登记(watcher 侧;beam-dist 分派 {19,watcher,watched,ref} 后调)
pub fn NodeAccount::register(
self : NodeAccount,
key~ : RefKey,
watched~ : String,
) -> Unit {
let _ = self.mons.push({ key, watched, })
}
///|
/// monitor 摘账(按 ref 配对;beam-dist 分派 {20,…,ref} 后调)
pub fn NodeAccount::demonitor(self : NodeAccount, key~ : RefKey) -> Unit {
self.mons = self.keep_others(key)
}
///|
/// 被监视者了断(按 ref 清账+事件计数;beam-dist 分派 {21,…,reason} 后调)
pub fn NodeAccount::monitored_exit(self : NodeAccount, key~ : RefKey) -> Unit {
self.mons = self.keep_others(key)
self.exit_n = self.exit_n + 1
}
///|
/// 摘除辅助:保留 ref 不匹配的页(配对摘除——闭域唯一性)
fn NodeAccount::keep_others(
self : NodeAccount,
key : RefKey,
) -> Array[MonEntry] {
let keep : Array[MonEntry] = []
for e in self.mons {
if !e.key.same(key) {
let _ = keep.push(e)
}
}
keep
}
///|
/// 连接丢失(门 C 事件源):TCP FIN/读错→清账+lost 计数+订阅者回调——
/// 本地判定(不依赖对端 EXIT 帧——对端死时发不出);Erlang 语义:
/// monitor 的该节点所有 watch 同时了断(reason=noconnection)
pub fn NodeAccount::on_conn_lost(
self : NodeAccount,
events : &NodeEvents,
) -> Unit {
self.mons = []
self.exit_n = 0
self.lost_n = self.lost_n + 1
events.on_nodedown(self.node)
}
///|
/// 连接丢失计数(罐测断言用)
pub fn NodeAccount::lost_count(self : NodeAccount) -> Int32 {
self.lost_n
}