Merge pull request #1868 from balena-os/finish-event

Ensure the `finish` event is always reported when fetching images
This commit is contained in:
bulldozer-balena[bot] 2022-02-01 21:47:22 +00:00 committed by GitHub
commit b6bc81cadf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -125,29 +125,26 @@ const runningTasks: { [imageName: string]: ImageTask } = {};
function reportEvent(event: 'start' | 'update' | 'finish', state: Image) { function reportEvent(event: 'start' | 'update' | 'finish', state: Image) {
const { name: imageName } = state; const { name: imageName } = state;
// Emit by default if a start event is reported
let emitChange = event === 'start';
// Get the current task and update it in memory // Get the current task and update it in memory
const currentTask = const currentTask = runningTasks[imageName] ?? createTask(state);
event === 'start' ? createTask(state) : runningTasks[imageName];
runningTasks[imageName] = currentTask; runningTasks[imageName] = currentTask;
// TODO: should we assert that the current task exists at this point? const stateChanged = (() => {
// On update, update the corresponding task with the new state if it exists switch (event) {
if (event === 'update' && currentTask) { case 'start':
const [updatedTask, changed] = currentTask.update(state); return true; // always report change on start
case 'update':
const [updatedTask, changedAfterUpdate] = currentTask.update(state);
runningTasks[imageName] = updatedTask; runningTasks[imageName] = updatedTask;
emitChange = changed; return changedAfterUpdate; // report change only if the task context changed
} case 'finish':
const [, changedAfterFinish] = currentTask.finish();
// On update, update the corresponding task with the new state if it exists
if (event === 'finish' && currentTask) {
[, emitChange] = currentTask.finish();
delete runningTasks[imageName]; delete runningTasks[imageName];
return changedAfterFinish; // report change depending on the state of the task
} }
})();
if (emitChange) { if (stateChanged) {
events.emit('change'); events.emit('change');
} }
} }
@ -172,7 +169,7 @@ export function imageFromService(service: ServiceInfo): Image {
export async function triggerFetch( export async function triggerFetch(
image: Image, image: Image,
opts: FetchOptions, opts: FetchOptions,
onFinish = _.noop, onFinish: (success: boolean) => void,
serviceName: string, serviceName: string,
): Promise<void> { ): Promise<void> {
const appUpdatePollInterval = await config.get('appUpdatePollInterval'); const appUpdatePollInterval = await config.get('appUpdatePollInterval');
@ -202,8 +199,7 @@ export async function triggerFetch(
let success: boolean; let success: boolean;
try { try {
const imageName = normalise(image.name); const imageName = normalise(image.name);
image = _.clone(image); image = { ...image, name: imageName };
image.name = imageName;
// Look for a matching image on the engine // Look for a matching image on the engine
const img = await inspectByName(image.name); const img = await inspectByName(image.name);
@ -214,8 +210,7 @@ export async function triggerFetch(
// Create image on the database if it already exists on the engine // Create image on the database if it already exists on the engine
await markAsSupervised({ ...image, dockerImageId: img.Id }); await markAsSupervised({ ...image, dockerImageId: img.Id });
onFinish(true); success = true;
return;
} catch (e) { } catch (e) {
if (!NotFoundError(e)) { if (!NotFoundError(e)) {
if (!(e instanceof ImageDownloadBackoffError)) { if (!(e instanceof ImageDownloadBackoffError)) {