diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.test.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.test.ts index fe9cf3c661..bd0b84227c 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.test.ts @@ -161,6 +161,44 @@ describe('DatabaseTaskStore', () => { expect(claimedTask.status).toBe('processing'); }); + it('should restore the state of the task after the task recovery', async () => { + const { store } = await createStore(); + const { taskId } = await store.createTask({ + spec: {} as TaskSpec, + createdBy: 'me', + }); + + const task = await store.getTask(taskId); + expect(task.status).toBe('open'); + await store.claimTask(); + + const state = { + state: { + checkpoints: { + 'v1.task.checkpoint.deploy.to.stg': { + status: 'success', + value: true, + }, + 'v1.task.checkpoint.deploy.to.pro': { + status: 'success', + value: true, + }, + }, + }, + }; + + await store.saveTaskState({ + taskId, + state, + }); + + await store.recoverTasks({ timeout: { milliseconds: 0 } }); + await store.claimTask(); + + const claimedTask = await store.getTask(taskId); + expect(claimedTask.state).toEqual({ state }); + }); + it('should shutdown the running task', async () => { const { store } = await createStore(); const { taskId } = await store.createTask({ diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts index 5b99b5d0bc..68f76cd3e4 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/DatabaseTaskStore.ts @@ -212,6 +212,7 @@ export class DatabaseTaskStore implements TaskStore { try { const spec = JSON.parse(result.spec); const secrets = result.secrets ? JSON.parse(result.secrets) : undefined; + const state = result.state ? JSON.parse(result.state) : undefined; return { id: result.id, spec, @@ -220,6 +221,7 @@ export class DatabaseTaskStore implements TaskStore { createdAt: parseSqlDateToIsoString(result.created_at), createdBy: result.created_by ?? undefined, secrets, + state, }; } catch (error) { throw new Error(`Failed to parse spec of task '${taskId}', ${error}`); @@ -536,14 +538,14 @@ export class DatabaseTaskStore implements TaskStore { status: 'open', last_heartbeat_at: this.db.fn.now(), }, - ['id', 'spec'], + ['id', 'spec', 'state'], ); taskIdsToRecover.push(...result.map(i => i.id)); for (const { id, spec } of result) { const taskSpec = JSON.parse(spec as string) as TaskSpec; - await this.db('task_events').insert({ + await tx('task_events').insert({ task_id: id, event_type: 'recovered', body: JSON.stringify({