Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion harmony/pushy/src/main/ets/PushyTurboModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export class PushyTurboModule extends UITurboModule {
const currentVersionInfo = currentVersion
? this.context.getKv(`hash_${currentVersion}`)
: '';
const isFirstTime = this.context.isFirstTime();
const isFirstTime = this.context.consumeFirstLoadMarker();
const rolledBackVersion = this.context.rolledBackVersion();
const uuid = this.context.getKv('uuid');
const isUsingBundleUrl = this.context.getIsUsingBundleUrl();
Expand Down
28 changes: 26 additions & 2 deletions harmony/pushy/src/main/ets/UpdateContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,15 @@ type FlushablePreferences = preferences.Preferences & {
};

export class UpdateContext {
private static readonly KEY_FIRST_LOAD_MARKED = 'firstLoadMarked';
private context: common.UIAbilityContext;
private rootDir: string;
private preferences!: preferences.Preferences;
private static DEBUG: boolean = false;
private static isUsingBundleUrl: boolean = false;
// 对齐安卓 UpdateContext.java:30。bundleURL 可能在同一进程内被解析多次,
// 首次消费 firstTime 后置 true,避免后续解析误触发 rollback。
private ignoreRollback = false;
Comment on lines +29 to +31

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Make ignoreRollback process-wide, not instance-local.

Line 31 resets to false for every new UpdateContext, but the provider path constructs a new UpdateContext before resolving getBundleUrl(). A second resolution through a new context in the same process can still pass false at Line 392 and re-trigger the rollback this PR is trying to suppress.

Proposed fix
-  private ignoreRollback = false;
+  private static ignoreRollback = false;
...
-      this.ignoreRollback = false;
+      UpdateContext.ignoreRollback = false;
...
-      this.ignoreRollback,
+      UpdateContext.ignoreRollback,
...
-      this.ignoreRollback = true;
+      UpdateContext.ignoreRollback = true;

Also applies to: 379-405

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@harmony/pushy/src/main/ets/UpdateContext.ts` around lines 29 - 31, Make
`ignoreRollback` process-wide instead of being reset per `UpdateContext`
instance; the current `private ignoreRollback = false` in `UpdateContext` lets a
new context in the same process re-enable rollback checks. Update the
`UpdateContext` class so the flag is shared across instances (or stored on a
process-level singleton/static), and ensure `getBundleUrl()` and the rollback
path around `shouldRollback`/`firstTime` consult and update that shared state
consistently so a second resolution in the same process cannot trigger rollback
again.


constructor(context: common.UIAbilityContext) {
this.context = context;
Expand Down Expand Up @@ -262,6 +266,15 @@ export class UpdateContext {
return this.getStateSnapshot().firstTime;
}

public consumeFirstLoadMarker(): boolean {
const marked = this.readBoolean(UpdateContext.KEY_FIRST_LOAD_MARKED, false);
if (marked) {
this.preferences.deleteSync(UpdateContext.KEY_FIRST_LOAD_MARKED);
this.flushPreferences('clear first load marker');
}
return marked;
}

public rolledBackVersion(): string {
return this.getStateSnapshot().rolledBackVersion || '';
}
Expand All @@ -278,6 +291,8 @@ export class UpdateContext {
}

public clearFirstTime(): void {
// 删除在 runStateOperation 的 flush 之前,同批原子落盘。对齐安卓 UpdateContext.java:298。
this.preferences.deleteSync(UpdateContext.KEY_FIRST_LOAD_MARKED);
this.runStateOperation(STATE_OP_CLEAR_FIRST_TIME, '', { cleanUp: true });
}

Expand Down Expand Up @@ -361,6 +376,7 @@ export class UpdateContext {
}

this.runStateOperation(STATE_OP_SWITCH_VERSION, hash);
this.ignoreRollback = false;
} catch (e) {
console.error('Failed to switch version:', e);
throw e;
Expand All @@ -373,12 +389,20 @@ export class UpdateContext {
STATE_OP_RESOLVE_LAUNCH,
this.getStateSnapshot(),
'',
false,
false,
this.ignoreRollback,
true,
);
if (launchState.didRollback || launchState.consumedFirstTime) {
if (launchState.consumedFirstTime) {
// 与 persistState 同批 flush,原子落盘。对齐安卓 UpdateContext.java:373-374。
this.preferences.putSync(UpdateContext.KEY_FIRST_LOAD_MARKED, true);
}
this.persistState(launchState);
}
if (launchState.consumedFirstTime) {
// bundleURL may be resolved multiple times in one process.
this.ignoreRollback = true;
}

let version = launchState.loadVersion || '';
while (version) {
Expand Down