diff --git a/src/lib/server/services/tasks.ts b/src/lib/server/services/tasks.ts index 1da6c2d..9f467c3 100644 --- a/src/lib/server/services/tasks.ts +++ b/src/lib/server/services/tasks.ts @@ -1,6 +1,17 @@ import { type DB, db } from "$lib/server/db/db"; +import type { tasks, taskTypes } from "$lib/server/db/schema/tasks"; +import type { ServiceResponse } from "$lib/server/services/service.types"; +import type { InferSelectModel } from "drizzle-orm"; import logger from "../logger"; +type Task = InferSelectModel & { + type: InferSelectModel; +}; + +type TaskOrNull = InferSelectModel & { + type: InferSelectModel | null; +}; + class TasksService { private db: DB; private caller: "internal" | "api"; @@ -10,22 +21,33 @@ class TasksService { this.caller = caller; } - public async getAll() { - logger.info("Fetching all task records..."); + private async _executeQuery( + query: () => Promise, + ): Promise> { try { - const tasks = await this.db.query.tasks.findMany({ - with: { - type: true, - }, - }); - logger.debug(`Found ${tasks.length} records.`); - return { tasks, status: "ok" }; + const tasks = await query(); + + if (tasks.some(x => x.type === null)) { + const badTaskIds = tasks.filter(t => t.type === null).map(t => t.id); + logger.error(`Data integrity issue: The following tasks have invalid type IDs: ${badTaskIds.join(", ")}`); + return { + status: "failure", + error: "One or more tasks are invalid because they are not associated with a type.", + code: "DATA_INTEGRITY_VIOLATION", + }; + } + return { data: tasks as Task[], status: "ok" }; } catch (error) { logger.error({ msg: "Error querying the database.", error }); - return { status: "failed", error }; + return { status: "failure", error: "An internal server error occurred.", code: "INTERNAL_ERROR" }; } } + public async getAll() { + logger.info("Fetching all task records..."); + return this._executeQuery(() => this.db.query.tasks.findMany({ with: { type: true } })); + } + public async getByTaskId(taskIds: Array) { const mappedTasks = taskIds.map(x => { const prefix = x.slice(0, 2); @@ -41,30 +63,22 @@ class TasksService { : `${taskIds.length} records` }.`, ); - try { - const tasks = await db.query.tasks.findMany({ + return this._executeQuery(() => + this.db.query.tasks.findMany({ with: { type: true }, where: (tasks, { inArray }) => inArray(tasks.taskId, mappedTasks.map(x => x.task_id)), - }); - return { tasks, status: "ok" }; - } catch (error) { - logger.error({ msg: "Error querying the database.", error }); - return { status: "failed", error }; - } + }) + ); } public async getByDbId(ids: Array) { logger.info(`Fetching ${ids.length} records.`); - try { - const tasks = await db.query.tasks.findMany({ + return this._executeQuery(() => + this.db.query.tasks.findMany({ with: { type: true }, where: (tasks, { inArray }) => inArray(tasks.id, ids), - }); - return { tasks, status: "ok" }; - } catch (error) { - logger.error({ msg: "Error querying the database.", error }); - return { status: "failed", error }; - } + }) + ); } }