Skip to content

Commit 79d22a3

Browse files
authored
Await download status report before resolving download() (#16)
Previously reportStatusDownload was fire-and-forget: download() resolved as soon as the native download finished, without waiting for the report_status/download HTTP call to complete. This let install() (and a potential immediate-mode reload) run ahead of the report, so if the app reloaded or was killed first, the download report was silently lost. Now the report is awaited, with errors caught locally so a failed report never blocks or breaks the install flow. This adds a small delay to download() resolving, which is an acceptable tradeoff since most installs are backgrounded, and even in immediate mode the wait is dominated by the download itself. Also adds a clarifying comment to reportStatusDeploy noting that deployedPackage/status are null for the binary-update report case.
1 parent b4bf0ad commit 79d22a3

2 files changed

Lines changed: 24 additions & 5 deletions

File tree

package-mixins.js

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,23 @@
11
import { NativeEventEmitter } from "react-native";
22
import log from "./logging";
33

4+
// Reporting this event is important, but avoid blocking install()/restartApp() indefinitely
5+
// on a stalled network request.
6+
const REPORT_STATUS_DOWNLOAD_TIMEOUT_MS = 5000;
7+
8+
async function withTimeout(promise, timeoutMs) {
9+
let timer;
10+
const timeout = new Promise((_, reject) => {
11+
timer = setTimeout(() => reject(new Error(`Timed out after ${timeoutMs}ms`)), timeoutMs);
12+
});
13+
14+
try {
15+
return await Promise.race([promise, timeout]);
16+
} finally {
17+
clearTimeout(timer);
18+
}
19+
}
20+
421
// This function is used to augment remote and local
522
// package objects with additional functionality/properties
623
// beyond what is included in the metadata sent by the server.
@@ -31,10 +48,11 @@ module.exports = (NativeCodePush) => {
3148
const downloadedPackage = await NativeCodePush.downloadUpdate(updatePackageCopy, !!downloadProgressCallback);
3249

3350
if (reportStatusDownload) {
34-
reportStatusDownload(this)
35-
.catch((err) => {
51+
try {
52+
await withTimeout(reportStatusDownload(this), REPORT_STATUS_DOWNLOAD_TIMEOUT_MS);
53+
} catch (err) {
3654
log(`Report download status failed: ${err}`);
37-
});
55+
}
3856
}
3957

4058
return { ...downloadedPackage, ...local };
@@ -65,4 +83,4 @@ module.exports = (NativeCodePush) => {
6583
};
6684

6785
return { local, remote };
68-
};
86+
};

src/acquisition-sdk/acquisition-sdk.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ export class AcquisitionManager {
166166
});
167167
}
168168

169+
// Note: deployedPackage and status are null when reporting a "binary update" (i.e. the app was updated through the app store, not CodePush)
169170
public reportStatusDeploy(deployedPackage?: Package, status?: string, previousLabelOrAppVersion?: string, previousDeploymentKey?: string, callback?: Callback<void>): void {
170171
if (AcquisitionManager._apiCallsDisabled) {
171172
console.log(`[CodePush] Api calls are disabled, skipping API call`);
@@ -289,4 +290,4 @@ function queryStringify(object: Object): string {
289290
}
290291

291292
return queryString;
292-
}
293+
}

0 commit comments

Comments
 (0)