From c64574aa715990ac206a62b35b3984b96d97304f Mon Sep 17 00:00:00 2001 From: Louis Date: Mon, 5 Aug 2024 19:34:44 +0700 Subject: [PATCH] chore: return error on pulling an existing model (#975) --- .../controllers/models.controller.ts | 19 ++++-- .../download-manager.service.ts | 4 +- .../src/usecases/cortex/cortex.usecases.ts | 2 +- .../src/usecases/models/models.usecases.ts | 5 +- cortex-js/src/utils/log.ts | 65 +++++++++---------- 5 files changed, 51 insertions(+), 44 deletions(-) diff --git a/cortex-js/src/infrastructure/controllers/models.controller.ts b/cortex-js/src/infrastructure/controllers/models.controller.ts index dc0043166..c4e73e40f 100644 --- a/cortex-js/src/infrastructure/controllers/models.controller.ts +++ b/cortex-js/src/infrastructure/controllers/models.controller.ts @@ -9,7 +9,10 @@ import { UseInterceptors, BadRequestException, Patch, + Res, + HttpStatus, } from '@nestjs/common'; +import { Response } from 'express'; import { ModelsUsecases } from '@/usecases/models/models.usecases'; import { CreateModelDto } from '@/infrastructure/dtos/models/create-model.dto'; import { UpdateModelDto } from '@/infrastructure/dtos/models/update-model.dto'; @@ -137,6 +140,7 @@ export class ModelsController { }) @Post(':modelId(*)/pull') pullModel( + @Res() res: Response, @Param('modelId') modelId: string, @Body() body?: { @@ -145,7 +149,7 @@ export class ModelsController { }, ) { const { fileName, persistedModelId } = body || {}; - this.modelsUsecases + return this.modelsUsecases .pullModel( modelId, false, @@ -170,10 +174,17 @@ export class ModelsController { name: EventName.DOWNLOAD_MODEL, modelId, }), + ) + .then(() => + res.status(HttpStatus.OK).json({ + message: 'Download model started successfully.', + }), + ) + .catch((e) => + res + .status(HttpStatus.CONFLICT) + .json({ error: { message: e.message ?? e }, code: 409 }), ); - return { - message: 'Download model started successfully.', - }; } @HttpCode(200) diff --git a/cortex-js/src/infrastructure/services/download-manager/download-manager.service.ts b/cortex-js/src/infrastructure/services/download-manager/download-manager.service.ts index 78e755484..8da2810bb 100644 --- a/cortex-js/src/infrastructure/services/download-manager/download-manager.service.ts +++ b/cortex-js/src/infrastructure/services/download-manager/download-manager.service.ts @@ -117,7 +117,7 @@ export class DownloadManagerService { this.eventEmitter.emit('download.event', this.allDownloadStates); }; if (!inSequence) { - return Promise.all( + Promise.all( Object.keys(urlToDestination).map((url) => { const destination = urlToDestination[url]; return this.downloadFile(downloadId, url, destination); @@ -141,7 +141,7 @@ export class DownloadManagerService { const controller = new AbortController(); // adding to abort controllers this.abortControllers[downloadId][destination] = controller; - return new Promise(async (resolve, reject) => { + return new Promise(async (resolve) => { const response = await firstValueFrom( this.httpService.get(url, { responseType: 'stream', diff --git a/cortex-js/src/usecases/cortex/cortex.usecases.ts b/cortex-js/src/usecases/cortex/cortex.usecases.ts index 758c5892b..bc8c27cb6 100644 --- a/cortex-js/src/usecases/cortex/cortex.usecases.ts +++ b/cortex-js/src/usecases/cortex/cortex.usecases.ts @@ -129,7 +129,7 @@ export class CortexUsecases implements BeforeApplicationShutdown { * @param port * @returns */ - healthCheck(host: string, port: number): Promise { + async healthCheck(host: string, port: number): Promise { return fetch(CORTEX_CPP_HEALTH_Z_URL(host, port)) .then((res) => { if (res.ok) { diff --git a/cortex-js/src/usecases/models/models.usecases.ts b/cortex-js/src/usecases/models/models.usecases.ts index 803696f4d..3f45ec254 100644 --- a/cortex-js/src/usecases/models/models.usecases.ts +++ b/cortex-js/src/usecases/models/models.usecases.ts @@ -10,7 +10,7 @@ import { StartModelSuccessDto } from '@/infrastructure/dtos/models/start-model-s import { ExtensionRepository } from '@/domain/repositories/extension.interface'; import { EngineExtension } from '@/domain/abstracts/engine.abstract'; import { isLocalModel, normalizeModelId } from '@/utils/normalize-model-id'; -import { fileManagerService, FileManagerService } from '@/infrastructure/services/file-manager/file-manager.service'; +import { fileManagerService } from '@/infrastructure/services/file-manager/file-manager.service'; import { AxiosError } from 'axios'; import { TelemetryUsecases } from '../telemetry/telemetry.usecases'; import { TelemetrySource } from '@/domain/telemetry/telemetry.interface'; @@ -507,6 +507,7 @@ export class ModelsUsecases { engine: Engines.llamaCPP, }; if (!(await this.findOne(modelId))) await this.create(model); + else throw 'Model already exists.'; } /** @@ -531,7 +532,7 @@ export class ModelsUsecases { * Check whether the model is running in the Cortex C++ server */ async isModelRunning(modelId: string): Promise { - const model = await this.getModelOrThrow(modelId).catch((e) => undefined); + const model = await this.getModelOrThrow(modelId).catch(() => undefined); if (!model) return false; diff --git a/cortex-js/src/utils/log.ts b/cortex-js/src/utils/log.ts index 4b90f2055..4fd1579c9 100644 --- a/cortex-js/src/utils/log.ts +++ b/cortex-js/src/utils/log.ts @@ -1,7 +1,7 @@ -import { fileManagerService } from "@/infrastructure/services/file-manager/file-manager.service"; -import { existsSync, stat, unlink, writeFileSync } from "fs"; +import { fileManagerService } from '@/infrastructure/services/file-manager/file-manager.service'; +import { existsSync, stat, unlink, writeFileSync } from 'fs'; -const logCleaningInterval: number = 120000 +const logCleaningInterval: number = 120000; let timeout: NodeJS.Timeout | undefined; export async function cleanLogs( @@ -10,46 +10,41 @@ export async function cleanLogs( ): Promise { // clear existing timeout // in case we rerun it with different values - if (timeout) clearTimeout(timeout) - timeout = undefined + if (timeout) clearTimeout(timeout); + timeout = undefined; + console.log('Validating app logs. Next attempt in ', logCleaningInterval); - console.log( - 'Validating app logs. Next attempt in ', - logCleaningInterval - ) - - const size = maxFileSizeBytes ?? 1 * 1024 * 1024 // 1 MB - const days = daysToKeep ?? 7 // 7 days - const filePath = await fileManagerService.getLogPath() + const size = maxFileSizeBytes ?? 1 * 1024 * 1024; // 1 MB + const days = daysToKeep ?? 7; // 7 days + const filePath = await fileManagerService.getLogPath(); // Perform log cleaning - const currentDate = new Date() + const currentDate = new Date(); if (existsSync(filePath)) - stat(filePath, (err, stats) => { - if (err) { - console.error('Error getting file stats:', err) - return - } + stat(filePath, (err, stats) => { + if (err) { + console.error('Error getting file stats:', err); + return; + } - // Check size - if (stats.size > size) { - writeFileSync(filePath, '', 'utf8') - } else { - // Check age - const creationDate = new Date(stats.ctime) - const daysDifference = Math.floor( - (currentDate.getTime() - creationDate.getTime()) / - (1000 * 3600 * 24) - ) - if (daysDifference > days) { - writeFileSync(filePath, '', 'utf8') + // Check size + if (stats.size > size) { + writeFileSync(filePath, '', 'utf8'); + } else { + // Check age + const creationDate = new Date(stats.ctime); + const daysDifference = Math.floor( + (currentDate.getTime() - creationDate.getTime()) / (1000 * 3600 * 24), + ); + if (daysDifference > days) { + writeFileSync(filePath, '', 'utf8'); + } } - } - }) + }); // Schedule the next execution with doubled delays timeout = setTimeout( () => this.cleanLogs(maxFileSizeBytes, daysToKeep), - logCleaningInterval - ) + logCleaningInterval, + ); }