introduce a performance backend
This commit is contained in:
		| @@ -2,6 +2,8 @@ import { Module } from '@nestjs/common'; | ||||
| import { ConfigModule, ConfigService } from '@nestjs/config'; | ||||
| import { MongooseModule } from '@nestjs/mongoose'; | ||||
| import Configuration from './config/configuration'; | ||||
| import { VersioningModule } from './versioning/versioning.module'; | ||||
| import { PerformanceModule } from './performance/performance.module'; | ||||
|  | ||||
| @Module({ | ||||
|   imports: [ | ||||
| @@ -20,8 +22,8 @@ import Configuration from './config/configuration'; | ||||
|         )}`, | ||||
|       }), | ||||
|     }), | ||||
|     VersioningModule, | ||||
|     PerformanceModule, | ||||
|   ], | ||||
|   controllers: [], | ||||
|   providers: [], | ||||
| }) | ||||
| export class AppModule {} | ||||
|   | ||||
							
								
								
									
										25
									
								
								src/performance/models/performance.model.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/performance/models/performance.model.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; | ||||
| import { Document } from 'mongoose'; | ||||
| import { PerformanceEntry } from './performanceentry.model'; | ||||
|  | ||||
| export type PerformanceDocument = Performance & Document; | ||||
|  | ||||
| @Schema() | ||||
| export class Performance { | ||||
|   @Prop({ required: true }) | ||||
|   icaoCode: string; | ||||
|  | ||||
|   @Prop({ required: true, type: PerformanceEntry }) | ||||
|   aboveFL240: PerformanceEntry; | ||||
|  | ||||
|   @Prop({ required: true, type: PerformanceEntry }) | ||||
|   aboveFL100: PerformanceEntry; | ||||
|  | ||||
|   @Prop({ required: true, type: PerformanceEntry }) | ||||
|   belowFL100: PerformanceEntry; | ||||
|  | ||||
|   @Prop({ required: true }) | ||||
|   minimalApproachSpeed: number; | ||||
| } | ||||
|  | ||||
| export const PerformanceSchema = SchemaFactory.createForClass(Performance); | ||||
							
								
								
									
										16
									
								
								src/performance/models/performanceentry.model.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/performance/models/performanceentry.model.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; | ||||
| import { Document } from 'mongoose'; | ||||
|  | ||||
| export type PerformanceEntryDocument = PerformanceEntry & Document; | ||||
|  | ||||
| @Schema() | ||||
| export class PerformanceEntry { | ||||
|   @Prop({ required: true }) | ||||
|   speed: number; | ||||
|  | ||||
|   @Prop({ required: true }) | ||||
|   rateOfDescend: number; | ||||
| } | ||||
|  | ||||
| export const PerformanceEntrySchema = | ||||
|   SchemaFactory.createForClass(PerformanceEntry); | ||||
							
								
								
									
										17
									
								
								src/performance/performance.module.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/performance/performance.module.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| import { Module } from '@nestjs/common'; | ||||
| import { MongooseModule } from '@nestjs/mongoose'; | ||||
| import { PerformanceSchema } from './models/performance.model'; | ||||
| import { PerformanceService } from './performance.service'; | ||||
| import { VersioningModule } from '../versioning/versioning.module'; | ||||
|  | ||||
| @Module({ | ||||
|   imports: [ | ||||
|     MongooseModule.forFeature([ | ||||
|       { name: 'performance', schema: PerformanceSchema }, | ||||
|     ]), | ||||
|     VersioningModule, | ||||
|   ], | ||||
|   providers: [PerformanceService], | ||||
|   exports: [MongooseModule, PerformanceService], | ||||
| }) | ||||
| export class PerformanceModule {} | ||||
							
								
								
									
										18
									
								
								src/performance/performance.service.spec.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/performance/performance.service.spec.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| import { Test, TestingModule } from '@nestjs/testing'; | ||||
| import { PerformanceService } from './performance.service'; | ||||
|  | ||||
| describe('PerformanceService', () => { | ||||
|   let service: PerformanceService; | ||||
|  | ||||
|   beforeEach(async () => { | ||||
|     const module: TestingModule = await Test.createTestingModule({ | ||||
|       providers: [PerformanceService], | ||||
|     }).compile(); | ||||
|  | ||||
|     service = module.get<PerformanceService>(PerformanceService); | ||||
|   }); | ||||
|  | ||||
|   it('should be defined', () => { | ||||
|     expect(service).toBeDefined(); | ||||
|   }); | ||||
| }); | ||||
							
								
								
									
										99
									
								
								src/performance/performance.service.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								src/performance/performance.service.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,99 @@ | ||||
| import { Injectable } from '@nestjs/common'; | ||||
| import { InjectModel } from '@nestjs/mongoose'; | ||||
| import { readFileSync } from 'fs'; | ||||
| import * as yaml from 'js-yaml'; | ||||
| import { Model } from 'mongoose'; | ||||
| import { join } from 'path'; | ||||
| import { SemanticVersionDto } from 'src/versioning/dto/semanticversion.dto'; | ||||
| import { VersioningService } from '../versioning/versioning.service'; | ||||
| import { PerformanceDocument } from './models/performance.model'; | ||||
|  | ||||
| const COMPONENT_NAME = 'performance'; | ||||
|  | ||||
| @Injectable() | ||||
| export class PerformanceService { | ||||
|   private static readPerformanceFile(): Record<string, any> { | ||||
|     return yaml.load( | ||||
|       readFileSync(join(process.cwd(), 'config/performance.yaml'), 'utf8'), | ||||
|     ) as Record<string, any>; | ||||
|   } | ||||
|  | ||||
|   private async updatePerformanceData( | ||||
|     performanceData: Record<string, any>, | ||||
|     version: SemanticVersionDto, | ||||
|   ): Promise<boolean> { | ||||
|     return this.performanceModel.deleteMany({}).then(async () => { | ||||
|       for (const key in performanceData) { | ||||
|         if (key !== 'FILEINFO') { | ||||
|           await this.performanceModel.create({ | ||||
|             icaoCode: key, | ||||
|             aboveFL240: { | ||||
|               speed: performanceData[key]['speedabovefl240'], | ||||
|               rateOfDescend: performanceData[key]['rodabovefl240'], | ||||
|             }, | ||||
|             aboveFL100: { | ||||
|               speed: performanceData[key]['speedabovefl100'], | ||||
|               rateOfDescend: performanceData[key]['rodabovefl100'], | ||||
|             }, | ||||
|             belowFL100: { | ||||
|               speed: performanceData[key]['speedbelowfl100'], | ||||
|               rateOfDescend: performanceData[key]['rodbelowfl100'], | ||||
|             }, | ||||
|             minimalApproachSpeed: performanceData[key]['speedapproach'], | ||||
|           }); | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       await this.versioningService.updateComponent( | ||||
|         COMPONENT_NAME, | ||||
|         performanceData['FILEINFO']['createdAt'], | ||||
|         version, | ||||
|       ); | ||||
|  | ||||
|       return true; | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   private async validateAndUpdatePerformanceData(): Promise<boolean> { | ||||
|     // read the performance file and validate the version length | ||||
|     const data = PerformanceService.readPerformanceFile(); | ||||
|     const versionParts = (data['FILEINFO']['version'] as string).split('.'); | ||||
|     if (versionParts.length !== 3) return false; | ||||
|  | ||||
|     // create the fileversion | ||||
|     const fileversion: SemanticVersionDto = { | ||||
|       main: parseInt(versionParts[0]), | ||||
|       major: parseInt(versionParts[1]), | ||||
|       minor: parseInt(versionParts[2]), | ||||
|     }; | ||||
|  | ||||
|     return this.versioningService | ||||
|       .findComponent(COMPONENT_NAME) | ||||
|       .then((resp) => { | ||||
|         if ( | ||||
|           resp === null || | ||||
|           VersioningService.newerVersion( | ||||
|             { | ||||
|               main: resp.versionMain, | ||||
|               major: resp.versionMajor, | ||||
|               minor: resp.versionMinor, | ||||
|             }, | ||||
|             fileversion, | ||||
|           ) | ||||
|         ) { | ||||
|           return this.updatePerformanceData(data, fileversion); | ||||
|         } | ||||
|  | ||||
|         return false; | ||||
|       }) | ||||
|       .catch(() => this.updatePerformanceData(data, fileversion)); | ||||
|   } | ||||
|  | ||||
|   constructor( | ||||
|     @InjectModel(COMPONENT_NAME) | ||||
|     private readonly performanceModel: Model<PerformanceDocument>, | ||||
|     private readonly versioningService: VersioningService, | ||||
|   ) { | ||||
|     this.validateAndUpdatePerformanceData(); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										25
									
								
								src/versioning/dto/semanticversion.dto.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/versioning/dto/semanticversion.dto.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| import { IsNotEmpty } from 'class-validator'; | ||||
| import { ApiProperty } from '@nestjs/swagger'; | ||||
|  | ||||
| export class SemanticVersionDto { | ||||
|   @IsNotEmpty() | ||||
|   @ApiProperty({ | ||||
|     description: 'The main version to describe downwards compatibility issues', | ||||
|     example: 1, | ||||
|   }) | ||||
|   main: number; | ||||
|  | ||||
|   @IsNotEmpty() | ||||
|   @ApiProperty({ | ||||
|     description: 'The major version to describe upwards compatibility issues', | ||||
|     example: 1, | ||||
|   }) | ||||
|   major: number; | ||||
|  | ||||
|   @IsNotEmpty() | ||||
|   @ApiProperty({ | ||||
|     description: 'The minor version to describe API stable changes', | ||||
|     example: 1, | ||||
|   }) | ||||
|   minor: number; | ||||
| } | ||||
							
								
								
									
										24
									
								
								src/versioning/versioning.model.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/versioning/versioning.model.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'; | ||||
| import { Document } from 'mongoose'; | ||||
|  | ||||
| export type VersioningDocument = Versioning & Document; | ||||
|  | ||||
| @Schema() | ||||
| export class Versioning { | ||||
|   @Prop({ required: true }) | ||||
|   componentName: string; | ||||
|  | ||||
|   @Prop({ required: true }) | ||||
|   createdAt: string; | ||||
|  | ||||
|   @Prop({ required: true }) | ||||
|   versionMain: number; | ||||
|  | ||||
|   @Prop({ required: true }) | ||||
|   versionMajor: number; | ||||
|  | ||||
|   @Prop({ required: true }) | ||||
|   versionMinor: number; | ||||
| } | ||||
|  | ||||
| export const VersioningSchema = SchemaFactory.createForClass(Versioning); | ||||
							
								
								
									
										15
									
								
								src/versioning/versioning.module.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/versioning/versioning.module.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| import { Module } from '@nestjs/common'; | ||||
| import { MongooseModule } from '@nestjs/mongoose'; | ||||
| import { VersioningSchema } from './versioning.model'; | ||||
| import { VersioningService } from './versioning.service'; | ||||
|  | ||||
| @Module({ | ||||
|   imports: [ | ||||
|     MongooseModule.forFeature([ | ||||
|       { name: 'versioning', schema: VersioningSchema }, | ||||
|     ]), | ||||
|   ], | ||||
|   providers: [VersioningService], | ||||
|   exports: [MongooseModule, VersioningService], | ||||
| }) | ||||
| export class VersioningModule {} | ||||
							
								
								
									
										18
									
								
								src/versioning/versioning.service.spec.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/versioning/versioning.service.spec.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| import { Test, TestingModule } from '@nestjs/testing'; | ||||
| import { VersioningService } from './versioning.service'; | ||||
|  | ||||
| describe('VersioningService', () => { | ||||
|   let service: VersioningService; | ||||
|  | ||||
|   beforeEach(async () => { | ||||
|     const module: TestingModule = await Test.createTestingModule({ | ||||
|       providers: [VersioningService], | ||||
|     }).compile(); | ||||
|  | ||||
|     service = module.get<VersioningService>(VersioningService); | ||||
|   }); | ||||
|  | ||||
|   it('should be defined', () => { | ||||
|     expect(service).toBeDefined(); | ||||
|   }); | ||||
| }); | ||||
							
								
								
									
										51
									
								
								src/versioning/versioning.service.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/versioning/versioning.service.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | ||||
| import { Injectable } from '@nestjs/common'; | ||||
| import { InjectModel } from '@nestjs/mongoose'; | ||||
| import { Model } from 'mongoose'; | ||||
| import { SemanticVersionDto } from './dto/semanticversion.dto'; | ||||
| import { Versioning, VersioningDocument } from './versioning.model'; | ||||
|  | ||||
| @Injectable() | ||||
| export class VersioningService { | ||||
|   constructor( | ||||
|     @InjectModel('versioning') | ||||
|     private readonly versioningModel: Model<VersioningDocument>, | ||||
|   ) {} | ||||
|  | ||||
|   async findComponent(name: string): Promise<Versioning> { | ||||
|     return this.versioningModel.findOne({ componentName: name }); | ||||
|   } | ||||
|  | ||||
|   async updateComponent( | ||||
|     name: string, | ||||
|     createdAt: string, | ||||
|     version: SemanticVersionDto, | ||||
|   ): Promise<void> { | ||||
|     return this.versioningModel.deleteOne({ componentName: name }).then(() => { | ||||
|       this.versioningModel.create({ | ||||
|         componentName: name, | ||||
|         createdAt, | ||||
|         versionMain: version.main, | ||||
|         versionMajor: version.major, | ||||
|         versionMinor: version.minor, | ||||
|       }); | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   static newerVersion( | ||||
|     reference: SemanticVersionDto, | ||||
|     version: SemanticVersionDto, | ||||
|   ): boolean { | ||||
|     // check special cases for the main part | ||||
|     if (reference.main < version.main) return true; | ||||
|     if (reference.main > version.main) return false; | ||||
|  | ||||
|     // main versions are equal | ||||
|     // check the special cases for the major part | ||||
|     if (reference.major < version.major) return true; | ||||
|     if (reference.major > version.major) return false; | ||||
|  | ||||
|     // major versions are equal | ||||
|     // check if the minor versions increased | ||||
|     return reference.minor < version.minor; | ||||
|   } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user