合并 resolveAudio 进 resolve():所有 RemoteConfig 字段走单一入口 + 同款 4 层 fallback
【动机】 上个 commit 把 audio_domain/audio_bucket 改成 4 层 fallback,但用了独立的 resolveAudio() 入口 —— 与 resolve() 并存意味着调用方要记两个 API,违反 "统一接口"原则。 【方案】 - ResolvedVersion 加 audioDomain / audioBucket 两个字段(扁平结构) - resolve() 内直接 pickString(chain, \.audioDomain) ?? config.audioDomain 一次解出 - 删除 resolveAudio() 公开入口 - WebContainerViewController parsed 分支:单次 resolve() 调用 + 同一 r 取所有字段 【硬约束(Plan ADR-009 同步)】 远端 RemoteConfig 所有字段必须走 VersionResolver.resolve(...) 单一入口、 同一套 4 层 fallback;新增字段时加进协议 + 节点 struct + ResolvedVersion + 一行 pickString,不允许为某字段单独写 if 链或 helper。 BuildProject 通过。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
a54d1511be
commit
485f0c6679
@@ -1259,8 +1259,11 @@ ResolvedVersion(
|
||||
| 微信 AppID | `Info.plist` 的 CFBundleURLTypes (URLName=weixin 首个 scheme) | iOS 系统级 URL Scheme 注册,运行期不可注入,Info.plist 是事实唯一可写位置 |
|
||||
| 应用级凭证(微信 AppSecret、七牛 AccessKey、七牛 SecretKey) | `AppSecrets.plist` | 跨渠道相同的应用全局凭证;与渠道差异化字段语义分离 |
|
||||
| 七牛 CDN 域名、bucket 名 | RemoteConfig 顶层 / 4 层节点任一处 `audio_domain` / `audio_bucket`(4 层 fallback + 顶层兜底) | 后台运维管理,按渠道差异化下发 |
|
||||
- **远端注入时序**:`WebContainerViewController` 在 `parsed` 分支(即 RemoteConfig 拉到、IPA 校验前)调 `VersionResolver.resolveAudio(...)` 解析(与版本字段同款 4 层 fallback:agent → game → channel → market 倒序找第一个非空,整链空时 fallback 到顶层 `audio_domain` / `audio_bucket`),再 `await QiniuConfig.shared.update(cdnDomain:bucketName:)` 注入;缺失抛 `BootError.audioConfigMissing`,与 showmessage 同等致命,弹 modal 永停
|
||||
- **2026-06-27 修订**:初版 `audio_domain` / `audio_bucket` 只从 RemoteConfig 顶层读取,实测渠道方习惯把这俩字段放 agent 节点下 → 客户端读不到误报"音频服务暂不可用"。改为 4 层 fallback + 顶层兜底(同 `app_version` / `game_zip` 等版本字段的 fallback 算法),节点与顶层任一处声明即可
|
||||
- **远端注入时序**:`WebContainerViewController` 在 `parsed` 分支(即 RemoteConfig 拉到、IPA 校验前)调 `VersionResolver.resolve(...)` 一次得到所有字段(含 `audioDomain` / `audioBucket`),再 `await QiniuConfig.shared.update(cdnDomain:bucketName:)` 注入;缺失抛 `BootError.audioConfigMissing`,与 showmessage 同等致命,弹 modal 永停
|
||||
- **统一接口(硬约束)**:远端 RemoteConfig 所有字段的获取**必须**走 `VersionResolver.resolve(...)` 单一入口、走同一套 4 层 fallback:agent → game → channel → market 倒序找第一个非空,整链空时 fallback 到 RemoteConfig 顶层。不允许新增字段时为它单独写 if 链或 helper —— 加进 `RemoteConfigNode` 协议 + 4 个节点 struct + `ResolvedVersion` + `resolve()` 内一行 `pickString(chain, \.xxx) ?? config.xxx`
|
||||
- **2026-06-27 修订**:
|
||||
- 初版 `audio_domain` / `audio_bucket` 只从 RemoteConfig 顶层读取,实测渠道方习惯把这俩字段放 agent 节点下 → 客户端读不到误报"音频服务暂不可用"。改为 4 层 fallback + 顶层兜底(同 `app_version` / `game_zip` 等字段算法)。
|
||||
- 同日二次:曾短暂拆 `resolve()` / `resolveAudio()` 两个公开入口,违反"单一接口"原则。已合并为单一 `resolve()`,所有字段(版本 + 音频 + showmessage)一次返回
|
||||
- **类型设计**:
|
||||
- `AppSecrets`:与 `BundleConfig` 同款 `nonisolated public final class Sendable`,3 个不可变 String 属性
|
||||
- `QiniuConfig`:从 `enum` 改为 `actor`,`accessKey`/`secretKey` 仍 nonisolated(直接读 `AppSecrets.shared`),`cdnDomain`/`bucketName` 进 actor 状态;`update(...)` / `publicURL(...)` async
|
||||
|
||||
Reference in New Issue
Block a user