Make the failure backoff time the same as the appUpdatePollTime

Change-type: patch
Signed-off-by: Cameron Diver <cameron@balena.io>
This commit is contained in:
Cameron Diver 2019-02-05 11:46:49 +00:00
parent 146267b402
commit 828a0fc345
No known key found for this signature in database
GPG Key ID: 49690ED87032539F
4 changed files with 22 additions and 9 deletions

View File

@ -64,7 +64,7 @@ createApplicationManagerRouter = (applications) ->
module.exports = class ApplicationManager extends EventEmitter
constructor: ({ @logger, @config, @db, @eventTracker, @deviceState }) ->
@docker = new Docker()
@images = new Images({ @docker, @logger, @db })
@images = new Images({ @docker, @logger, @db, @config })
@services = new ServiceManager({ @docker, @logger, @images, @config })
@networks = new NetworkManager({ @docker, @logger })
@volumes = new Volumes({ @docker, @logger })
@ -74,6 +74,11 @@ module.exports = class ApplicationManager extends EventEmitter
@fetchesInProgress = 0
@_targetVolatilePerImageId = {}
@_containerStarted = {}
@config.on 'change', (changedConfig) =>
if changedConfig.appUpdatePollInterval
@images.appUpdatePollInterval = changedConfig.appUpdatePollInterval
@actionExecutors = {
stop: (step, { force = false, skipLock = false } = {}) =>
@_lockingIfNecessary step.current.appId, { force, skipLock: skipLock or step.options?.skipLock }, =>
@ -178,7 +183,10 @@ module.exports = class ApplicationManager extends EventEmitter
@emit('change', data)
init: =>
@images.cleanupDatabase()
@config.get('appUpdatePollInterval')
.then (interval) =>
@images.appUpdatePollInterval = interval
@images.cleanupDatabase()
.then =>
@localModeManager.init()
.then =>

View File

@ -4,6 +4,7 @@ import { EventEmitter } from 'events';
import * as _ from 'lodash';
import StrictEventEmitter from 'strict-event-emitter-types';
import Config from '../config';
import Database from '../db';
import * as constants from '../lib/constants';
import {
@ -27,6 +28,7 @@ interface ImageConstructOpts {
docker: DockerUtils;
logger: Logger;
db: Database;
config: Config;
}
interface FetchProgressEvent {
@ -65,6 +67,8 @@ export class Images extends (EventEmitter as {
private logger: Logger;
private db: Database;
public appUpdatePollInterval: number;
private imageFetchFailures: Dictionary<number> = {};
private imageFetchLastFailureTime: Dictionary<
ReturnType<typeof process.hrtime>
@ -92,7 +96,7 @@ export class Images extends (EventEmitter as {
// engine, and ensure that we wait a bit lnger
const minDelay = Math.min(
2 ** this.imageFetchFailures[image.name] * constants.backoffIncrement,
constants.maxBackoffTime,
this.appUpdatePollInterval,
);
const timeSinceLastError = process.hrtime(
this.imageFetchLastFailureTime[image.name],

View File

@ -138,11 +138,11 @@ module.exports = class DeviceState extends EventEmitter
@applications.on('change', @reportCurrentState)
healthcheck: =>
@config.getMany([ 'appUpdatePollInterval', 'unmanaged' ])
@config.getMany([ 'unmanaged' ])
.then (conf) =>
cycleTime = process.hrtime(@lastApplyStart)
cycleTimeMs = cycleTime[0] * 1000 + cycleTime[1] / 1e6
cycleTimeWithinInterval = cycleTimeMs - @applications.timeSpentFetching < 2 * conf.appUpdatePollInterval
cycleTimeWithinInterval = cycleTimeMs - @applications.timeSpentFetching < 2 * @maxPollTime
applyTargetHealthy = conf.unmanaged or !@applyInProgress or @applications.fetchesInProgress > 0 or cycleTimeWithinInterval
return applyTargetHealthy
@ -249,13 +249,16 @@ module.exports = class DeviceState extends EventEmitter
@logger.enable(changedConfig.loggingEnabled)
if changedConfig.apiSecret?
@reportCurrentState(api_secret: changedConfig.apiSecret)
if changedConfig.appUpdatePollInterval?
@maxPollTime = changedConfig.appUpdatePollInterval
@config.getMany([
'initialConfigSaved', 'listenPort', 'apiSecret', 'osVersion', 'osVariant',
'version', 'provisioned', 'apiEndpoint', 'connectivityCheckEnabled', 'legacyAppsPresent',
'targetStateSet', 'unmanaged'
'targetStateSet', 'unmanaged', 'appUpdatePollInterval'
])
.then (conf) =>
@maxPollTime = conf.appUpdatePollInterval
@applications.init()
.then =>
if !conf.initialConfigSaved
@ -570,7 +573,7 @@ module.exports = class DeviceState extends EventEmitter
if @scheduledApply?
console.log("Updating failed, but there's another update scheduled immediately: ", err)
else
delay = Math.min((2 ** @failedUpdates) * constants.backoffIncrement, constants.maxBackoffTime)
delay = Math.min((2 ** @failedUpdates) * constants.backoffIncrement, @maxPollTime)
# If there was an error then schedule another attempt briefly in the future.
console.log('Scheduling another update attempt due to failure: ', delay, err)
@triggerApplyTarget({ force, delay, initial })

View File

@ -53,8 +53,6 @@ const constants = {
// Use this failure multiplied by 2**Number of failures to increase
// the backoff on subsequent failures
backoffIncrement: 500,
// The maximum time to backoff on repeated failure
maxBackoffTime: 30000,
};
if (process.env.DOCKER_HOST == null) {