Browse Source

Initial commit of NestJS tfb configuration - included tests - json, p… (#4098)

* Initial commit of NestJS tfb configuration - included tests - json, plaintext, updates, multiple, single

* had array append values that are returned by pg after saving

* added TypeScript to travis.yml, removed entries from .gitignore, removed tests and references to tests in package.json, removed unnecessary condition in bench service

* removed unnecessary code - superfluous awaits

* added TS to travis.yml file

* [ci skip] changed display_name to nestjs in the benchmark config

* [ci skip] added .spec.ts files to the .gitignore
jenriquez-techempower 6 years ago
parent
commit
a8bc95124b

+ 1 - 0
.travis.yml

@@ -97,6 +97,7 @@ env:
      - 'TESTDIR="Rust/rouille Rust/thruster Rust/tokio-minihttp"'
      - "TESTLANG=Scala"
      - "TESTLANG=Swift"
+     - "TESTLANG=TypeScript"
      - "TESTLANG=Ur"
      - "TESTLANG=Vala"
      - "TESTLANG=VB"

+ 32 - 0
frameworks/TypeScript/nest/.gitignore

@@ -0,0 +1,32 @@
+
+
+### Node ###
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# Dependency directories
+node_modules/
+jspm_packages/
+
+# TypeScript v1 declaration files
+typings/
+
+# Optional npm cache directory
+.npm
+
+# Output of 'npm pack'
+*.tgz
+
+# Yarn Integrity file
+.yarn-integrity
+
+# dotenv environment variables file
+.env
+
+tslint.json
+
+*.spec.ts

+ 7 - 0
frameworks/TypeScript/nest/.prettierrc

@@ -0,0 +1,7 @@
+{
+  "singleQuote": true,
+  "trailingComma": "all",
+  "arrowParens": "avoid",
+  "useTabs": true,
+  "tabWidth": 2
+}

+ 32 - 0
frameworks/TypeScript/nest/README.md

@@ -0,0 +1,32 @@
+# NestJS Benchmarking Test
+
+This is the Nest portion of a [benchmarking test suite](../).
+
+
+## Infrastructure Software Versions
+The tests were run with:
+* [NestJS v5.1.0](https://docs.nestjs.com/)
+* [pg 7.5.0](https://node-postgres.com/)
+
+## Resources
+* http://nodejs.org/api/cluster.html
+
+## Test URLs
+### JSON Encoding Test
+
+http://localhost:8080/bench/json
+
+### Data-Store/Database Mapping Test
+
+PostgreSQL:
+http://localhost:8080/bencg/db
+
+### Variable Query Test
+
+PostgreSQL:
+http://localhost:8080/bench/queries?queries=2
+
+### Update Query Test
+
+PostgreSQL:
+http://localhost:8080/bench/updates?queries=2

+ 23 - 0
frameworks/TypeScript/nest/benchmark_config.json

@@ -0,0 +1,23 @@
+{
+  "framework": "nestjs",
+  "tests": [{
+    "default": {
+      "json_url": "/bench/json",
+      "plaintext_url": "/bench/plaintext",
+      "update_url": "/bench/updates?queries=",
+      "query_url": "/bench/queries?queries=",
+      "db_url": "/bench/db",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Micro",
+      "framework": "nestjs",
+      "language": "TypeScript",
+      "os": "Linux",
+      "orm": "Full",
+      "database": "Postgres",
+      "database_os": "Linux",
+      "display_name": "nestjs",
+      "versus": "nodejs"
+    }
+  }]
+}

+ 5 - 0
frameworks/TypeScript/nest/nest-cli.json

@@ -0,0 +1,5 @@
+{
+  "language": "ts",
+  "collection": "@nestjs/schematics",
+  "sourceRoot": "src"
+}

+ 9 - 0
frameworks/TypeScript/nest/nestjs.dockerfile

@@ -0,0 +1,9 @@
+FROM node:10.3.0
+
+COPY ./ ./
+
+RUN yarn install
+
+# ENV NODE_ENV production
+
+CMD ["yarn", "start"]

+ 6 - 0
frameworks/TypeScript/nest/nodemon-debug.json

@@ -0,0 +1,6 @@
+{
+  "watch": ["src"],
+  "ext": "ts",
+  "ignore": ["src/**/*.spec.ts"],
+  "exec": "node --inspect-brk -r ts-node/register src/main.ts"
+}

+ 6 - 0
frameworks/TypeScript/nest/nodemon.json

@@ -0,0 +1,6 @@
+{
+  "watch": ["src"],
+  "ext": "ts",
+  "ignore": ["src/**/*.spec.ts"],
+  "exec": "ts-node -r tsconfig-paths/register src/main.ts"
+}

+ 11 - 0
frameworks/TypeScript/nest/ormconfig.json

@@ -0,0 +1,11 @@
+{
+    "type": "postgres",
+    "host": "tfb-database",
+    "port": 5432,
+    "username": "benchmarkdbuser",
+    "password": "benchmarkdbpass",
+    "database": "hello_world",
+    "synchronize":false,
+    "logging": false,
+    "entities": ["./src/**/*.entity.ts", "./dist/**/*.entity.js"]
+}

+ 62 - 0
frameworks/TypeScript/nest/package.json

@@ -0,0 +1,62 @@
+{
+  "name": "nest",
+  "version": "0.0.0",
+  "description": "description",
+  "author": "",
+  "license": "MIT",
+  "scripts": {
+    "format": "prettier --write \"src/**/*.ts\"",
+    "start": "ts-node -r tsconfig-paths/register src/main.ts",
+    "start:dev": "nodemon",
+    "start:debug": "nodemon --config nodemon-debug.json",
+    "prestart:prod": "rm -rf dist && tsc",
+    "start:prod": "node dist/main.js"
+  },
+  "dependencies": {
+    "@nestjs/common": "5.1.0",
+    "@nestjs/core": "5.1.0",
+    "@nestjs/typeorm": "5.2.2",
+    "dotenv": "6.0.0",
+    "fastify": "1.12.1",
+    "fastify-formbody": "2.0.1",
+    "pg": "7.5.0",
+    "reflect-metadata": "0.1.12",
+    "rxjs": "6.2.2",
+    "typeorm": "0.2.7",
+    "typescript": "3.0.1"
+  },
+  "devDependencies": {
+    "@nestjs/testing": "5.1.0",
+    "@types/express": "4.16.0",
+    "@types/jest": "23.3.1",
+    "@types/node": "10.7.1",
+    "@types/supertest": "2.0.5",
+    "jest": "23.5.0",
+    "nodemon": "1.18.3",
+    "prettier": "1.14.2",
+    "rimraf": "2.6.2",
+    "supertest": "3.1.0",
+    "ts-jest": "23.1.3",
+    "ts-loader": "4.4.2",
+    "ts-node": "7.0.1",
+    "tsconfig-paths": "3.5.0",
+    "tslint": "5.11.0",
+    "webpack": "4.16.5",
+    "webpack-cli": "3.1.0",
+    "webpack-node-externals": "1.7.2"
+  },
+  "jest": {
+    "moduleFileExtensions": [
+      "js",
+      "json",
+      "ts"
+    ],
+    "rootDir": "src",
+    "testRegex": ".spec.ts$",
+    "transform": {
+      "^.+\\.(t|j)s$": "ts-jest"
+    },
+    "coverageDirectory": "../coverage",
+    "testEnvironment": "node"
+  }
+}

+ 22 - 0
frameworks/TypeScript/nest/src/app.controller.spec.ts

@@ -0,0 +1,22 @@
+import { Test, TestingModule } from '@nestjs/testing';
+import { INestApplication } from '@nestjs/common';
+import { AppController } from './app.controller';
+import { AppService } from './app.service';
+
+describe('AppController', () => {
+  let app: TestingModule;
+
+  beforeAll(async () => {
+    app = await Test.createTestingModule({
+      controllers: [AppController],
+      providers: [AppService],
+    }).compile();
+  });
+
+  describe('root', () => {
+    it('should return "Hello World!"', () => {
+      const appController = app.get<AppController>(AppController);
+      expect(appController.root()).toBe('Hello World!');
+    });
+  });
+});

+ 13 - 0
frameworks/TypeScript/nest/src/app.controller.ts

@@ -0,0 +1,13 @@
+import { Get, Controller } from '@nestjs/common';
+
+import { AppService } from './app.service';
+
+@Controller()
+export class AppController {
+  constructor(private readonly appService: AppService) {}
+
+  @Get()
+  root(): string {
+    return this.appService.root();
+  }
+}

+ 14 - 0
frameworks/TypeScript/nest/src/app.module.ts

@@ -0,0 +1,14 @@
+import { Module } from '@nestjs/common';
+import { TypeOrmModule } from '@nestjs/typeorm';
+
+import { AppController } from './app.controller';
+import { AppService } from './app.service';
+import { BenchModule } from './bench/bench.module';
+
+
+@Module({
+  imports: [TypeOrmModule.forRoot(), BenchModule],
+  controllers: [AppController],
+  providers: [AppService],
+})
+export class AppModule {}

+ 8 - 0
frameworks/TypeScript/nest/src/app.service.ts

@@ -0,0 +1,8 @@
+import { Injectable } from '@nestjs/common';
+
+@Injectable()
+export class AppService {
+  root(): string {
+    return 'Hello World!';
+  }
+}

+ 15 - 0
frameworks/TypeScript/nest/src/bench/bench.controller.spec.ts

@@ -0,0 +1,15 @@
+import { Test, TestingModule } from '@nestjs/testing';
+import { BenchController } from './bench.controller';
+
+describe('Bench Controller', () => {
+  let module: TestingModule;
+  beforeAll(async () => {
+    module = await Test.createTestingModule({
+      controllers: [BenchController],
+    }).compile();
+  });
+  it('should be defined', () => {
+    const controller: BenchController = module.get<BenchController>(BenchController);
+    expect(controller).toBeDefined();
+  });
+});

+ 45 - 0
frameworks/TypeScript/nest/src/bench/bench.controller.ts

@@ -0,0 +1,45 @@
+import { Controller, Get, Header, Query } from '@nestjs/common';
+
+import { BenchService } from './bench.service';
+
+@Controller('bench')
+export class BenchController {
+    constructor(private benchService: BenchService){}
+
+    @Get('/db')
+    @Header('Server', 'NestJS')
+    getRandomWorld(){
+
+        return this.benchService.getOne();
+    }
+
+    @Get('/queries')
+    @Header('Server', 'NestJS')
+    getMultipleRandomWorlds(@Query('queries') query){
+
+        return this.benchService.getMultiple(query);
+    }
+
+    @Get('/updates')
+    @Header('Server', 'NestJS')
+    updateRandomWorlds(@Query('queries') query){
+
+        return this.benchService.updateMultiple(query);
+    }
+
+    @Get('/json')
+    @Header('Server', 'NestJS')
+    @Header('Content-Type', 'application/json')
+    sayHello() {
+
+        return JSON.stringify({message: 'Hello, World!'});
+    }
+
+    @Get('/plaintext')
+    @Header('Server', 'NestJS')
+    @Header('Content-Type', 'text/plain')
+    plaintext() {
+
+        return 'Hello, World!';
+    }
+}

+ 16 - 0
frameworks/TypeScript/nest/src/bench/bench.module.ts

@@ -0,0 +1,16 @@
+import { Module } from '@nestjs/common';
+import { TypeOrmModule } from '@nestjs/typeorm';
+
+import { BenchController } from './bench.controller';
+import { BenchService } from './bench.service';
+import { WorldEntity } from './../models/world.entity';
+// import { FortuneEntity } from './../models/fortune.entity';
+
+@Module({
+  imports: [TypeOrmModule.forFeature([WorldEntity])],
+  controllers: [BenchController],
+  providers: [BenchService],
+  components: [BenchService],
+  exports: [BenchService],
+})
+export class BenchModule {}

+ 15 - 0
frameworks/TypeScript/nest/src/bench/bench.service.spec.ts

@@ -0,0 +1,15 @@
+import { Test, TestingModule } from '@nestjs/testing';
+import { BenchService } from './bench.service';
+
+describe('BenchService', () => {
+  let service: BenchService;
+  beforeAll(async () => {
+    const module: TestingModule = await Test.createTestingModule({
+      providers: [BenchService],
+    }).compile();
+    service = module.get<BenchService>(BenchService);
+  });
+  it('should be defined', () => {
+    expect(service).toBeDefined();
+  });
+});

+ 57 - 0
frameworks/TypeScript/nest/src/bench/bench.service.ts

@@ -0,0 +1,57 @@
+import { Injectable } from '@nestjs/common';
+import { Repository } from 'typeorm';
+import { WorldEntity } from 'models/world.entity';
+import { InjectRepository } from '@nestjs/typeorm';
+
+@Injectable()
+export class BenchService {
+    constructor(
+        @InjectRepository(WorldEntity)
+        private worldRepository: Repository<WorldEntity>){}
+
+    getOne(){
+
+        return this.worldRepository.findOne({ where: {id: Math.floor(Math.random() * 10000) + 1}});
+    }
+
+    async getMultiple(totalQueries: string) {
+
+        return new Promise(async (resolve, reject) => {
+            const worldArr = [];
+            const total = this.sanitizeQueries(totalQueries);
+            for (let i = 0; i < total; i++) {
+                worldArr.push(await this.getOne());
+            }
+            resolve(worldArr);
+        });
+    }
+
+    async updateMultiple(totalQueries: string) {
+
+        return new Promise(async (resolve, reject) => {
+            const worldArr = [];
+            const total = this.sanitizeQueries(totalQueries);
+            for (let i = 0; i < total; i++) {
+                let worldToUpdate = await this.getOne();
+                worldToUpdate.randomnumber = Math.floor(Math.random() * 10000) + 1;
+                worldToUpdate = await this.worldRepository.save(worldToUpdate);
+                worldArr.push(worldToUpdate);
+            }
+            resolve(worldArr);
+        });
+    }
+
+    sanitizeQueries(queries: string) {
+        const isNum = parseInt(queries, null);
+        if (isNum) {
+            if (isNum > 500) {
+                return 500;
+            } else if (isNum < 1) {
+                return 1;
+            }
+        } else {
+            return 1;
+        }
+        return isNum;
+    }
+}

+ 13 - 0
frameworks/TypeScript/nest/src/main.ts

@@ -0,0 +1,13 @@
+import 'dotenv/config';
+import { NestFactory, FastifyAdapter } from '@nestjs/core';
+import { AppModule } from './app.module';
+import { Logger } from '@nestjs/common';
+
+const port = process.env.PORT || 8080;
+
+async function bootstrap() {
+  const app = await NestFactory.create(AppModule);
+  await app.listen(port);
+  Logger.log(`Listening on port ${port}`, 'Nest Server');
+}
+bootstrap();

+ 10 - 0
frameworks/TypeScript/nest/src/models/fortune.entity.ts

@@ -0,0 +1,10 @@
+import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
+
+@Entity('fortune')
+export class FortuneEntity {
+    @PrimaryGeneratedColumn()
+    id: number;
+
+    @Column('text')
+    message: string;
+}

+ 10 - 0
frameworks/TypeScript/nest/src/models/world.entity.ts

@@ -0,0 +1,10 @@
+import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
+
+@Entity('world')
+export class WorldEntity {
+    @PrimaryGeneratedColumn()
+    id: number;
+
+    @Column('int')
+    randomnumber: number;
+}

+ 23 - 0
frameworks/TypeScript/nest/tsconfig.json

@@ -0,0 +1,23 @@
+{
+  "compilerOptions": {
+    "module": "commonjs",
+    "declaration": true,
+    "noImplicitAny": false,
+    "removeComments": true,
+    "noLib": false,
+    "allowSyntheticDefaultImports": true,
+    "emitDecoratorMetadata": true,
+    "experimentalDecorators": true,
+    "target": "es6",
+    "sourceMap": true,
+    "outDir": "./dist",
+    "baseUrl": "./src"
+  },
+  "include": [
+    "src/**/*"
+  ],
+  "exclude": [
+    "node_modules",
+    "**/*.spec.ts"
+  ]
+}

+ 7 - 0
frameworks/TypeScript/nest/tsconfig.spec.json

@@ -0,0 +1,7 @@
+{
+  "extends": "tsconfig.json",
+  "compilerOptions": {
+    "types": ["jest", "node"]
+  },
+  "include": ["**/*.spec.ts", "**/*.d.ts"]
+}