Skip to content

源码:labs/java/bridge-hybrid/bridge-timeout-layering-simulation/src/BridgeTimeoutLayeringSimulation.java ​

  • 原始路径:labs/java/bridge-hybrid/bridge-timeout-layering-simulation/src/BridgeTimeoutLayeringSimulation.java
  • 类型:java
java
import java.util.Map;

/**
 * 桥接调用超时分层仿真(对应 docs/05-bridge-hybrid/11)。
 *
 * 核心思想:桥接调用的「超时」不是一个数——运输层就绪、单次 RPC、
 * 用户操作 UI、HTTP 读超时是四件事,必须分层建模。
 *
 * 纯 Java CLI(无外部依赖,用压缩等待模拟真实计时以便快速跑完)。
 * 运行:javac -d out src/BridgeTimeoutLayeringSimulation.java && java -cp out BridgeTimeoutLayeringSimulation
 */
public class BridgeTimeoutLayeringSimulation {

    // 四层超时语义(数值不可合并)
    static final long TRANSPORT_READY_MS = 3000;         // waitForBridge:超时仍 resolve,防卡死
    static final long SINGLE_RPC_MS = 15000;             // 单次 RPC 默认
    static final long USER_OP_DISABLE_WEB_TIMER = -1;    // 依赖用户操作:Web 侧不计时
    static final long HTTP_READ_MS = 120000;             // 上传等多图弱网慢操作

    // 每通道独立超时表
    static final Map<String, Long> channelTimeout = Map.of(
            "getDeviceInfo", SINGLE_RPC_MS,
            "requestPayment", USER_OP_DISABLE_WEB_TIMER,  // 等用户操作,Native 关页才结束
            "openGallery", USER_OP_DISABLE_WEB_TIMER,
            "appUploadOss", HTTP_READ_MS);

    public static void main(String[] args) throws InterruptedException {
        System.out.println("=== 四层超时分离 ===");
        System.out.println("  TRANSPORT_READY(waitForBridge) = " + TRANSPORT_READY_MS
                + "ms,超时仍 resolve(防卡死页面)");
        System.out.println("  SINGLE_RPC 默认 = " + SINGLE_RPC_MS + "ms");
        System.out.println("  USER_OP 通道:Web 侧关闭计时(requestPayment/openGallery)");
        System.out.println("  HTTP_READ(appUploadOss) = " + HTTP_READ_MS + "ms(多图压缩+OSS 弱网慢)");

        // 场景1:运输层未在窗口内就绪 → waitForBridge 超时仍 resolve(不卡死)
        System.out.println();
        System.out.println("=== 场景1:waitForBridge 超时仍 resolve ===");
        boolean bridgeReady = false; // 模拟未就绪
        boolean resolved = waitForBridge(bridgeReady, TRANSPORT_READY_MS);
        System.out.println("  桥未就绪,但 waitForBridge 返回: resolved=" + resolved
                + "(页面继续跑,不因桥缺失卡死)");

        // 场景2:requestPayment 是用户操作通道,Web 侧不计时
        System.out.println();
        System.out.println("=== 场景2:用户操作通道关闭 Web 侧计时 ===");
        long t = channelTimeout.get("requestPayment");
        System.out.println("  requestPayment Web 侧计时="
                + (t == USER_OP_DISABLE_WEB_TIMER ? "关闭(等用户操作/Native 关页)" : "开启 " + t + "ms"));
        System.out.println("  若 Web 侧强行计时 15s:用户正在选支付方式 → 15s 到点误判失败 ❌");
        System.out.println("  正确:Web 侧不计时,由 Native 界面关闭事件结束 ✅");

        // 场景3:阶梯 backoff
        System.out.println();
        System.out.println("=== 场景3:阶梯冷却 backoff ===");
        for (long backoff : new long[]{1000, 2000, 4000}) {
            System.out.println("  重试冷却 " + backoff + "ms");
        }

        System.out.println();
        System.out.println("=== 结论 ===");
        System.out.println("  · 运输层就绪 / 单次 RPC / 用户操作 UI / HTTP 读超时 是四件事,必须分层建模");
        System.out.println("  · 用户操作通道禁用 Web 侧计时,否则会把『用户正在操作』误判成超时失败");
    }

    /** 模拟 waitForBridge:到达窗口即返回 true(即使桥仍未就绪),绝不抛异常卡死页面 */
    static boolean waitForBridge(boolean ready, long windowMs) throws InterruptedException {
        long waited = Math.min(windowMs, ready ? 0 : windowMs);
        Thread.sleep(Math.min(waited, 50)); // 演示用,压缩真实等待
        return true; // 关键:超时也返回 true(resolved),不抛、不卡
    }
}

站点构建时间:2026/8/24 23:43:17