Skip to content

运行时治理与故障恢复 ​

页签事务、应用沙箱和页面缓存各自拥有生命周期。operate() 成功表示导航已提交;远端应用是否完成加载和业务初始化,应读取 runtime 状态。Vue 项目通常通过 useMicroWorkspace 创建宿主和运行时,再使用 MicroAppContainer 展示加载、失败与重试。

配置与默认上限 ​

ts
import { useMicroWorkspace } from '@axewo/fin-micro/vue'

// 在宿主组件 setup 中创建;apps 来自可信应用注册表。
const workspace = useMicroWorkspace(apps, {
  host: {
    guardTimeoutMs: 60000,
    navigationTimeoutMs: 120000,
    maxPendingNavigations: 100,
  },
  runtime: {
    waitForReady: true,
    mountTimeoutMs: 30000,
    readyTimeoutMs: 30000,
    unmountTimeoutMs: 5000,
    maxMountedApps: 16,
    maxConcurrentMounts: 4,
  },
})
选项默认值超限行为
host.guardTimeoutMs60000ms单个离页守卫以 GUARD_TIMEOUT 拒绝,不自动放行
host.navigationTimeoutMs120000ms从入队开始计算,包含排队、全部守卫与路由确认,以 NAVIGATION_TIMEOUT 拒绝
host.maxPendingNavigations100包含执行中的事务,以 QUEUE_FULL 拒绝新增命令
runtime.mountTimeoutMs30000ms资源启动以 LOAD_TIMEOUT 拒绝,然后有界清理
runtime.readyTimeoutMs30000ms资源启动后等待业务就绪,以 READY_TIMEOUT 拒绝
runtime.unmountTimeoutMs5000ms销毁等待以 UNMOUNT_TIMEOUT 拒绝,旧桥及 DOM 已立即撤销
runtime.maxMountedApps16在管实例与残留沙箱之和达到上限,以 RESOURCE_LIMIT 拒绝新增挂载
runtime.maxConcurrentMounts4启动或初始化中的尝试达到上限,以 RESOURCE_LIMIT 拒绝新增挂载

持续时间须为正有限数且不超过 2147483647,数量须为正安全整数。运行时配置非法同步抛出 MicroRuntimeError(INVALID_OPTIONS);宿主配置非法在创建时同步拒绝。

资源预算不会自动关闭页签、丢弃未保存内容或无限排队。由项目提示用户关闭应用、等待清理后显式重试;若确实需要更多并发,可依据设备和业务规模提高上限。这里限制实例数量,不测量或承诺浏览器真实内存字节数。页面 MicroTabCache.max 是应用内页缓存上限,与沙箱数量不同。

路由成功后再提交页签 ​

connectMicroHostRouter 同时协调浏览器导航和核心交互导航:

  1. 捕获目标生命周期,执行核心离页确认,准备候选快照。
  2. 等待 Vue Router 的 beforeEnter、异步组件和 beforeResolve。
  3. Router 成功后同步提交页签,再释放关闭或替换的页面;拒绝或解析失败时取消候选事务。

重定向只为最终目标建立页签。后发导航、调用方取消、总等待超时或工作区销毁都会使旧事务失效。异步组件晚到不能重新提交旧页签;准备期间宿主版本变化时返回 stale,连接器按当前核心状态纠正 URL。

菜单、按钮和页面交互使用 host.operate() 或 PageSDK;同步 openTab/activateTab/closeTab 是可信底层原语,会直接改状态,不能获得外部 Router 拒绝时的事务保证。

底层适配器可使用 host.prepare(operation),得到 PreparedNavigation。只有 status === 'prepared' 时存在待提交事务;路由成功调用幂等 commit(),失败调用幂等 cancel()。在此期间队列串行占用,总上限自动释放;迟到 commit() 返回 stale。项目通常无需直接调用它,使用公共连接器即可。

coordinateNavigation(callback) 是核心导航的单一外部确认挂点。回调接收候选快照、signal 和幂等 commit;Router 成功时同步 commit,拒绝返回 false。每个宿主只能有一个有效协调器,销毁连接时须撤销钩子及待决等待。

每次挂载独立撤销能力 ​

每次 mount 都使用独立沙箱名、容器、就绪通道和 host.bridge(appId, { signal })。该桥只属于本次尝试,与 host.bridge(appId) 返回的共享桥不同。

卸载、加载失败或重试清理会立即中止实例信号,取消旧桥的会话/状态订阅、PageSDK 事件/守卫、待决能力调用和未提交导航。重试桥可继续使用仍存活的同一页签 key;旧实例不能调用 closeCurrent() 关闭它。单独 page.dispose() 后的原 key 关闭特例,前提是其应用桥仍然有效。

撤销通知 handler 的 context.signal,并使 context.isActive() 为 false。已经发生的保存请求或服务端副作用不能自动回滚,业务仍须协作取消、检查有效性,并正确处理幂等性。桥和 Wujie 不是恶意同窗口代码的安全隔离方案。

资源 fetch 同时保留调用方 signal、Request 自带 signal 和实例撤销信号;卸载也能中止响应体的继续读取。

观测就绪、失败和残留 ​

ts
import { MicroRuntimeError } from '@axewo/fin-micro/runtime'

const { runtime } = workspace
const off = runtime.subscribe(state => {
  // 只接收后续变化;elapsedMs 在状态变化时采样。
  console.info(state.appId, state.attemptId, state.status, state.errorCode)
})
workspace.own(off)

const resources = runtime.getResources()
// mountedApps:当前在管实例,含加载/就绪/卸载中。
// loadingApps:尚未完成启动/初始化,可能包含已隔离的旧尝试。
// residualSandboxes:不能确认清理完成的 { appId, attemptId }。
console.info(resources)

try {
  await runtime.unmount('business')
} catch (error) {
  if (error instanceof MicroRuntimeError && error.code === 'UNMOUNT_TIMEOUT') {
    // 使用固定文案提示;业务无需读取第三方原始异常。
  }
}

getState(appId) 返回最近尝试的冻结快照:appId/attemptId/status/elapsedMs/errorCode。未尝试挂载时为 idle;读取不会触发加载。订阅异常隔离,不改变挂载结果。getResources() 返回实时冻结副本;销毁后仍可用于诊断。

卸载首先撤销桥并移除 DOM,再等待 Wujie 销毁。超时结束公开等待,保留残留记录并继续消费第三方迟到结果;只有确认启动与清理完成后才移除记录。重试使用新沙箱,旧结果不会覆盖新状态。

无法强制结束的 JavaScript、永不返回的第三方 Promise 或销毁异常可能留下残留;不能把超时误报为强制销毁成功。残留继续计入预算。持续残留应定位子应用的卸载钩子、定时器和网络取消;必要时在保存业务内容后由用户刷新整页,运行库不自动刷新或静默丢弃内容。

dispose() 幂等共享一个 Promise,并行清理全部在管实例,每个实例都受卸载上限约束;所有等待结束后报告首个失败。先前已隔离的残留不会被反复销毁,仍保留诊断。挂载失败还会等待有界清理,因此最坏耗时包含对应启动/就绪上限与卸载上限。

稳定错误契约 ​

错误码含义
LOAD_FAILED / LOAD_TIMEOUT资源启动异常 / 超时
BOOTSTRAP_FAILED / READY_TIMEOUT子应用显式回报初始化失败 / 就绪等待超时
MOUNT_CANCELLED未完成的挂载被主动卸载或销毁
UNMOUNT_FAILED / UNMOUNT_TIMEOUT沙箱销毁异常 / 等待超时
RUNTIME_DISPOSED已销毁运行时拒绝挂载或新订阅
UNKNOWN_APP / LOCAL_APP未登记应用 / 尝试用 Wujie 挂载本地应用
CONTAINER_CONFLICT同一运行时内,该应用已有另一个挂载容器
RESOURCE_LIMIT驻留或并发预算不足,未创建新实例
INVALID_OPTIONS配置或挂载容器非法

运行时 Promise 使用 MicroRuntimeError 拒绝,不再透传原始 Wujie Error。加载与清理同时失败时,挂载 Promise 和最终 failed 快照保留原始加载类别,清理只记录固定脱敏提示;独立调用 unmount 则报告对应清理类别。主动取消后若清理正常完成,快照可回到 idle。

导航以 NavigationError 报告队列、守卫和权限问题;能力调用以 HostCallError 报告超时、桥撤销等问题。按各自 code 分支,不匹配中文 message,也不自动重试非幂等保存操作。

验收场景 ​

  • Router 在 beforeEnter/beforeResolve 拒绝或异步组件失败后,原页签和 SDK 保持有效。
  • 浏览器前进后退、守卫重定向与并发导航最终 URL 和活动页一致。
  • 排队任务取消立即结束并释放容量,不等待前一个守卫。
  • 卸载永久挂起也在配置上限内结束,并能观察残留及预算拒绝。
  • 重试后旧桥、旧就绪通道和迟到响应不能操作新实例。
  • 预算不足时原页签仍然存在,用户可以保存内容并选择释放应用。