Skip to content

NACP 可观测 ​

NACP 不持有独立 EventBus,所有观测事件都发布到所属 NApp 的 app.bus。

js
const listenerId = app.bus.listen("nacp:*:*:*", (payload, hitKey) => {
  console.log(hitKey, payload)
})

app.bus.off(listenerId)

NACP 事件分为三族:

事件名模式记录内容
nacp:inbound:{type}NACPMessage 进入本端 NACP
nacp:outbound:{type}NACPMessage 尝试离开本端 NACP
nacp:{event|ability}:{reqId}:{stage}一次 Request 的处理过程与终局
nacp:internal:{subject}:{level}路由、链路、队列和协议异常

type 是九种 NACPMessage 类型之一。

内部事件的具体原因统一放在 payload.reason,事件名只表达主题与级别。

出入站事件 ​

入站 ​

js
nacp:inbound:{type}

payload:

ts
interface InboundPayload {
  fromPeerId: NACTPeerId
  msg: NACPMessage
}

TIP

消息一旦进入 inbound() 就会触发入站事件,早于地址检查、Gateway 转发、ACK、去重和具体的 onXxx() 处理。

因此以下消息也可以被观察到:

  • 发给其他 NApp、随后被转发的消息。
  • 地址错误、随后被丢弃的消息。
  • 已经处理过、随后被去重的可靠消息副本。

出站 ​

js
nacp:outbound:{type}

payload:

ts
interface OutboundPayload {
  toPeerId: NACTPeerId | undefined
  msg: NACPMessage
}

TIP

出站事件在消息尝试提交给 NACT 前触发。

它表示一次出站尝试,不保证 NACT 已接纳、对端已收到或业务已经完成。

场景是否立即产生出站事件
目标在线是
目标离线,消息进入 Backlog否;重连后真正尝试出线时才产生
未知目标且没有 Gateway是,toPeerId 为 undefined,随后报告 no-route
消息发给自己是,toPeerId 为 undefined,随后报告 self-addressed
Gateway 转发是,Provider 接纳后产生 nacp:internal:gateway:success
AutoSubscribe 的虚拟订阅与退订否

同一条可靠消息在断线重发时可能多次产生 nacp:outbound:{type},需要按 msg.id 关联这些尝试。

WARNING

入站或出站事件是“经过 NACP - NACT”的含义,不是“对方已接收的成功信号”。

  • 是否交给 NACT,结合 nacp:internal:route:error 判断。
  • 是否到达对端,由 ACK 与 nacp:internal:ack:warning 判断。
  • Request 是否处理完成,由 Response 或调用事件的 response 阶段判断。

Request 事件 ​

Request 事件描述 Processor 所在端的实际处理过程。

它们不同于 nacp:inbound:request、nacp:outbound:notify 和 nacp:outbound:response 等传输事件,request相关事件实际上更多关注Processor的输出。

事件名触发时机payload
nacp:event:{reqId}:processEvent Processor 产出一条过程消息Raw Chunk
nacp:event:{reqId}:responseEvent Processor 产出终局{ result, isOk, whyNotOk }
nacp:event:{reqId}:signalEvent Request 收到一条 SignalSignalMessage
nacp:ability:{reqId}:responseAbility Processor 产出终局{ result, isOk, whyNotOk }

链路事件 ​

js
nacp:internal:napp:success

payload:

ts
interface NappSuccessPayload {
  appId: string
  reason: "bound" | "offline" | "dropped"
  isGateway?: boolean
}
reason含义
boundRegister 成功,App 已在线。重连成功时会再次出现
offlineNACT 断连或 ACK 超时,App 进入重连宽限期
dropped宽限期结束或收到 Unregister,App 状态已彻底清理

isGateway: true 只对 bound 有意义,表示该对端被本端采纳为 Gateway fallback。

dropped 不区分宽限期结束和主动 Unregister,只报告 NACP 已完成清理这一事实。

一次典型断连会先产生 nact:peer:disconnect,再由 NACP 为该 Peer 上的每个 App ID 产生 reason: "offline"。详见 NACT 可观测。

Gateway 事件 ​

事件名触发时机reasonpayload 主要字段
nacp:internal:gateway:success本端 Provider 已接纳转发包forwarded{ toPeerId, msg, reason }
nacp:internal:gateway:error错误地址消息不能或不允许转发dropped{ msg, reason }
nacp:internal:gateway:warning第二个 Gateway 声明被降级multi-gateway-downgraded{ appId, peerId, keptGatewayPeerId, reason }

gateway:error 也用于 Register 的错址丢弃。

协议错误 ​

除 Register 外,下表 payload 都是 { msg, reason }。

事件名触发时机reason
nacp:internal:request:errorRequest 找不到对应 Processorno-processor
nacp:internal:signal:errorSignal 无法交给 Event Processorno-event-processor / processor-rejected
nacp:internal:response:errorResponse 找不到等待方has-no-consumer
nacp:internal:notify:errorNotify 找不到本地订阅has-no-consumer
nacp:internal:subscribe:error订阅参数或目标订阅无效bad-target-sub-name / unknown-subscription
nacp:internal:ack:errorACK 找不到待确认消息has-no-consumer
nacp:internal:register:errorRegister错误,见下表见下表

Register 错误 ​

js
nacp:internal:register:error

payload:

ts
interface RegisterErrorPayload {
  fromPeerId: NACTPeerId
  from: string
  reason: string
}

常见 reason:

reason含义
dual-gateway两端都声明为 Gateway
version-mismatchNACP 主版本不兼容
appId-in-use同一 App ID 已在线
multi-gateway第二个 Gateway 不允许降级
expect-mismatch对端实际 App ID 与 connect() 预期不符
response-timeoutRegister 在协议时限内没有收到 Response

路由与队列 ​

路由错误 ​

js
nacp:internal:route:error

payload 为 { msg, reason }:

reason含义
self-addressed消息目标是本 App
no-route没有目标直连,也没有可用 Gateway
send-failed已解析 Peer,但 NACT 拒绝接纳消息

nacp:outbound:{type} 早于这些错误触发,可用相同的 msg.id 将一次出线尝试与失败原因关联。

ACK 告警 ​

text
nacp:internal:ack:warning

payload 为 { msg, reason }:

reason含义
timeout最早的消息等待 ACK 超时,对应 App 将进入 offline
pending-overflowAckPendingTable 溢出,最早的待确认消息被逐出

Backlog 告警 ​

text
nacp:internal:backlog:warning

payload 为 { msg, reason },其中 msg 是被拒绝或逐出的消息:

reason含义
notify-dropped新 Notify 因 Backlog 容量不足被直接拒绝
notify-evicted最早的 Notify 被逐出,为其他消息腾出空间
fifo-evicted没有 Notify 可逐出,最早的其他消息按 FIFO 被逐出

队列行为和 Promise 结算规则见生命周期。


WARNING

NACP 事件发布在普通 app.bus 上,因此可以被另一个 NApp 通过 Subscribe 远程订阅。但不要订阅会命中 Notify 自身出站事件的模式,例如:

js
remote.subscribe(target, "nacp:outbound:*")
remote.subscribe(target, "nacp:outbound:notify")

订阅命中后,NACP 需要发送 Notify;该 Notify 又产生 nacp:outbound:notify,再次命中同一订阅,形成消息自激,最终引发消息洪流。

本地 app.bus.listen() 不会自动发送 Notify,不存在这一问题。

远程观察时应订阅不会覆盖 nacp:outbound:notify 的具体事件,或在 NACP 之外转发观测数据。

Released under the MIT License.