Merge pull request #23515 from acierto/scaffolder-checkpoint-fix

Scaffolder checkpoint fix
This commit is contained in:
Ben Lambert
2024-03-19 10:50:35 +01:00
committed by GitHub
6 changed files with 61 additions and 1 deletions
+6
View File
@@ -0,0 +1,6 @@
---
'@backstage/plugin-scaffolder-backend': patch
'@backstage/plugin-scaffolder-node': patch
---
Fixing the lost of the initial state after a task recovery.
@@ -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: state.state });
});
it('should shutdown the running task', async () => {
const { store } = await createStore();
const { taskId } = await store.createTask({
@@ -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).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}`);
@@ -268,6 +270,16 @@ export class DatabaseTaskStore implements TaskStore {
return undefined;
}
const getState = () => {
try {
return task.state ? JSON.parse(task.state).state : undefined;
} catch (error) {
throw new Error(
`Failed to parse state of the task '${task.id}', ${error}`,
);
}
};
const secrets = this.parseTaskSecrets(task);
return {
id: task.id,
@@ -277,6 +289,7 @@ export class DatabaseTaskStore implements TaskStore {
createdAt: task.created_at,
createdBy: task.created_by ?? undefined,
secrets,
state: getState(),
};
});
}
@@ -532,7 +545,7 @@ export class DatabaseTaskStore implements TaskStore {
for (const { id, spec } of result) {
const taskSpec = JSON.parse(spec as string) as TaskSpec;
await this.db<RawDbTaskEventRow>('task_events').insert({
await tx<RawDbTaskEventRow>('task_events').insert({
task_id: id,
event_type: 'recovered',
body: JSON.stringify({
@@ -314,6 +314,7 @@ export class StorageTaskBroker implements TaskBroker {
spec: pendingTask.spec,
secrets: pendingTask.secrets,
createdBy: pendingTask.createdBy,
state: pendingTask.state,
},
this.storage,
abortController.signal,
+1
View File
@@ -286,6 +286,7 @@ export type SerializedTask = {
lastHeartbeatAt?: string;
createdBy?: string;
secrets?: TaskSecrets;
state?: JsonObject;
};
// @public
@@ -59,6 +59,7 @@ export type SerializedTask = {
lastHeartbeatAt?: string;
createdBy?: string;
secrets?: TaskSecrets;
state?: JsonObject;
};
/**