diff --git a/src/apps.js b/src/apps.js index ea03b0e02..019bf8f52 100644 --- a/src/apps.js +++ b/src/apps.js @@ -604,20 +604,31 @@ function scheduleTask(appId, installationState, taskId, callback) { assert.strictEqual(typeof taskId, 'string'); assert.strictEqual(typeof callback, 'function'); - appTaskManager.scheduleTask(appId, taskId, function (error) { - debug(`scheduleTask: task ${taskId} of ${appId} completed`); - if (error && (error.code === tasks.ECRASHED || error.code === tasks.ESTOPPED)) { // if task crashed, update the error - debug(`Apptask crashed/stopped: ${error.message}`); - let boxError = new BoxError(BoxError.TASK_ERROR, error.message); - boxError.details.crashed = error.code === tasks.ECRASHED; - boxError.details.stopped = error.code === tasks.ESTOPPED; - // see also apptask makeTaskError - boxError.details.taskId = taskId; - boxError.details.installationState = installationState; - appdb.update(appId, { installationState: exports.ISTATE_ERROR, error: boxError.toPlainObject(), taskId: null }, callback); - } else if (!(installationState === exports.ISTATE_PENDING_UNINSTALL && !error)) { // clear out taskId except for successful uninstall - appdb.update(appId, { taskId: null }, callback); + settings.getBackupConfig(function (error, backupConfig) { + if (error) return callback(error); + + let memoryLimit = 400; + if (installationState === exports.ISTATE_PENDING_BACKUP || installationState === exports.ISTATE_PENDING_CLONE || installationState === exports.ISTATE_PENDING_RESTORE) { + memoryLimit = 'memoryLimit' in backupConfig ? Math.max(backupConfig.memoryLimit/1024/1024, 400) : 400; } + + const options = { timeout: 20 * 60 * 60 * 1000 /* 20 hours */, nice: 15, memoryLimit }; + + appTaskManager.scheduleTask(appId, taskId, options, function (error) { + debug(`scheduleTask: task ${taskId} of ${appId} completed`); + if (error && (error.code === tasks.ECRASHED || error.code === tasks.ESTOPPED)) { // if task crashed, update the error + debug(`Apptask crashed/stopped: ${error.message}`); + let boxError = new BoxError(BoxError.TASK_ERROR, error.message); + boxError.details.crashed = error.code === tasks.ECRASHED; + boxError.details.stopped = error.code === tasks.ESTOPPED; + // see also apptask makeTaskError + boxError.details.taskId = taskId; + boxError.details.installationState = installationState; + appdb.update(appId, { installationState: exports.ISTATE_ERROR, error: boxError.toPlainObject(), taskId: null }, callback); + } else if (!(installationState === exports.ISTATE_PENDING_UNINSTALL && !error)) { // clear out taskId except for successful uninstall + appdb.update(appId, { taskId: null }, callback); + } + }); }); } diff --git a/src/apptaskmanager.js b/src/apptaskmanager.js index bfbe3c5a1..f6be87394 100644 --- a/src/apptaskmanager.js +++ b/src/apptaskmanager.js @@ -37,9 +37,10 @@ function initializeSync() { } // callback is called when task is finished -function scheduleTask(appId, taskId, callback) { +function scheduleTask(appId, taskId, options, callback) { assert.strictEqual(typeof appId, 'string'); assert.strictEqual(typeof taskId, 'string'); + assert.strictEqual(typeof options, 'object'); assert.strictEqual(typeof callback, 'function'); if (!gInitialized) initializeSync(); @@ -72,8 +73,7 @@ function scheduleTask(appId, taskId, callback) { scheduler.suspendJobs(appId); - // TODO: set memory limit for app backup task - tasks.startTask(taskId, { logFile, timeout: 20 * 60 * 60 * 1000 /* 20 hours */, nice: 15 }, function (error, result) { + tasks.startTask(taskId, Object.assign(options, { logFile }), function (error, result) { callback(error, result); delete gActiveTasks[appId];