add a getTasks method to get multiple tasks through 1 DB query

Signed-off-by: Kashish Mittal <kmittal@redhat.com>
This commit is contained in:
Kashish Mittal
2025-04-25 11:52:24 -04:00
parent fe85d897d5
commit 63a8d8e171
7 changed files with 55 additions and 20 deletions
+4
View File
@@ -329,6 +329,8 @@ export class DatabaseTaskStore implements TaskStore {
// (undocumented)
getTask(taskId: string): Promise<SerializedTask>;
// (undocumented)
getTasks(taskIds: string[]): Promise<SerializedTask_2[]>;
// (undocumented)
getTaskState({ taskId }: { taskId: string }): Promise<
| {
state: JsonObject;
@@ -483,6 +485,8 @@ export interface TaskStore {
// (undocumented)
getTask(taskId: string): Promise<SerializedTask>;
// (undocumented)
getTasks(taskIds: string[]): Promise<SerializedTask[]>;
// (undocumented)
getTaskState?({ taskId }: { taskId: string }): Promise<
| {
state: JsonObject;
@@ -344,24 +344,45 @@ export class DatabaseTaskStore implements TaskStore {
throw new NotFoundError(`No task with id '${taskId}' found`);
}
try {
const spec = JSON.parse(result.spec);
const secrets = result.secrets ? JSON.parse(result.secrets) : undefined;
const state = this.getState(result);
return {
id: result.id,
spec,
status: result.status,
lastHeartbeatAt: parseSqlDateToIsoString(result.last_heartbeat_at),
createdAt: parseSqlDateToIsoString(result.created_at),
createdBy: result.created_by ?? undefined,
secrets,
state,
};
return this.parseTaskRow(result);
} catch (error) {
throw new Error(`Failed to parse spec of task '${taskId}', ${error}`);
}
}
async getTasks(taskIds: string[]): Promise<SerializedTask[]> {
const results = await this.db<RawDbTaskRow>('tasks')
.whereIn('id', taskIds)
.select();
return results.map(result => {
try {
return this.parseTaskRow(result);
} catch (error) {
throw new Error(
`Failed to parse spec of task '${result.id}', ${error}`,
);
}
});
}
private parseTaskRow(result: RawDbTaskRow): SerializedTask {
const spec = JSON.parse(result.spec);
const secrets = result.secrets ? JSON.parse(result.secrets) : undefined;
const state = this.getState(result);
return {
id: result.id,
spec,
status: result.status,
lastHeartbeatAt: parseSqlDateToIsoString(result.last_heartbeat_at),
createdAt: parseSqlDateToIsoString(result.created_at),
createdBy: result.created_by ?? undefined,
secrets,
state,
};
}
async createTask(
options: TaskStoreCreateTaskOptions,
): Promise<TaskStoreCreateTaskResult> {
@@ -29,6 +29,7 @@ import {
TaskBrokerDispatchOptions,
TaskCompletionState,
TaskContext,
TaskFilters,
TaskSecrets,
TaskStatus,
} from '@backstage/plugin-scaffolder-node';
@@ -43,6 +44,7 @@ import ObservableImpl from 'zen-observable';
import { DefaultWorkspaceService, WorkspaceService } from './WorkspaceService';
import { readDuration } from './helper';
import { InternalTaskSecrets, TaskStore } from './types';
import { PermissionCriteria } from '@backstage/plugin-permission-common';
type TaskState = {
checkpoints: {
@@ -291,6 +293,7 @@ export class StorageTaskBroker implements TaskBroker {
offset?: number;
};
order?: { order: 'asc' | 'desc'; field: string }[];
permissionFilters?: PermissionCriteria<TaskFilters>;
}): Promise<{ tasks: SerializedTask[]; totalTasks?: number }> {
if (!this.storage.list) {
throw new Error(
@@ -400,6 +403,13 @@ export class StorageTaskBroker implements TaskBroker {
return this.storage.getTask(taskId);
}
/**
* {@inheritdoc TaskBroker.getTasks}
*/
getTasks(taskIds: string[]): Promise<SerializedTask[]> {
return this.storage.getTasks(taskIds);
}
/**
* {@inheritdoc TaskBroker.event$}
*/
@@ -110,6 +110,8 @@ export interface TaskStore {
getTask(taskId: string): Promise<SerializedTask>;
getTasks(taskIds: string[]): Promise<SerializedTask[]>;
claimTask(): Promise<SerializedTask | undefined>;
completeTask(options: {
@@ -366,13 +366,7 @@ export async function createRouter(
resourceType: RESOURCE_TYPE_SCAFFOLDER_TASK,
permissions: scaffolderTaskPermissions,
rules: taskRules,
getResources: async resourceRefs => {
return Promise.all(
resourceRefs.map(async taskId => {
return await taskBroker.get(taskId);
}),
);
},
getResources: resourceRefs => taskBroker.getTasks(resourceRefs),
},
],
permissions: scaffolderPermissions,
+2
View File
@@ -361,6 +361,8 @@ export interface TaskBroker {
// (undocumented)
get(taskId: string): Promise<SerializedTask>;
// (undocumented)
getTasks(taskIds: string[]): Promise<SerializedTask[]>;
// (undocumented)
list?(options?: {
filters?: {
createdBy?: string | string[];
@@ -204,6 +204,8 @@ export interface TaskBroker {
get(taskId: string): Promise<SerializedTask>;
getTasks(taskIds: string[]): Promise<SerializedTask[]>;
list?(options?: {
filters?: {
createdBy?: string | string[];