mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2025-02-22 18:22:41 +00:00
Back off fetching the target state exponentially, for faster retries when there's no connectivity
Change-Type: patch Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
This commit is contained in:
parent
caca29f3a0
commit
72a5f03b0c
@ -8,7 +8,7 @@ express = require 'express'
|
|||||||
bodyParser = require 'body-parser'
|
bodyParser = require 'body-parser'
|
||||||
Lock = require 'rwlock'
|
Lock = require 'rwlock'
|
||||||
{ request, requestOpts } = require './lib/request'
|
{ request, requestOpts } = require './lib/request'
|
||||||
{ checkTruthy } = require './lib/validation'
|
{ checkTruthy, checkInt } = require './lib/validation'
|
||||||
|
|
||||||
DuplicateUuidError = (err) ->
|
DuplicateUuidError = (err) ->
|
||||||
_.startsWith(err.message, '"uuid" must be unique')
|
_.startsWith(err.message, '"uuid" must be unique')
|
||||||
@ -26,6 +26,7 @@ createAPIBinderRouter = (apiBinder) ->
|
|||||||
apiBinder.eventTracker.track('Update notification')
|
apiBinder.eventTracker.track('Update notification')
|
||||||
if apiBinder.readyForUpdates
|
if apiBinder.readyForUpdates
|
||||||
apiBinder.getAndSetTargetState(req.body.force)
|
apiBinder.getAndSetTargetState(req.body.force)
|
||||||
|
.catchReturn()
|
||||||
res.sendStatus(204)
|
res.sendStatus(204)
|
||||||
return router
|
return router
|
||||||
|
|
||||||
@ -40,6 +41,7 @@ module.exports = class APIBinder
|
|||||||
@_targetStateInterval = null
|
@_targetStateInterval = null
|
||||||
@reportPending = false
|
@reportPending = false
|
||||||
@stateReportErrors = 0
|
@stateReportErrors = 0
|
||||||
|
@targetStateFetchErrors = 0
|
||||||
@router = createAPIBinderRouter(this)
|
@router = createAPIBinderRouter(this)
|
||||||
_lock = new Lock()
|
_lock = new Lock()
|
||||||
@_writeLock = Promise.promisify(_lock.async.writeLock)
|
@_writeLock = Promise.promisify(_lock.async.writeLock)
|
||||||
@ -332,27 +334,31 @@ module.exports = class APIBinder
|
|||||||
.then =>
|
.then =>
|
||||||
@lastTarget = _.cloneDeep(targetState)
|
@lastTarget = _.cloneDeep(targetState)
|
||||||
@deviceState.triggerApplyTarget({ force })
|
@deviceState.triggerApplyTarget({ force })
|
||||||
.catch (err) ->
|
.tapCatch (err) ->
|
||||||
console.error("Failed to get target state for device: #{err}")
|
console.error("Failed to get target state for device: #{err}")
|
||||||
.finally =>
|
.finally =>
|
||||||
@lastTargetStateFetch = process.hrtime()
|
@lastTargetStateFetch = process.hrtime()
|
||||||
|
|
||||||
_pollTargetState: =>
|
_pollTargetState: =>
|
||||||
|
@getAndSetTargetState()
|
||||||
|
.then =>
|
||||||
|
@targetStateFetchErrors = 0
|
||||||
|
@config.get('appUpdatePollInterval')
|
||||||
|
.catch =>
|
||||||
|
@targetStateFetchErrors += 1
|
||||||
@config.get('appUpdatePollInterval')
|
@config.get('appUpdatePollInterval')
|
||||||
.then (appUpdatePollInterval) =>
|
.then (appUpdatePollInterval) =>
|
||||||
if @_targetStateInterval?
|
Math.min(appUpdatePollInterval, 15000 * 2 ** (@targetStateFetchErrors - 1))
|
||||||
clearInterval(@_targetStateInterval)
|
.then(checkInt)
|
||||||
@_targetStateInterval = setInterval(@getAndSetTargetState, appUpdatePollInterval)
|
.then(Promise.delay)
|
||||||
@getAndSetTargetState()
|
.then(@_pollTargetState)
|
||||||
return null
|
|
||||||
|
|
||||||
startTargetStatePoll: ->
|
startTargetStatePoll: =>
|
||||||
|
Promise.try =>
|
||||||
if !@resinApi?
|
if !@resinApi?
|
||||||
throw new Error('Trying to start poll without initializing API client')
|
throw new Error('Trying to start poll without initializing API client')
|
||||||
@_pollTargetState()
|
@_pollTargetState()
|
||||||
@config.on 'change', (changedConfig) =>
|
return null
|
||||||
if changedConfig.appUpdatePollInterval?
|
|
||||||
@_pollTargetState()
|
|
||||||
|
|
||||||
_getStateDiff: =>
|
_getStateDiff: =>
|
||||||
diff = {
|
diff = {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user