/// 断网场景注入(P3 Task 11,计划偏差登记项)。 /// /// 模拟器上断真实网络不便(后端就在宿主 10.0.2.2,断网=断后端不可分区 /// 观察),按计划改为 **DIO 层故障注入**:包装 App ApiClient 的 /// HttpClientAdapter,闸门关闭期间所有 cn-api 请求立即以 connectionError /// 失败——引擎 initUpload/completeUpload 走该 dio,按 NETWORK_ERROR 分类 /// 进入 waitingNetwork 退避,恢复后重试成功,即覆盖「断网→等待网络→ /// 恢复→续传」语义。 /// /// 边界(有意,登记为偏差):presign PUT 在 Android 走原生 WorkManager /// 桥接(不经 dio),本注入不覆盖该腿;waitingNetwork 判定由 initUpload /// 失败驱动,足以驱动状态机目标分支。 library; import 'dart:typed_data'; import 'package:dio/dio.dart'; /// 故障闸门:`offline=true` 期间所有经该 adapter 的请求立即失败。 class FaultGate { bool offline = false; } /// 包装任意 [HttpClientAdapter] 的故障注入实现。 class FaultInjectingHttpClientAdapter implements HttpClientAdapter { FaultInjectingHttpClientAdapter({required this.gate, required this.inner}); final FaultGate gate; final HttpClientAdapter inner; @override Future fetch( RequestOptions options, Stream? requestStream, Future? cancelFuture, ) async { if (gate.offline) { // 与真实断网同型(connectionError → AppException NETWORK_ERROR), // 立即抛出避免 10s 连接超时拖慢场景。 throw DioException.connectionError( requestOptions: options, reason: 'it fault gate: offline', ); } return inner.fetch(options, requestStream, cancelFuture); } @override void close({bool force = false}) => inner.close(force: force); }