Merge pull request #1021 from mwohlert/instantly-apply-update-on-api-request

Apply targetState immediately after update request
This commit is contained in:
CameronDiver 2019-07-09 05:14:53 -07:00 committed by GitHub
commit 821b5ea071
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 34 additions and 4 deletions

View File

@ -579,7 +579,7 @@ export class APIBinder {
if (isFromApi || !_.isEqual(targetState, this.lastTarget)) {
await this.deviceState.setTarget(targetState);
this.lastTarget = _.cloneDeep(targetState);
this.deviceState.triggerApplyTarget({ force });
this.deviceState.triggerApplyTarget({ force, isFromApi });
}
})
.tapCatch(err => {

View File

@ -129,6 +129,8 @@ module.exports = class DeviceState extends EventEmitter
@lastSuccessfulUpdate = null
@failedUpdates = 0
@applyInProgress = false
@applyCancelled = false
@cancelDelay = null
@lastApplyStart = process.hrtime()
@scheduledApply = null
@shuttingDown = false
@ -676,19 +678,31 @@ module.exports = class DeviceState extends EventEmitter
@applyUnblocker?()
return
triggerApplyTarget: ({ force = false, delay = 0, initial = false } = {}) =>
triggerApplyTarget: ({ force = false, delay = 0, initial = false, isFromApi = false } = {}) =>
if @applyInProgress
if !@scheduledApply?
if !@scheduledApply? || (isFromApi && @cancelDelay)
@scheduledApply = { force, delay }
if isFromApi
# Cancel promise delay if call came from api to prevent waiting due to backoff
@cancelDelay()
else
# If a delay has been set it's because we need to hold off before applying again,
# so we need to respect the maximum delay that has been passed
@scheduledApply.delay = Math.max(delay, @scheduledApply.delay)
@scheduledApply.force or= force
return
@applyCancelled = false
@applyInProgress = true
Promise.delay(delay)
new Promise (resolve, reject) =>
setTimeout(resolve, delay)
@cancelDelay = reject
.catch =>
@applyCancelled = true
.then =>
@cancelDelay = null
if @applyCancelled
log.info('Skipping applyTarget because of a cancellation')
return
@lastApplyStart = process.hrtime()
log.info('Applying target state')
@applyTarget({ force, initial })

View File

@ -290,6 +290,22 @@ describe 'deviceState', ->
done()
, 5
it 'cancels current promise applying the target state', (done) ->
@deviceState.scheduledApply = { force: false, delay: 100 }
@deviceState.applyInProgress = true
@deviceState.applyCancelled = false
new Promise (resolve, reject) =>
setTimeout(resolve, 100000)
@deviceState.cancelDelay = reject
.catch =>
@deviceState.applyCancelled = true
.finally =>
expect(@deviceState.scheduledApply).to.deep.equal({ force: true, delay: 0 })
expect(@deviceState.applyCancelled).to.be.true
done()
@deviceState.triggerApplyTarget({ force: true, isFromApi: true })
it 'applies the target state for device config'
it 'applies the target state for applications'