mirror of
https://github.com/balena-os/balena-supervisor.git
synced 2025-02-21 18:06:47 +00:00
Use Promise Disposer for lock, + cleanup
This commit is contained in:
parent
685af77007
commit
c2496d30c2
@ -22,7 +22,7 @@ func TestPurge(t *testing.T) {
|
|||||||
|
|
||||||
if err = os.MkdirAll(dataPath, 0755); err != nil {
|
if err = os.MkdirAll(dataPath, 0755); err != nil {
|
||||||
t.Fatal("Could not create test directory for purge")
|
t.Fatal("Could not create test directory for purge")
|
||||||
} else if err = ioutil.WriteFile(dataPath+"/test", []byte("test"), 777); err != nil {
|
} else if err = ioutil.WriteFile(dataPath+"/test", []byte("test"), 0777); err != nil {
|
||||||
t.Fatal("Could not create test file for purge")
|
t.Fatal("Could not create test file for purge")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,31 +42,29 @@ func TestPurge(t *testing.T) {
|
|||||||
appId := config.ApplicationId
|
appId := config.ApplicationId
|
||||||
dataPath := "/resin-data/" + appId
|
dataPath := "/resin-data/" + appId
|
||||||
|
|
||||||
if err := ioutil.WriteFile(dataPath+"/test", []byte("test"), 777); err != nil {
|
if err := ioutil.WriteFile(dataPath+"/test", []byte("test"), 0777); err != nil {
|
||||||
t.Fatal("Could not create test file for purge")
|
t.Fatal("Could not create test file for purge")
|
||||||
} else if request, err := http.NewRequest("POST", supervisorAddress+"/v1/purge?apikey=bananas", strings.NewReader(`{"appId": "`+appId+`"}`)); err != nil {
|
} else if request, err := http.NewRequest("POST", supervisorAddress+"/v1/purge?apikey=bananas", strings.NewReader(`{"appId": "`+appId+`"}`)); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
} else {
|
} else {
|
||||||
request.Header.Set("Content-Type", "application/json")
|
request.Header.Set("Content-Type", "application/json")
|
||||||
|
response, err := http.DefaultClient.Do(request)
|
||||||
if response, err := http.DefaultClient.Do(request); err != nil {
|
defer response.Body.Close()
|
||||||
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
} else if response.StatusCode != http.StatusOK {
|
} else if response.StatusCode != http.StatusOK {
|
||||||
t.Errorf("Expected 200, got %d", response.StatusCode)
|
t.Errorf("Expected 200, got %d", response.StatusCode)
|
||||||
defer response.Body.Close()
|
|
||||||
if contents, err := ioutil.ReadAll(response.Body); err != nil {
|
if contents, err := ioutil.ReadAll(response.Body); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
} else {
|
} else {
|
||||||
t.Fatalf("Response: %s", contents)
|
t.Fatalf("Response: %s", contents)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
defer response.Body.Close()
|
|
||||||
if contents, err := ioutil.ReadAll(response.Body); err != nil {
|
if contents, err := ioutil.ReadAll(response.Body); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
} else if !strings.EqualFold(string(contents), `{"Status":"OK","Error":""}`) {
|
} else if !strings.EqualFold(string(contents), `{"Status":"OK","Error":""}`) {
|
||||||
t.Errorf("Purge response didn't match the expected JSON, got: %s", contents)
|
t.Errorf("Purge response didn't match the expected JSON, got: %s", contents)
|
||||||
}
|
}
|
||||||
|
|
||||||
if dirContents, err := ioutil.ReadDir(dataPath); err != nil {
|
if dirContents, err := ioutil.ReadDir(dataPath); err != nil {
|
||||||
t.Errorf("Could not read the data path after purge: %s", err)
|
t.Errorf("Could not read the data path after purge: %s", err)
|
||||||
} else if len(dirContents) > 0 {
|
} else if len(dirContents) > 0 {
|
||||||
|
@ -67,21 +67,20 @@ module.exports = (secret) ->
|
|||||||
utils.mixpanelTrack('Purge /data', appId)
|
utils.mixpanelTrack('Purge /data', appId)
|
||||||
if !appId?
|
if !appId?
|
||||||
return res.status(400).send('Missing app id')
|
return res.status(400).send('Missing app id')
|
||||||
app = null
|
|
||||||
knex('app').select().where({ appId })
|
knex('app').select().where({ appId })
|
||||||
.then ([ appFromDB ]) ->
|
.then ([ app ]) ->
|
||||||
if !appFromDB?
|
if !app?
|
||||||
throw new Error('App not found')
|
throw new Error('App not found')
|
||||||
app = appFromDB
|
Promise.using application.lockUpdates(), ->
|
||||||
application.lockUpdatesAsync()
|
application.kill(app)
|
||||||
.tap ->
|
|
||||||
application.kill(app)
|
|
||||||
.then (release) ->
|
|
||||||
request.post config.gosuperAddress + '/v1/purge', { json: true, body: applicationId: appId }, ->
|
|
||||||
application.start(app)
|
|
||||||
.then ->
|
.then ->
|
||||||
release()
|
new Promise (resolve, reject) ->
|
||||||
.pipe(res)
|
request.post(config.gosuperAddress + '/v1/purge', { json: true, body: applicationId: appId })
|
||||||
|
.on 'error', reject
|
||||||
|
.on 'response', -> resolve()
|
||||||
|
.pipe(res)
|
||||||
|
.finally ->
|
||||||
|
application.start(app)
|
||||||
.catch (err) ->
|
.catch (err) ->
|
||||||
res.status(503).send(err?.message or err or 'Unknown error')
|
res.status(503).send(err?.message or err or 'Unknown error')
|
||||||
|
|
||||||
|
@ -242,9 +242,10 @@ getEnvironment = do ->
|
|||||||
console.error("Failed to get environment for device #{deviceId}, app #{appId}. #{err}")
|
console.error("Failed to get environment for device #{deviceId}, app #{appId}. #{err}")
|
||||||
throw err
|
throw err
|
||||||
|
|
||||||
lock = new Lock()
|
exports.lockUpdates = lockUpdates = do ->
|
||||||
exports.lockUpdates = lockUpdates = lock.async.writeLock
|
_lock = new Lock()
|
||||||
exports.lockUpdatesAsync = lockUpdatesAsync = Promise.promisify(lockUpdates)
|
_lockUpdates = Promise.promisify(_lock.async.writeLock)
|
||||||
|
return -> _lockUpdates().disposer (release) -> release()
|
||||||
|
|
||||||
# 0 - Idle
|
# 0 - Idle
|
||||||
# 1 - Updating
|
# 1 - Updating
|
||||||
@ -325,27 +326,24 @@ exports.update = update = ->
|
|||||||
app = remoteApps[imageId]
|
app = remoteApps[imageId]
|
||||||
fetch(app)
|
fetch(app)
|
||||||
.then ->
|
.then ->
|
||||||
lockUpdatesAsync()
|
Promise.using lockUpdates(), ->
|
||||||
.tap ->
|
# Then delete all the ones to remove in one go
|
||||||
# Then delete all the ones to remove in one go
|
Promise.map toBeRemoved, (imageId) ->
|
||||||
Promise.map toBeRemoved, (imageId) ->
|
kill(apps[imageId])
|
||||||
kill(apps[imageId])
|
|
||||||
.tap ->
|
|
||||||
# Then install the apps and add each to the db as they succeed
|
|
||||||
installingPromises = toBeInstalled.map (imageId) ->
|
|
||||||
app = remoteApps[imageId]
|
|
||||||
start(app)
|
|
||||||
# And remove/recreate updated apps and update db as they succeed
|
|
||||||
updatingPromises = toBeUpdated.map (imageId) ->
|
|
||||||
localApp = apps[imageId]
|
|
||||||
app = remoteApps[imageId]
|
|
||||||
logSystemEvent(logTypes.updateApp, app)
|
|
||||||
kill(localApp)
|
|
||||||
.then ->
|
.then ->
|
||||||
start(app)
|
# Then install the apps and add each to the db as they succeed
|
||||||
Promise.all(installingPromises.concat(updatingPromises))
|
installingPromises = toBeInstalled.map (imageId) ->
|
||||||
.then (release) ->
|
app = remoteApps[imageId]
|
||||||
release()
|
start(app)
|
||||||
|
# And remove/recreate updated apps and update db as they succeed
|
||||||
|
updatingPromises = toBeUpdated.map (imageId) ->
|
||||||
|
localApp = apps[imageId]
|
||||||
|
app = remoteApps[imageId]
|
||||||
|
logSystemEvent(logTypes.updateApp, app)
|
||||||
|
kill(localApp)
|
||||||
|
.then ->
|
||||||
|
start(app)
|
||||||
|
Promise.all(installingPromises.concat(updatingPromises))
|
||||||
.then ->
|
.then ->
|
||||||
failedUpdates = 0
|
failedUpdates = 0
|
||||||
# We cleanup here as we want a point when we have a consistent apps/images state, rather than potentially at a
|
# We cleanup here as we want a point when we have a consistent apps/images state, rather than potentially at a
|
||||||
|
Loading…
x
Reference in New Issue
Block a user