diff --git a/annotation-server/package.json b/annotation-server/package.json index 70bcecdd9..7e4fbe0b6 100644 --- a/annotation-server/package.json +++ b/annotation-server/package.json @@ -55,7 +55,6 @@ "@nestjs/cli": "^8.0.0", "@nestjs/schematics": "^8.0.0", "@nestjs/testing": "^8.0.0", - "@types/cron": "^1.7.3", "@types/express": "^4.17.13", "@types/jest": "27.4.1", "@types/jsonstream": "^0.8.30", diff --git a/annotation-server/src/app.module.ts b/annotation-server/src/app.module.ts index 3e92b8f8c..74864477c 100644 --- a/annotation-server/src/app.module.ts +++ b/annotation-server/src/app.module.ts @@ -1,6 +1,5 @@ import { Module } from '@nestjs/common'; import { ConfigModule, ConfigService } from '@nestjs/config'; -import { ScheduleModule } from '@nestjs/schedule'; import { TypeOrmModule } from '@nestjs/typeorm'; import { AppController } from './app.controller'; @@ -35,7 +34,6 @@ import { PhenotypesModule } from './phenotypes/phenotypes.module'; PhenotypesModule, GuidelinesModule, MedicationsModule, - ScheduleModule.forRoot(), ], controllers: [AppController], providers: [AppService], diff --git a/annotation-server/src/app.service.ts b/annotation-server/src/app.service.ts index cb1bad409..a0c8452e2 100644 --- a/annotation-server/src/app.service.ts +++ b/annotation-server/src/app.service.ts @@ -1,22 +1,17 @@ import { Injectable } from '@nestjs/common'; -import { Cron } from '@nestjs/schedule'; import { GuidelinesService } from './guidelines/guidelines.service'; import { MedicationsService } from './medications/medications.service'; -import { PhenotypesService } from './phenotypes/phenotypes.service'; @Injectable() export class AppService { constructor( private medicationService: MedicationsService, private guidelineService: GuidelinesService, - private phenotypesService: PhenotypesService, ) {} - @Cron('0 0 1 * *', { name: 'monthlyUpdates' }) async initializeDatabase(): Promise { await this.medicationService.fetchAllMedications(); - await this.phenotypesService.fetchPhenotypes(); await this.guidelineService.fetchGuidelines(); } } diff --git a/annotation-server/src/guidelines/guidelines.controller.ts b/annotation-server/src/guidelines/guidelines.controller.ts index a53cb9216..da137ee51 100644 --- a/annotation-server/src/guidelines/guidelines.controller.ts +++ b/annotation-server/src/guidelines/guidelines.controller.ts @@ -1,4 +1,4 @@ -import { Controller, Get, Param, Query } from '@nestjs/common'; +import { Controller, Get, Param, Post, Query } from '@nestjs/common'; import { ApiOperation, ApiParam, ApiTags } from '@nestjs/swagger'; import { @@ -18,6 +18,12 @@ import { GuidelinesService } from './guidelines.service'; export class GuidelinesController { constructor(private guidelinesService: GuidelinesService) {} + @ApiOperation({ summary: 'Clear and update all data from CPIC' }) + @Post() + initializeDatabase(): Promise { + return this.guidelinesService.fetchGuidelines(); + } + @ApiOperation({ summary: 'Fetch all guidelines' }) @ApiFindGuidelinesQueries() @Get() diff --git a/annotation-server/src/guidelines/guidelines.service.ts b/annotation-server/src/guidelines/guidelines.service.ts index 2872fc9df..4777abed7 100644 --- a/annotation-server/src/guidelines/guidelines.service.ts +++ b/annotation-server/src/guidelines/guidelines.service.ts @@ -1,6 +1,6 @@ import { sheets_v4 } from '@googleapis/sheets'; import { HttpService } from '@nestjs/axios'; -import { Injectable, Logger } from '@nestjs/common'; +import { HttpException, HttpStatus, Injectable, Logger } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { InjectRepository } from '@nestjs/typeorm'; import { lastValueFrom } from 'rxjs'; @@ -120,6 +120,16 @@ export class GuidelinesService { } async fetchGuidelines(): Promise { + if (!(await this.medicationsService.hasData())) { + throw new HttpException( + { + status: HttpStatus.BAD_REQUEST, + error: 'Medication data has to be initialized.', + }, + HttpStatus.BAD_REQUEST, + ); + } + await this.phenotypesService.fetchPhenotypes(); await this.clearAllData(); const guidelines = await this.fetchCpicGuidelines(); await this.addGuidelineURLS(guidelines); diff --git a/annotation-server/src/medications/medications.service.ts b/annotation-server/src/medications/medications.service.ts index a32eda4d7..66cdf17da 100644 --- a/annotation-server/src/medications/medications.service.ts +++ b/annotation-server/src/medications/medications.service.ts @@ -155,6 +155,10 @@ export class MedicationsService { await this.medicationRepository.delete({}); } + async hasData(): Promise { + return (await this.medicationRepository.count()) > 0; + } + getJSONfromZip(): Promise { const jsonPath = path.join(os.tmpdir(), 'drugbank-data.json'); const proc = getOsSpecificPyProcess(this.configService); diff --git a/annotation-server/test/app.e2e-spec.ts b/annotation-server/test/app.e2e-spec.ts index 238318b7f..46e7a9a77 100644 --- a/annotation-server/test/app.e2e-spec.ts +++ b/annotation-server/test/app.e2e-spec.ts @@ -26,10 +26,19 @@ describe('App (e2e)', () => { medicationService.clearAllMedicationData(); }); + describe('Pre-initialization', () => { + it('should fail to load guidelines without medications', async () => { + const createResponse = await request(app.getHttpServer()).post( + '/guidelines', + ); + expect(createResponse.status).toEqual(400); + }); + }); + describe('Initialization', () => { it('should load all data', async () => { const createResponse = await request(app.getHttpServer()).post( - '/init/', + '/init', ); expect(createResponse.status).toEqual(201); }, 30000); diff --git a/yarn.lock b/yarn.lock index bbfeb24c0..6b4a2dcd8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1146,14 +1146,6 @@ resolved "https://registry.yarnpkg.com/@types/cookiejar/-/cookiejar-2.1.2.tgz#66ad9331f63fe8a3d3d9d8c6e3906dd10f6446e8" integrity sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog== -"@types/cron@^1.7.3": - version "1.7.3" - resolved "https://registry.yarnpkg.com/@types/cron/-/cron-1.7.3.tgz#993db7d54646f61128c851607b64ba4495deae93" - integrity sha512-iPmUXyIJG1Js+ldPYhOQcYU3kCAQ2FWrSkm1FJPoii2eYSn6wEW6onPukNTT0bfiflexNSRPl6KWmAIqS+36YA== - dependencies: - "@types/node" "*" - moment ">=2.14.0" - "@types/eslint-scope@^3.7.3": version "3.7.3" resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.3.tgz#125b88504b61e3c8bc6f870882003253005c3224" @@ -5741,7 +5733,7 @@ moment-timezone@^0.5.x: dependencies: moment ">= 2.9.0" -"moment@>= 2.9.0", moment@>=2.14.0, moment@^2.29.1: +"moment@>= 2.9.0", moment@^2.29.1: version "2.29.3" resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.3.tgz#edd47411c322413999f7a5940d526de183c031f3" integrity sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw==