Repository navigation
feat(native): 三端统一持久化落盘格式并一次性迁移 - #691
Conversation
Every platform now keeps the same keys with the same value encoding in two stores of its own, pushy_state and pushy_cache (Android SharedPreferences files, iOS NSUserDefaults suites, Harmony preferences): every value is a string, booleans are "1"/"0", markers are "1" while set, and the state store carries schemaVersion. scripts/contract.ts (storeSchema, stateFields, storedItems, legacyLayouts) is the single source; the generator emits each platform's key table and State <-> store mapping and the C++ legacy tables. The one-time move out of the layouts SDKs up to 10.61 wrote is a shared pure function, cpp/patch_core/stored_items.h MigrateStoredItems, pinned by stored-items-vectors.json. It carries only what a binary upgrade keeps (uuid, native config, round breadcrumb, bundle hash cache) plus the binary identity: the new layout ships in a new binary, whose release buildTime always changes, so its first launch resets the update state anyway. Puts end with the schema, legacy keys are deleted only after the puts are durable, the store always wins over the legacy value, and a store a later SDK wrote is left alone. A migration that cannot run falls back to a fresh store that still carries the uuid and retries on the next launch. iOS moves off standardUserDefaults into its own suites: no collisions with host keys, no wipe when the host clears its defaults domain. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Important Review skippedReview was skipped as selected files did not have any reviewable changes. ⛔ Files ignored due to path filters: 4
⚙️ Run configuration
⛔ Files ignored due to path filters: 4
You can disable this status message by setting the Use the checkbox below for a quick retry:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
📝 Walkthrough
Merge Risk: ⚪ Minimal · up to
|
Bump package.json and harmony/pushy/oh-package.json5 together, with the bilingual release notes. Ships everything since 10.61.0: one persisted layout on every platform with a one-time migration (#691), the UIScene life cycle in the iOS examples (#692) and the CI actions bump (#690). Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
概要
三端(Android、iOS、鸿蒙)改用同一份持久化布局(schema 1),并在首次以新格式启动时一次性迁移旧布局。设计与降级说明见
docs/STORED_STATE_LAYOUT.md。pushy_state/pushy_cache(Android SharedPreferences 文件、iOSNSUserDefaultssuite、鸿蒙 preferences)。键名三端一致;值一律是字符串,布尔"1"/"0",标记置位时存"1"、清除即删键,空串不落盘;状态存储带schemaVersion。响应缓存单独放在pushy_cache(三端存储都是整文件重写,Android 原本就这样,现在三端对齐)。scripts/contract.ts新增storeSchema/stateFields/legacyLayouts,storedItems改为三端同名的物理键;生成器产出 JavaStoreSchema、ArkTSStoreSchema.ts、iOSRCTPushyState.mm的键表与 State ↔ 存储读写映射、各端 reset/升级清理清单,以及 C++ 的旧布局表(带 update 字样的旧键自动编码)。syncStorageKeys并入storedItems。cpp/patch_core/stored_items.h的MigrateStoredItems(layout, legacy, current) -> {puts, removes, schemaVersion, migrated},纯函数,三端只做 KV IO(Android 走新 JNIStoreMigration.migrateStoredItems,鸿蒙走新 NAPImigrateStoredItems,iOS 直接调用)。按目录自动收录进三端构建。迁移策略
uuid、nativeConfig、nativeCheckIncomplete、bundleHashCache,外加packageVersion/buildTime(让升级照常由SyncBinaryVersion判定)。已核实:三端 release 构建每次都会写入新的 buildTime(Android gradle resValue、iOS podspec 脚本阶段、鸿蒙 hvigor 插件),带新 SDK 的二进制第一次启动必然被判为升级、清空热更状态,所以热更状态、版本元信息、启动标记、响应缓存直接删除,不做翻译。例外是 debug 构建(三端 buildTime 都固定为"0"):迁移后回到内置包,只影响开发期。schemaVersion结尾;新存储里已有的值不覆盖(新存储优先);旧键只在 puts 落盘后删除(Android 一次 commit、鸿蒙 flush 成功后、iOS 写入返回即已交给 cfprefsd);看到当前 schema 时只清理残留旧键;看到更高的 schema 两个存储都不碰。C++ 测试对每个向量的每个前缀都验证了重入结果一致。uuid搬过去,不写 schema,下次启动重做完整迁移。blockUntil、REACTNATIVECN_PUSHY_BLOCKUPDATE等)与hash_前缀;iOS 旧存储与宿主共用,早期无前缀的packageVersion/buildTime可能属于宿主,不读不删。降级行为
装回旧二进制时旧键已删除,旧二进制表现为全新安装:无热更版本、无原生配置(JS 运行后会重新同步),
uuid由 JS 重新生成(降级期间灰度分桶会变)。再升级回来时新存储的 schema 仍在,不再迁移,降级期间旧二进制写的键被清掉,uuid恢复为降级前的值。App Store / 应用市场不允许降级,只出现在侧载、adb install -d等场景;为此保留旧uuid键会违背“迁移后删除旧键”,权衡后不保留。iOS 改用独立 suite 的取舍
换成
initWithSuiteName:@"pushy_state"/@"pushy_cache":避免与宿主键冲突(无前缀packageVersion/buildTime曾撞键导致每次启动清掉热更);宿主常见的“退出登录清 defaults 域”不再连带抹掉 uuid 与热更状态;hash_*前缀清理不再遍历宿主的全部 defaults;三端可用同一组无前缀键名。代价是多一个 plist(同在Library/Preferences,备份行为不变,隐私清单CA92.1照样覆盖)以及本次迁移。不变的部分
热更行为、JS API、服务端协议都不变;状态转移仍在
state_core.cpp。验证(本地)
test-patch-core.sh(含 ASan/UBSan)新增stored_items_test:12 个向量的计划、应用后的两个存储、再规划为空、任一前缀被杀后重入;test-update-flow-core.sh、test-core-platform-flags.sh通过。.so(verify-android-so通过);JVM 单测全绿,新增StoreMigrationTest(按向量回放迁移 IO、提交失败保留旧键、内核失败只搬 uuid、State 映射往返)。test-ios-purge-restore.sh(VERIFY_REGRESSIONS=1)全绿,新增stored_items_vectors(真实内核 + 真实PushyMigrateStores)、legacy_migration_upgrade/_same_binary/_write_failure/_read_failure,负向对照skip-carry、remove-first均被抓到;全部 RCTPushy 源文件对 RN 头文件-fsyntax-only通过。harmonyStateLifecycle.test.ts按向量回放migrateStore并覆盖落盘失败、内核失败;DevEco clang 编译pushy.cpp通过;check-harmony-types通过。bun run lint(含生成器--check)、bun test(473 个)、check-packlist通过。bundle-hash.test.ts改为读新的pushy_state存储。🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need.Summary by CodeRabbit