WU / 文档通用微前端
中文

监督、恢复与 replay

监督每个应用的合作式故障,并用有界 journals 重放 RPC、时钟和随机性。

这些 APIs 属于 host,可用于单例或私有 new WuCore() 实例。请显式导入其函数。执行 destroy() 时,core 会释放 supervisors 和 sessions。

superviseApp

superviseApp(core, appName, options?): WuHealthHandle

应用必须已注册,且只能有一个 supervisor。host 通过 handle.report(error) 报告故障,应用通过 context.wu.reportError(error) 报告。达到阈值后,supervisor 撤销 scope、卸载应用并显示 fallback;随后尝试在同一容器恢复并还原 props。

import { superviseApp } from 'wu-framework/health';
// runtime already registered checkout; #checkout-slot exists.
const health = superviseApp(runtime, 'checkout', {
  threshold: 3, windowMs: 30000, retries: 2, delay: 1000, maxDelay: 30000,
  onState: status => console.log(status.state),
  fallback: element => { element.textContent = 'Checkout unavailable'; },
});
await runtime.mount('checkout', '#checkout-slot');
// Teardown when the owner of this supervisor exits:
health.stop();

示例值即默认值。threshold 和 retries 为整数;windowMs 表示故障统计窗口。恢复使用受 maxDelay 限制的指数等待,在 supervisor 整个生命周期内最多消耗 retries 次尝试。onState(status) 观察转换;fallback(element, status) 自定义消息。

status() 返回 { appName, state, attempts, failures, error? }。状态包括 healthy、quarantined、recovering、exhausted 和 stopped。隔离或耗尽时 isBlocked() 为真,手动挂载以 WU_APP_QUARANTINED 拒绝。settled() 等待当前任务,而非未来所有重试等待。stop() 取消恢复并移除 fallback,不重新挂载应用。

监督依赖已报告的错误和合作式代码。它无法中断无限循环,也不会自动检测所有浏览器异常。第二个 supervisor 会产生 WU_HEALTH_ALREADY_SUPERVISED;未知应用会产生 WU_APP_NOT_REGISTERED。

createReplaySession

createReplaySession(core, { apps, mode?, journal?, maxEntries?, maxBytes? }): WuReplaySession

为已注册应用记录 scoped request、now 和 random 调用。在可重放代码中使用 context.wu.now() 和 context.wu.random()。默认模式为 record,限制为 5000 条记录和 2 MiB;同一应用不能有重叠 sessions。

import { createReplaySession } from 'wu-framework/replay';
import 'wu-framework/timeline';
// checkout performs its scoped operations during its awaited lifecycle.
const recording = createReplaySession(runtime, { apps: ['checkout'] });
await runtime.mount('checkout', '#checkout-slot');
const journal = await recording.export({ timeline: true });
recording.stop();
await runtime.unmount('checkout', { force: true });

const playback = createReplaySession(runtime, { apps: ['checkout'], mode: 'replay', journal });
try {
  await runtime.mount('checkout', '#checkout-slot');
  playback.assertComplete();
} finally {
  playback.stop();
}

重放时应用、操作和输入必须一致,包括 RPC 通道、数据和版本。它返回已记录结果或错误,不调用真实 provider。差异会抛出 WU_REPLAY_MISMATCH;非 JSON 数据产生 WU_REPLAY_VALUE,超限产生 WU_REPLAY_LIMIT。记录按调用顺序而非完成顺序重放。

status() 报告 { mode, entries, cursor, pending, stopped, invalid }。export() 返回 wu-replay/1 格式的 promise;若仍有 RPC 待处理或 journal 无效则拒绝。export({ timeline: true }) 添加同一 core 的 timeline;使用 core 入口时需显式导入 timeline。assertComplete() 要求没有待处理调用或未消费重放条目。stop() 释放 interceptors,允许重新调用真实 providers。

journal 不捕获直接 fetch、Date.now、Math.random、timers、DOM 或外部副作用,也不会自动恢复初始状态或执行导入的 timeline。重放前应准备相同输入和状态。Journals 可能包含应用数据,请控制存储和访问。Replay 不等于回滚或持久审计。

证据与生命周期

实现:src/core/wu-health.js 中的 superviseApp、src/core/wu-replay.js 中的 createReplaySession 和 src/core/wu-app-scope.js 中的 facade。测试:tests/unit/app-health-supervision.test.js、tests/unit/replay-journal.test.js、tests/unit/replay-session.test.js 和 tests/unit/subsystem-lifecycle.test.js。

一起完善 WU

发现了问题?有新的想法?

你的使用体验能让 WU 变得更好。告诉我们遇到的问题,或支持项目的持续开发。