Merge pull request #64 from Microsoft/restart_fix

Updating restartApp and setDeploymentKey
This commit is contained in:
Jonathan Carter
2015-11-24 08:51:15 -08:00
4 changed files with 51 additions and 80 deletions

View File

@@ -6,13 +6,21 @@ var packageMixins = require("./package-mixins")(NativeCodePush);
var requestFetchAdapter = require("./request-fetch-adapter.js");
var Sdk = require("code-push/script/acquisition-sdk").AcquisitionManager;
function checkForUpdate() {
function checkForUpdate(deploymentKey = null) {
var config;
var sdk;
return getConfiguration()
.then((configResult) => {
config = configResult;
// If a deployment key was explicitly provided,
// then let's override the one we retrieved
// from the native-side of the app.
if (deploymentKey) {
config.deploymentKey = deploymentKey;
}
return getSdk();
})
.then((sdkResult) => {
@@ -51,12 +59,10 @@ function checkForUpdate() {
});
}
var isConfigValid = true;
var getConfiguration = (() => {
var config;
return function getConfiguration() {
if (config && isConfigValid) {
if (config) {
return Promise.resolve(config);
} else if (testConfig) {
return Promise.resolve(testConfig);
@@ -64,7 +70,6 @@ var getConfiguration = (() => {
return NativeCodePush.getConfiguration()
.then((configuration) => {
if (!config) config = configuration;
isConfigValid = true;
return config;
});
}
@@ -114,20 +119,6 @@ function log(message) {
console.log(`[CodePush] ${message}`)
}
function restartApp(rollbackTimeout = 0) {
NativeCodePush.restartApp(rollbackTimeout);
}
function setDeploymentKey(deploymentKey) {
return NativeCodePush.setDeploymentKey(deploymentKey)
.then(() => {
// Mark the local copy of the config data
// as invalid since we just modified it
// on the native end.
isConfigValid = false;
});
}
var testConfig;
var testSdk;
@@ -150,6 +141,7 @@ function setUpTestDependencies(providedTestSdk, providedTestConfig, testNativeBr
function sync(options = {}, syncStatusChangeCallback, downloadProgressCallback) {
var syncOptions = {
deploymentKey: null,
ignoreFailedUpdates: true,
installMode: CodePush.InstallMode.ON_NEXT_RESTART,
rollbackTimeout: 0,
@@ -205,7 +197,7 @@ function sync(options = {}, syncStatusChangeCallback, downloadProgressCallback)
return new Promise((resolve, reject) => {
syncStatusChangeCallback(CodePush.SyncStatus.CHECKING_FOR_UPDATE);
checkForUpdate()
checkForUpdate(syncOptions.deploymentKey)
.then((remotePackage) => {
var doDownloadAndInstall = () => {
syncStatusChangeCallback(CodePush.SyncStatus.DOWNLOADING_PACKAGE);
@@ -288,8 +280,7 @@ var CodePush = {
getCurrentPackage: getCurrentPackage,
log: log,
notifyApplicationReady: NativeCodePush.notifyApplicationReady,
restartApp: restartApp,
setDeploymentKey: setDeploymentKey,
restartPendingUpdate: NativeCodePush.restartPendingUpdate,
setUpTestDependencies: setUpTestDependencies,
sync: sync,
InstallMode: {

View File

@@ -116,7 +116,8 @@ static NSString * const PendingUpdateRollbackTimeoutKey = @"rollbackTimeout";
{
// Export the values of the CodePushInstallMode enum
// so that the script-side can easily stay in sync
return @{ @"codePushInstallModeOnNextRestart":@(CodePushInstallModeOnNextRestart),
return @{
@"codePushInstallModeOnNextRestart":@(CodePushInstallModeOnNextRestart),
@"codePushInstallModeImmediate": @(CodePushInstallModeImmediate),
@"codePushInstallModeOnNextResume": @(CodePushInstallModeOnNextResume)
};
@@ -243,8 +244,8 @@ static NSString * const PendingUpdateRollbackTimeoutKey = @"rollbackTimeout";
// JavaScript-exported module methods
RCT_EXPORT_METHOD(downloadUpdate:(NSDictionary*)updatePackage
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{
[CodePushPackage downloadPackage:updatePackage
progressCallback:^(long expectedContentLength, long receivedContentLength) {
@@ -273,13 +274,13 @@ RCT_EXPORT_METHOD(downloadUpdate:(NSDictionary*)updatePackage
}
RCT_EXPORT_METHOD(getConfiguration:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
rejecter:(RCTPromiseRejectBlock)reject)
{
resolve([[CodePushConfig current] configuration]);
}
RCT_EXPORT_METHOD(getCurrentPackage:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
rejecter:(RCTPromiseRejectBlock)reject)
{
dispatch_async(dispatch_get_main_queue(), ^{
NSError *error;
@@ -293,10 +294,10 @@ RCT_EXPORT_METHOD(getCurrentPackage:(RCTPromiseResolveBlock)resolve
}
RCT_EXPORT_METHOD(installUpdate:(NSDictionary*)updatePackage
rollbackTimeout:(int)rollbackTimeout
installMode:(CodePushInstallMode)installMode
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
rollbackTimeout:(int)rollbackTimeout
installMode:(CodePushInstallMode)installMode
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSError *error;
@@ -318,8 +319,8 @@ RCT_EXPORT_METHOD(installUpdate:(NSDictionary*)updatePackage
}
RCT_EXPORT_METHOD(isFailedUpdate:(NSString *)packageHash
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject)
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject)
{
BOOL isFailedHash = [self isFailedHash:packageHash];
resolve(@(isFailedHash));
@@ -345,16 +346,16 @@ RCT_EXPORT_METHOD(notifyApplicationReady:(RCTPromiseResolveBlock)resolve
resolve([NSNull null]);
}
RCT_EXPORT_METHOD(restartApp:(int)rollbackTimeout){
// This function is exposed solely for immediately installed
// update support, and shouldn't be consumed directly by user code.
RCT_EXPORT_METHOD(restartImmedidateUpdate:(int)rollbackTimeout)
{
[self initializeUpdateWithRollbackTimeout:rollbackTimeout needsRestart:YES];
}
RCT_EXPORT_METHOD(setDeploymentKey:(NSString *)deploymentKey
resolve:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
RCT_EXPORT_METHOD(restartPendingUpdate)
{
[[CodePushConfig current] setDeploymentKey:deploymentKey];
resolve(nil);
[self checkForPendingUpdate:YES];
}
RCT_EXPORT_METHOD(setUsingTestFolder:(BOOL)shouldUseTestFolder)
@@ -362,4 +363,4 @@ RCT_EXPORT_METHOD(setUsingTestFolder:(BOOL)shouldUseTestFolder)
usingTestFolder = shouldUseTestFolder;
}
@end
@end

View File

@@ -124,18 +124,17 @@ When you require the `react-native-code-push` module, that object provides the f
* [checkForUpdate](#codepushcheckforupdate): Queries the CodePush service for an update against the configured deployment. This method returns a promise which resolves to a `RemotePackage` that can be subsequently downloaded.
* [getCurrentPackage](#codepushgetcurrentpackage): Gets information about the currently installed package (e.g. description, installation time)
* [notifyApplicationReady](#codepushnotifyapplicationready): Notifies the CodePush runtime that an installed update is considered successful. This is an optional API, but is useful when you want to expicitly enable "rollback protection" in the event that an exception occurs in any code that you've deployed to production
* [restartApp](#codepushrestartapp): Installs a pending update by immediately restarting the app.
* [setDeploymentKey](#codepushsetdeploymentkey): Dynamically updates the deployment key that the CodePush runtime will use to query for app updates.
* [notifyApplicationReady](#codepushnotifyapplicationready): Notifies the CodePush runtime that an installed update is considered successful. This is an optional API, but is useful when you want to expicitly enable "rollback protection" in the event that an exception occurs in any code that you've deployed to production.
* [restartPendingUpdate](#codepushrestartPendingUpdate): Conditionally restarts the app if a previously installed update is currently pending (e.g. it was installed using the `ON_NEXT_RESTART` or `ON_NEXT_RESUME` modes, and the user hasn't restarted or resumed the app yet).
* [sync](#codepushsync): Allows checking for an update, downloading it and installing it, all with a single call. Unless you need custom UI and/or behavior, we recommend most developers to use this method when integrating CodePush into their apps
#### codePush.checkForUpdate
```javascript
codePush.checkForUpdate(): Promise<RemotePackage>;
codePush.checkForUpdate(deploymentKey: String = null): Promise<RemotePackage>;
```
Queries the CodePush service for an update against the configured deployment. This method returns a promise which resolves to a `RemotePackage` that can be subsequently downloaded.
Queries the CodePush service for an update using the deployment configured either in your `Info.plist` file or specified using the optional `deploymentKey` parameter. This method returns a promise which resolves to a `RemotePackage` that can be subsequently downloaded.
`checkForUpdate` returns a Promise that resolves to one of two values:
@@ -175,39 +174,18 @@ Notifies the CodePush runtime that an update is considered successful, and there
If the `rollbackTimeout` parameter was not specified, the CodePush runtime will not enforce any automatic rollback behavior, and therefore, calling this function is not required and will result in a no-op.
#### codePush.restartApp
```javascript
codePush.restartApp(rollbackTimeout: Number = 0): void;
```
Installs the pending update (if applicable) by immediately restarting the app, and optionally starting the rollback timer. This method is for advanced scenarios, and is useful when the following conditions are true:
1. Your app is specifying an install mode value of `ON_NEXT_RESTART` when calling `sync` or `LocalPackage.install`, which has the effect of not applying your update until the app has been restarted (by either the end-user or OS)
2. You have an app-specific user event (e.g. the end-user navigated back to the app's home page) that allows you to apply the update in an unobtrusive way, and potentially gets the update in front of the end-user sooner then waiting until the next restart.
The `rollbackTimeout` parameter has the same behavior as the equivalent in the `sync` and `checkForUpdate` method, and allows your app to have control over the point that an update is installed, while still benefitting from rollback production.
#### codePush.setDeploymentKey
```javascript
codePush.setDeploymentKey(deploymentKey: String): Promise<void>;
```
Dynamically updates the deployment key that the CodePush runtime will use to query for app updates. This is beneficial if your app has a default deployment key which you added to your `Info.plist` file, but you want to dynamically change it at runtime based on some app-specific policy (e.g. you want to give early access to certain users, by pointing them at your staging deployment).
The method simply takes a string representing the new deployment, and returns a `Promise` that will resolve once the specified deployment key has been applied, and calls to `sync` and/or `checkForUpdate` could be successfully called.
Example Usage:
```javascript
codePush.setDeploymentKey("SOME_VALID_KEY_VALUE").then(() => {
// The following call to sync with query the updated
// app deployment for an update
codePush.sync();
});
```
#### codePush.restartPendingUpdate
```javascript
codePush.restartPendingUpdate(): void;
```
Installs the pending update (if applicable) by immediately restarting the app, and optionally starting the rollback timer. This method is for advanced scenarios, and is only useful when the following conditions are true:
1. Your app is specifying an install mode value of `ON_NEXT_RESTART` or `ON_NEXT_RESUME` when calling the `sync` or `LocalPackage.install` methods. This has the effect of not applying your update until the app has been restarted (by either the end-user or OS) or resumed, and therefore, the update won't be immediately displayed to the end-user .
2. You have an app-specific user event (e.g. the end-user navigated back to the app's home route) that allows you to apply the update in an unobtrusive way, and potentially gets the update in front of the end-user sooner then waiting until the next restart or resume.
If you call this method, and there isn't a pending update, it will result in a no-op. Otherwise, the app will be restarted in order to display the update to the end-user.
#### codePush.sync
@@ -226,6 +204,7 @@ If you want to pivot whether you check and/or download an available update based
The method accepts an options object that allows you to customize numerous aspects of the default behavior, all of which provide sensible values by default:
* __deploymentKey__ (String) - Specifies the deployment key you want to query for an update against. By default, this value is derived from the `Info.plist` file, but this option allows you to override it from the script-side if you need to dynamically change your app's current deployment.
* __ignoreFailedUpdates__ (Boolean) - Indicates whether you would like to automatically ignored updates which are available, but have been previously attemped to install, but failed. Defaults to `true`.
* __installMode__ (CodePush.InstallMode) - Indicates whether you would like to restart the app immediately after the update has been installed, or wait until the next app resume or restart. Defaults to `CodePush.InstallMode.ON_NEXT_RESTART`
* __rollbackTimeout__ (Number) - The number of seconds that you want the runtime to wait after an update has been installed before considering it failed and rolling it back. Defaults to `0`, which disables rollback protection.

View File

@@ -40,8 +40,8 @@ module.exports = (NativeCodePush) => {
.then(function() {
updateInstalledCallback && updateInstalledCallback();
if (installMode == NativeCodePush.codePushInstallModeImmediate) {
NativeCodePush.restartApp(rollbackTimeout);
}
NativeCodePush.restartImmedidateUpdate(rollbackTimeout);
};
});
}
};