From 68d358d5d6375121944cf216469d1c1dc21fd5ce Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Tue, 29 Dec 2020 14:28:33 +0800 Subject: [PATCH 01/22] chore: add grpc file --- packages/core/src/interface.ts | 2 +- .../decorator/src/microservice/producer.ts | 16 +++ packages/decorator/src/rpc/hsf.ts | 5 + packages/grpc/README.md | 12 ++ packages/grpc/jest.config.js | 8 ++ packages/grpc/package.json | 43 +++++++ packages/grpc/src/framework.ts | 107 ++++++++++++++++++ packages/grpc/src/index.ts | 0 packages/grpc/src/interface.ts | 18 +++ packages/grpc/src/logger.ts | 26 +++++ packages/grpc/tsconfig.json | 12 ++ packages/socketio/src/logger.ts | 26 +++++ 12 files changed, 274 insertions(+), 1 deletion(-) create mode 100644 packages/decorator/src/microservice/producer.ts create mode 100644 packages/grpc/README.md create mode 100644 packages/grpc/jest.config.js create mode 100644 packages/grpc/package.json create mode 100644 packages/grpc/src/framework.ts create mode 100644 packages/grpc/src/index.ts create mode 100644 packages/grpc/src/interface.ts create mode 100644 packages/grpc/src/logger.ts create mode 100644 packages/grpc/tsconfig.json create mode 100644 packages/socketio/src/logger.ts diff --git a/packages/core/src/interface.ts b/packages/core/src/interface.ts index fce3edc0259b..ac35091b7f25 100644 --- a/packages/core/src/interface.ts +++ b/packages/core/src/interface.ts @@ -359,7 +359,7 @@ export enum MidwayFrameworkType { WEB_EXPRESS = '@midwayjs/express', FAAS = '@midwayjs/faas', MS_HSF = '', - MS_GRPC = '', + MS_GRPC = '@midwayjs/grpc', MS_RABBITMQ = '@midwayjs/rabbitmq', WS_IO = '@midwayjs/socketio', WSS = '', diff --git a/packages/decorator/src/microservice/producer.ts b/packages/decorator/src/microservice/producer.ts new file mode 100644 index 000000000000..ff381cba0fa5 --- /dev/null +++ b/packages/decorator/src/microservice/producer.ts @@ -0,0 +1,16 @@ +import { ScopeEnum, saveClassMetadata, saveModule, MS_PRODUCER_KEY } from '../'; +import { Scope } from '../annotation'; + +export enum MSProducerType { + DUBBO = 'dubbo', + GRPC = 'gRPC', + HSF = 'hsf', +} + +export function Producer(type: MSProducerType): ClassDecorator { + return (target: any) => { + saveModule(MS_PRODUCER_KEY, target); + saveClassMetadata(MS_PRODUCER_KEY, type, target); + Scope(ScopeEnum.Request)(target); + }; +} diff --git a/packages/decorator/src/rpc/hsf.ts b/packages/decorator/src/rpc/hsf.ts index 2e4c157d8c50..9548c462c0be 100644 --- a/packages/decorator/src/rpc/hsf.ts +++ b/packages/decorator/src/rpc/hsf.ts @@ -8,6 +8,11 @@ export interface HSFOpts { namespace?: string; } +/** + * @deprecated + * @param hsfOption + * @constructor + */ export function HSF(hsfOption: HSFOpts = {}): ClassDecorator { return (target: any) => { saveModule(HSF_KEY, target); diff --git a/packages/grpc/README.md b/packages/grpc/README.md new file mode 100644 index 000000000000..54dc6edba4db --- /dev/null +++ b/packages/grpc/README.md @@ -0,0 +1,12 @@ +# midway-web + +[![Package Quality](http://npm.packagequality.com/shield/midway-web.svg)](http://packagequality.com/#?package=midway-web) +[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/midwayjs/midway/pulls) + +this is a sub package for midway. + +Document: [https://midwayjs.org/midway](https://midwayjs.org/midway) + +## License + +[MIT]((http://github.com/midwayjs/midway/blob/master/LICENSE)) diff --git a/packages/grpc/jest.config.js b/packages/grpc/jest.config.js new file mode 100644 index 000000000000..bb2f28760e4c --- /dev/null +++ b/packages/grpc/jest.config.js @@ -0,0 +1,8 @@ +const path = require('path'); + +module.exports = { + preset: 'ts-jest', + testEnvironment: 'node', + testPathIgnorePatterns: ['/test/fixtures'], + coveragePathIgnorePatterns: ['/test/'], +}; diff --git a/packages/grpc/package.json b/packages/grpc/package.json new file mode 100644 index 000000000000..2010d0d14170 --- /dev/null +++ b/packages/grpc/package.json @@ -0,0 +1,43 @@ +{ + "name": "@midwayjs/grpc", + "version": "2.5.5", + "description": "Midway Framework for gRPC", + "main": "dist/index", + "typings": "dist/index.d.ts", + "scripts": { + "build": "midway-bin build -c", + "test": "midway-bin test --forceExit", + "cov": "midway-bin cov --forceExit", + "ci": "npm run test" + }, + "keywords": [ + "midway", + "IoC", + "web", + "scene", + "express" + ], + "files": [ + "dist/**/*.js", + "dist/**/*.d.ts" + ], + "license": "MIT", + "devDependencies": { + "@midwayjs/cli": "^1.0.0", + "@midwayjs/mock": "^2.5.5", + "@types/google-protobuf": "^3.7.4", + "google-protobuf": "^3.14.0", + "fs-extra": "^8.0.1" + }, + "dependencies": { + "@midwayjs/core": "^2.5.5", + "@midwayjs/decorator": "^2.4.7", + "@grpc/grpc-js": "^1.2.1" + }, + "author": "Harry Chen ", + "repository": { + "type": "git", + "url": "http://github.com/midwayjs/midway.git" + }, + "gitHead": "a603d2348d6141f8f723901498f03a162a037708" +} diff --git a/packages/grpc/src/framework.ts b/packages/grpc/src/framework.ts new file mode 100644 index 000000000000..3eab7c2a6de5 --- /dev/null +++ b/packages/grpc/src/framework.ts @@ -0,0 +1,107 @@ +import { Server, ServerCredentials, loadPackageDefinition, setLogger } from '@grpc/grpc-js'; + +import { + BaseFramework, + extractExpressLikeValue, + getClassMetadata, + getPropertyDataFromClass, + getPropertyMetadata, + getProviderId, + IMidwayBootstrapOptions, + listModule, + MidwayFrameworkType, + MidwayRequestContainer, +} from '@midwayjs/core'; + +import { + CONTROLLER_KEY, + ControllerOption, + PRIORITY_KEY, + RouterOption, + RouterParamValue, + WEB_RESPONSE_CONTENT_TYPE, + WEB_RESPONSE_HEADER, + WEB_RESPONSE_HTTP_CODE, + WEB_RESPONSE_KEY, + WEB_RESPONSE_REDIRECT, + WEB_ROUTER_KEY, + WEB_ROUTER_PARAM_KEY, +} from '@midwayjs/decorator'; +import { + IMidwayGRPCApplication, IMidwayGRPConfigurationOptions, +} from './interface'; +import { MidwayGRPCContextLogger } from './logger'; + +export class MidwayGRPCFramework extends BaseFramework< + IMidwayGRPCApplication, + IMidwayGRPConfigurationOptions + > { + public app: IMidwayGRPCApplication; + private server: Server; + + public configure( + options: IMidwayGRPConfigurationOptions + ): MidwayGRPCFramework { + this.configurationOptions = options; + return this; + } + + async applicationInitialize(options: Partial) { + // set logger to grpc server + setLogger(this.logger); + const server: Server = new Server({ + 'grpc.max_receive_message_length': -1, + 'grpc.max_send_message_length': -1, + }); + + this.app = server as IMidwayGRPCApplication; + this.server = server; + this.app.use((req, res, next) => { + const ctx = { req, res } as IMidwayExpressContext; + ctx.logger = new MidwayGRPCContextLogger(ctx, this.appLogger); + ctx.startTime = Date.now(); + ctx.requestContext = new MidwayRequestContainer( + ctx, + this.getApplicationContext() + ); + (req as any).requestContext = ctx.requestContext; + ctx.requestContext.registerObject('req', req); + ctx.requestContext.registerObject('res', res); + ctx.requestContext.ready(); + next(); + }); + } + + protected async afterContainerReady( + options: Partial + ): Promise { + await this.loadService(); + } + + protected async loadService() { + this.server.addService() + } + + public async run(): Promise { + this.server.bindAsync(`0.0.0.0:${this.configurationOptions.port}`, ServerCredentials.createInsecure(), (err: Error | null, bindPort: number) => { + if (err) { + throw err; + } + + this.logger.info(`gRPC:Server:${bindPort}`, new Date().toLocaleString()); + this.server.start(); + }); + } + + public getFrameworkType(): MidwayFrameworkType { + return MidwayFrameworkType.MS_GRPC; + } + + public getApplication(): IMidwayGRPCApplication { + return this.app; + } + + public getServer() { + return this.server; + } +} diff --git a/packages/grpc/src/index.ts b/packages/grpc/src/index.ts new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/packages/grpc/src/interface.ts b/packages/grpc/src/interface.ts new file mode 100644 index 000000000000..47ae14c8b299 --- /dev/null +++ b/packages/grpc/src/interface.ts @@ -0,0 +1,18 @@ +import { IMidwayApplication, IMidwayContext } from '@midwayjs/core'; +import { Server } from '@grpc/grpc-js'; + +export type IMidwayGRPCContext = IMidwayContext & { + startTime: number; +} +export type IMidwayGRPCApplication = IMidwayApplication & Server; + +export interface IMidwayGRPConfigurationOptions { + /** + * application gRPC port + */ + port?: number; + /** + * proto path + */ + protoPath?: string; +} diff --git a/packages/grpc/src/logger.ts b/packages/grpc/src/logger.ts new file mode 100644 index 000000000000..e9e9c6504768 --- /dev/null +++ b/packages/grpc/src/logger.ts @@ -0,0 +1,26 @@ +import { MidwayContextLogger } from '@midwayjs/core'; +import { IMidwayGRPCContext } from './interface'; + +export class MidwayGRPCContextLogger extends MidwayContextLogger< + IMidwayGRPCContext + > { + formatContextLabel() { + // format: '[$userId/$ip/$traceId/$use_ms $method $url]' + // const userId = req?.['session']?.['userId'] || '-'; + // const traceId = '-'; + // const use = Date.now() - this.ctx.startTime; + // return ( + // userId + + // '/' + + // req.ip + + // '/' + + // traceId + + // '/' + + // use + + // 'ms ' + + // req.method + + // ' ' + + // req.url + return ''; + } +} diff --git a/packages/grpc/tsconfig.json b/packages/grpc/tsconfig.json new file mode 100644 index 000000000000..b1a4a0c8633f --- /dev/null +++ b/packages/grpc/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.json", + "compileOnSave": true, + "compilerOptions": { + "rootDir": "src", + "outDir": "dist", + "jsx": "react" + }, + "include": [ + "./src/**/*.ts" + ] +} diff --git a/packages/socketio/src/logger.ts b/packages/socketio/src/logger.ts new file mode 100644 index 000000000000..2ad654051cf1 --- /dev/null +++ b/packages/socketio/src/logger.ts @@ -0,0 +1,26 @@ +import { MidwayContextLogger } from '@midwayjs/core'; +import { IMidwaySocketIOContext } from './interface'; + +export class MidwaySocketIOContextLogger extends MidwayContextLogger< + IMidwaySocketIOContext + > { + formatContextLabel() { + // format: '[$userId/$ip/$traceId/$use_ms $method $url]' + // const userId = req?.['session']?.['userId'] || '-'; + // const traceId = '-'; + // const use = Date.now() - this.ctx.startTime; + // return ( + // userId + + // '/' + + // req.ip + + // '/' + + // traceId + + // '/' + + // use + + // 'ms ' + + // req.method + + // ' ' + + // req.url + return ''; + } +} From 7cc643b887c0483b60a12b86731995ddd2b2ce7e Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Sat, 2 Jan 2021 22:56:47 +0800 Subject: [PATCH 02/22] feat: implement grpc --- packages/decorator/src/common/constant.ts | 5 + .../decorator/src/common/decoratorManager.ts | 9 +- packages/decorator/src/index.ts | 1 + .../decorator/src/microservice/producer.ts | 53 ++++++++- packages/grpc/package.json | 3 +- packages/grpc/src/framework.ts | 67 ++++++----- packages/grpc/src/index.ts | 2 + packages/grpc/src/interface.ts | 7 ++ .../grpc/test/fixtures/base-app/package.json | 3 + .../fixtures/base-app/src/producer/greeter.ts | 111 ++++++++++++++++++ .../base-app/src/protos/helloworld.proto | 38 ++++++ packages/grpc/test/index.test.ts | 1 + packages/grpc/test/utils.ts | 25 ++++ 13 files changed, 291 insertions(+), 34 deletions(-) create mode 100644 packages/grpc/test/fixtures/base-app/package.json create mode 100644 packages/grpc/test/fixtures/base-app/src/producer/greeter.ts create mode 100644 packages/grpc/test/fixtures/base-app/src/protos/helloworld.proto create mode 100644 packages/grpc/test/index.test.ts create mode 100644 packages/grpc/test/utils.ts diff --git a/packages/decorator/src/common/constant.ts b/packages/decorator/src/common/constant.ts index 5d1b4addf164..05a9e64c7ea4 100644 --- a/packages/decorator/src/common/constant.ts +++ b/packages/decorator/src/common/constant.ts @@ -36,6 +36,11 @@ export const RPC_DUBBO_KEY = 'rpc:dubbo'; export const MS_CONSUMER_KEY = 'ms:consumer'; export const MS_PRODUCER_KEY = 'ms:producer'; +// rpc method +export const MS_GRPC_METHOD_KEY = 'ms:grpc:method'; +export const MS_DUBBO_METHOD_KEY = 'ms:dubbo:method'; +export const MS_HSF_METHOD_KEY = 'ms:hsf:method'; + // framework export const CONFIG_KEY = 'config'; export const PLUGIN_KEY = 'plugin'; diff --git a/packages/decorator/src/common/decoratorManager.ts b/packages/decorator/src/common/decoratorManager.ts index 8e69ded3afe4..2afab6c413dd 100644 --- a/packages/decorator/src/common/decoratorManager.ts +++ b/packages/decorator/src/common/decoratorManager.ts @@ -715,8 +715,13 @@ export function saveModule(decoratorNameKey: decoratorKey, target) { * list module from decorator key * @param decoratorNameKey */ -export function listModule(decoratorNameKey: decoratorKey): any[] { - return manager.listModule(decoratorNameKey); +export function listModule(decoratorNameKey: decoratorKey, filter?:(module) => boolean): any[] { + const modules = manager.listModule(decoratorNameKey); + if (filter) { + return modules.filter(filter); + } else { + return modules; + } } /** diff --git a/packages/decorator/src/index.ts b/packages/decorator/src/index.ts index ae16172a1b72..b6ec3b9bfa45 100644 --- a/packages/decorator/src/index.ts +++ b/packages/decorator/src/index.ts @@ -18,6 +18,7 @@ export * from './framework/plugin'; export * from './framework/app'; export * from './ws/webSocketController'; export * from './ws/webSocketEvent'; +export * from './microservice/producer'; export * from './microservice/consumer'; export * from './microservice/rabbitmqListener'; export * from './util/index'; diff --git a/packages/decorator/src/microservice/producer.ts b/packages/decorator/src/microservice/producer.ts index ff381cba0fa5..fd594caeff40 100644 --- a/packages/decorator/src/microservice/producer.ts +++ b/packages/decorator/src/microservice/producer.ts @@ -1,4 +1,13 @@ -import { ScopeEnum, saveClassMetadata, saveModule, MS_PRODUCER_KEY } from '../'; +import { + ScopeEnum, + saveClassMetadata, + saveModule, + MS_PRODUCER_KEY, + attachClassMetadata, + MS_GRPC_METHOD_KEY, + MS_DUBBO_METHOD_KEY, + MS_HSF_METHOD_KEY, +} from '../'; import { Scope } from '../annotation'; export enum MSProducerType { @@ -14,3 +23,45 @@ export function Producer(type: MSProducerType): ClassDecorator { Scope(ScopeEnum.Request)(target); }; } + +export function GrpcMethod(methodName?: string): MethodDecorator { + return (target, propertyName, descriptor: PropertyDescriptor) => { + attachClassMetadata( + MS_GRPC_METHOD_KEY, + { + methodName: methodName || propertyName + }, + target + ); + + return descriptor; + }; +} + +export function DubboMethod(methodName?: string): MethodDecorator { + return (target, propertyName, descriptor: PropertyDescriptor) => { + attachClassMetadata( + MS_DUBBO_METHOD_KEY, + { + methodName: methodName || propertyName + }, + target + ); + + return descriptor; + }; +} + +export function HSFMethod(methodName?: string): MethodDecorator { + return (target, propertyName, descriptor: PropertyDescriptor) => { + attachClassMetadata( + MS_HSF_METHOD_KEY, + { + methodName: methodName || propertyName + }, + target + ); + + return descriptor; + }; +} diff --git a/packages/grpc/package.json b/packages/grpc/package.json index 2010d0d14170..625f921608d4 100644 --- a/packages/grpc/package.json +++ b/packages/grpc/package.json @@ -25,8 +25,7 @@ "devDependencies": { "@midwayjs/cli": "^1.0.0", "@midwayjs/mock": "^2.5.5", - "@types/google-protobuf": "^3.7.4", - "google-protobuf": "^3.14.0", + "@grpc/proto-loader": "^0.5.5", "fs-extra": "^8.0.1" }, "dependencies": { diff --git a/packages/grpc/src/framework.ts b/packages/grpc/src/framework.ts index 3eab7c2a6de5..ce9f19464d77 100644 --- a/packages/grpc/src/framework.ts +++ b/packages/grpc/src/framework.ts @@ -1,8 +1,7 @@ import { Server, ServerCredentials, loadPackageDefinition, setLogger } from '@grpc/grpc-js'; - +import * as grpc from '@grpc/grpc-js'; import { BaseFramework, - extractExpressLikeValue, getClassMetadata, getPropertyDataFromClass, getPropertyMetadata, @@ -14,18 +13,7 @@ import { } from '@midwayjs/core'; import { - CONTROLLER_KEY, - ControllerOption, - PRIORITY_KEY, - RouterOption, - RouterParamValue, - WEB_RESPONSE_CONTENT_TYPE, - WEB_RESPONSE_HEADER, - WEB_RESPONSE_HTTP_CODE, - WEB_RESPONSE_KEY, - WEB_RESPONSE_REDIRECT, - WEB_ROUTER_KEY, - WEB_ROUTER_PARAM_KEY, + MS_PRODUCER_KEY, MSProducerType } from '@midwayjs/decorator'; import { IMidwayGRPCApplication, IMidwayGRPConfigurationOptions, @@ -56,20 +44,22 @@ export class MidwayGRPCFramework extends BaseFramework< this.app = server as IMidwayGRPCApplication; this.server = server; - this.app.use((req, res, next) => { - const ctx = { req, res } as IMidwayExpressContext; - ctx.logger = new MidwayGRPCContextLogger(ctx, this.appLogger); - ctx.startTime = Date.now(); - ctx.requestContext = new MidwayRequestContainer( - ctx, - this.getApplicationContext() - ); - (req as any).requestContext = ctx.requestContext; - ctx.requestContext.registerObject('req', req); - ctx.requestContext.registerObject('res', res); - ctx.requestContext.ready(); - next(); - }); + // this.app.use((req, res, next) => { + // const ctx = { req, res } as IMidwayExpressContext; + // ctx.logger = new MidwayGRPCContextLogger(ctx, this.appLogger); + // ctx.startTime = Date.now(); + // ctx.requestContext = new MidwayRequestContainer( + // ctx, + // this.getApplicationContext() + // ); + // (req as any).requestContext = ctx.requestContext; + // ctx.requestContext.registerObject('req', req); + // ctx.requestContext.registerObject('res', res); + // ctx.requestContext.ready(); + // next(); + // }); + + await this.loadService(); } protected async afterContainerReady( @@ -79,7 +69,26 @@ export class MidwayGRPCFramework extends BaseFramework< } protected async loadService() { - this.server.addService() + const gRPCModules = listModule(MS_PRODUCER_KEY, (module) => { + const type = getClassMetadata(MS_PRODUCER_KEY, module); + return type === MSProducerType.GRPC; + }); + + console.log(gRPCModules); + + if (this.configurationOptions.packageDefinition) { + const definitions = grpc.loadPackageDefinition(this.configurationOptions.packageDefinition); + const protoModule = definitions[this.configurationOptions.package]; + + for (const protoService in protoModule) { + // TODO get service from container + // TODO find method + // binding service to server + this.server.addService(protoService['service'], {sayHello: sayHello}); + } + } + + } public async run(): Promise { diff --git a/packages/grpc/src/index.ts b/packages/grpc/src/index.ts index e69de29bb2d1..7382fadf3777 100644 --- a/packages/grpc/src/index.ts +++ b/packages/grpc/src/index.ts @@ -0,0 +1,2 @@ +export * from './interface'; +export { MidwayGRPCFramework as Framework } from './framework'; diff --git a/packages/grpc/src/interface.ts b/packages/grpc/src/interface.ts index 47ae14c8b299..13e2ead4622f 100644 --- a/packages/grpc/src/interface.ts +++ b/packages/grpc/src/interface.ts @@ -15,4 +15,11 @@ export interface IMidwayGRPConfigurationOptions { * proto path */ protoPath?: string; + + /** + * protobuf package name + */ + package: string; + + packageDefinition?: any; } diff --git a/packages/grpc/test/fixtures/base-app/package.json b/packages/grpc/test/fixtures/base-app/package.json new file mode 100644 index 000000000000..621cdc6a4174 --- /dev/null +++ b/packages/grpc/test/fixtures/base-app/package.json @@ -0,0 +1,3 @@ +{ + "name": "ali-demo" +} diff --git a/packages/grpc/test/fixtures/base-app/src/producer/greeter.ts b/packages/grpc/test/fixtures/base-app/src/producer/greeter.ts new file mode 100644 index 000000000000..7705879d422c --- /dev/null +++ b/packages/grpc/test/fixtures/base-app/src/producer/greeter.ts @@ -0,0 +1,111 @@ +import { + MetadataValue, + sendUnaryData, + ServerDuplexStream, + ServerReadableStream, + ServerUnaryCall, + ServerWritableStream, + status, + UntypedHandleCall +} from '@grpc/grpc-js'; +import { randomBytes } from 'crypto'; +import { ListValue, Struct, Value } from 'google-protobuf/google/protobuf/struct_pb'; + +import { IGreeterServer } from '../../models/helloworld_grpc_pb'; +import { HelloRequest, HelloResponse } from '../../models/helloworld_pb'; +import { logger, ServiceError } from '../utils'; + +import { MSProducerType, Producer, Provide, GrpcMethod } from '@midwayjs/decorator'; + +/** + * package helloworld + * service Greeter + */ +@Provide() +@Producer(MSProducerType.GRPC) +export class Greeter implements IGreeterServer { + // Argument of type 'Greeter' is not assignable to parameter of type 'UntypedServiceImplementation'. + // Index signature is missing in type 'Greeter'.ts(2345) + [method: string]: UntypedHandleCall; + + @GrpcMethod() + /** + * Implements the SayHello RPC method. + */ + public sayHello(call: ServerUnaryCall, callback: sendUnaryData): void { + logger.info('sayHello', Date.now()); + + const res: HelloResponse = new HelloResponse(); + const name: string = call.request.getName(); + logger.info('sayHelloName:', name); + + if (name === 'error') { + // https://grpc.io/grpc/node/grpc.html#.status__anchor + return callback(new ServiceError(status.INVALID_ARGUMENT, 'InvalidValue'), null); + } + + const metadataValue: MetadataValue[] = call.metadata.get('foo'); + logger.info('sayHelloMetadata:', metadataValue); + + res.setMessage(`Hello ${metadataValue.length > 0 ? metadataValue : name}`); + + const paramStruct: Struct | undefined = call.request.getParamStruct(); + const paramListValue: ListValue | undefined = call.request.getParamListValue(); + const paramValue: Value | undefined = call.request.getParamValue(); + logger.info('sayHelloStruct:', paramStruct?.toJavaScript()); + logger.info('sayHelloListValue:', paramListValue?.toJavaScript()); + logger.info('sayHelloValue:', paramValue?.toJavaScript()); + + if (paramStruct) { + // = res.setParamStruct(paramStruct); + res.setParamStruct(Struct.fromJavaScript(paramStruct.toJavaScript())); + } + res.setParamListValue(paramListValue); + res.setParamValue(paramValue); + + callback(null, res); + } + + public sayHelloStreamRequest(call: ServerReadableStream, callback: sendUnaryData): void { + logger.info('sayHelloStreamRequest:', call.getPeer()); + + const data: string[] = []; + call.on('data', (req: HelloRequest) => { + data.push(`${req.getName()} - ${randomBytes(5).toString('hex')}`); + }).on('end', () => { + const res: HelloResponse = new HelloResponse(); + res.setMessage(data.join('\n')); + + callback(null, res); + }).on('error', (err: Error) => { + callback(new ServiceError(status.INTERNAL, err.message), null); + }); + } + + public sayHelloStreamResponse(call: ServerWritableStream): void { + logger.info('sayHelloStreamResponse:', call.request.toObject()); + + const name: string = call.request.getName(); + + for (const text of Array(10).fill('').map(() => randomBytes(5).toString('hex'))) { + const res: HelloResponse = new HelloResponse(); + res.setMessage(`${name} - ${text}`); + call.write(res); + } + call.end(); + } + + public sayHelloStream(call: ServerDuplexStream): void { + logger.info('sayHelloStream:', call.getPeer()); + + call.on('data', (req: HelloRequest) => { + const res: HelloResponse = new HelloResponse(); + res.setMessage(`${req.getName()} - ${randomBytes(5).toString('hex')}`); + call.write(res); + }).on('end', () => { + call.end(); + }).on('error', (err: Error) => { + logger.error('sayHelloStream:', err); + }); + } +} diff --git a/packages/grpc/test/fixtures/base-app/src/protos/helloworld.proto b/packages/grpc/test/fixtures/base-app/src/protos/helloworld.proto new file mode 100644 index 000000000000..be878ce25fff --- /dev/null +++ b/packages/grpc/test/fixtures/base-app/src/protos/helloworld.proto @@ -0,0 +1,38 @@ +// Copyright 2015 gRPC authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +syntax = "proto3"; + +option java_multiple_files = true; +option java_package = "io.grpc.examples.helloworld"; +option java_outer_classname = "HelloWorldProto"; +option objc_class_prefix = "HLW"; + +package helloworld; + +// The greeting service definition. +service Greeter { + // Sends a greeting + rpc SayHello (HelloRequest) returns (HelloReply) {} +} + +// The request message containing the user's name. +message HelloRequest { + string name = 1; +} + +// The response message containing the greetings +message HelloReply { + string message = 1; +} diff --git a/packages/grpc/test/index.test.ts b/packages/grpc/test/index.test.ts new file mode 100644 index 000000000000..8b137891791f --- /dev/null +++ b/packages/grpc/test/index.test.ts @@ -0,0 +1 @@ + diff --git a/packages/grpc/test/utils.ts b/packages/grpc/test/utils.ts new file mode 100644 index 000000000000..ada6d2a3ca53 --- /dev/null +++ b/packages/grpc/test/utils.ts @@ -0,0 +1,25 @@ +import { Framework, IMidwayGRPCApplication, IMidwayGRPConfigurationOptions } from '../src'; +import { join } from 'path'; +import { close, createApp } from '@midwayjs/mock'; + +import * as protoLoader from '@grpc/proto-loader'; + +/** + * create a gRPC server + * @param name + * @param options + */ +export async function creatApp(name: string, options: IMidwayGRPConfigurationOptions = {}): Promise { + options.packageDefinition = protoLoader.loadSync(options.protoPath, { + keepCase: true, + longs: String, + enums: String, + defaults: true, + oneofs: true + }); + return createApp(join(__dirname, 'fixtures', name), options, Framework); +} + +export async function closeApp(app) { + return close(app); +} From 7bbcce7136378e0f43d8e242ea4f26cd8bd3bb18 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Sun, 3 Jan 2021 23:33:52 +0800 Subject: [PATCH 03/22] feat: add grpc server --- packages/grpc/package.json | 4 +- packages/grpc/src/framework.ts | 81 +++++++------- packages/grpc/src/interface.ts | 2 +- .../test/fixtures/base-app/src/interface.ts | 14 +++ .../fixtures/base-app/src/producer/greeter.ts | 102 ++---------------- .../fixtures/base-app/src/producer/hero.ts | 15 +++ .../src/protos => proto}/helloworld.proto | 0 packages/grpc/test/fixtures/proto/hero.proto | 16 +++ packages/grpc/test/index.test.ts | 14 +++ packages/grpc/test/utils.ts | 2 +- 10 files changed, 114 insertions(+), 136 deletions(-) create mode 100644 packages/grpc/test/fixtures/base-app/src/interface.ts create mode 100644 packages/grpc/test/fixtures/base-app/src/producer/hero.ts rename packages/grpc/test/fixtures/{base-app/src/protos => proto}/helloworld.proto (100%) create mode 100644 packages/grpc/test/fixtures/proto/hero.proto diff --git a/packages/grpc/package.json b/packages/grpc/package.json index 625f921608d4..06d578e9c4ba 100644 --- a/packages/grpc/package.json +++ b/packages/grpc/package.json @@ -31,7 +31,9 @@ "dependencies": { "@midwayjs/core": "^2.5.5", "@midwayjs/decorator": "^2.4.7", - "@grpc/grpc-js": "^1.2.1" + "@grpc/grpc-js": "^1.2.1", + "camelcase": "^6.2.0", + "pascal-case": "^3.1.2" }, "author": "Harry Chen ", "repository": { diff --git a/packages/grpc/src/framework.ts b/packages/grpc/src/framework.ts index ce9f19464d77..90157d283e9f 100644 --- a/packages/grpc/src/framework.ts +++ b/packages/grpc/src/framework.ts @@ -1,11 +1,7 @@ -import { Server, ServerCredentials, loadPackageDefinition, setLogger } from '@grpc/grpc-js'; -import * as grpc from '@grpc/grpc-js'; +import { Server, ServerCredentials, setLogger, loadPackageDefinition } from '@grpc/grpc-js'; import { BaseFramework, getClassMetadata, - getPropertyDataFromClass, - getPropertyMetadata, - getProviderId, IMidwayBootstrapOptions, listModule, MidwayFrameworkType, @@ -13,12 +9,16 @@ import { } from '@midwayjs/core'; import { - MS_PRODUCER_KEY, MSProducerType + getProviderId, + MS_PRODUCER_KEY, + MSProducerType } from '@midwayjs/decorator'; import { IMidwayGRPCApplication, IMidwayGRPConfigurationOptions, } from './interface'; import { MidwayGRPCContextLogger } from './logger'; +import { pascalCase } from 'pascal-case'; +import * as camelCase from 'camelcase'; export class MidwayGRPCFramework extends BaseFramework< IMidwayGRPCApplication, @@ -44,22 +44,6 @@ export class MidwayGRPCFramework extends BaseFramework< this.app = server as IMidwayGRPCApplication; this.server = server; - // this.app.use((req, res, next) => { - // const ctx = { req, res } as IMidwayExpressContext; - // ctx.logger = new MidwayGRPCContextLogger(ctx, this.appLogger); - // ctx.startTime = Date.now(); - // ctx.requestContext = new MidwayRequestContainer( - // ctx, - // this.getApplicationContext() - // ); - // (req as any).requestContext = ctx.requestContext; - // ctx.requestContext.registerObject('req', req); - // ctx.requestContext.registerObject('res', res); - // ctx.requestContext.ready(); - // next(); - // }); - - await this.loadService(); } protected async afterContainerReady( @@ -74,31 +58,52 @@ export class MidwayGRPCFramework extends BaseFramework< return type === MSProducerType.GRPC; }); - console.log(gRPCModules); - if (this.configurationOptions.packageDefinition) { - const definitions = grpc.loadPackageDefinition(this.configurationOptions.packageDefinition); + const definitions = loadPackageDefinition(this.configurationOptions.packageDefinition); const protoModule = definitions[this.configurationOptions.package]; - for (const protoService in protoModule) { - // TODO get service from container - // TODO find method - // binding service to server - this.server.addService(protoService['service'], {sayHello: sayHello}); + for (const module of gRPCModules) { + const provideId = getProviderId(module); + let serviceName = pascalCase(provideId); + + if (protoModule[serviceName]) { + const protoService = protoModule[serviceName]['service']; + const serviceInstance = {}; + for (const method in protoService) { + serviceInstance[method] = async (...args) => { + const ctx = {} as any; + ctx.requestContext = new MidwayRequestContainer(ctx, this.getApplicationContext()); + ctx.logger = new MidwayGRPCContextLogger(ctx, this.appLogger); + + const service = await ctx.requestContext.getAsync(gRPCModules); + return service[camelCase(method)]?.apply(this, args); + }; + } + this.server.addService(protoService, serviceInstance); + } else { + this.logger.warn(`Proto ${serviceName} not found and not add to gRPC server`, {label: 'midway:gRPC'}); + } } } - - } public async run(): Promise { - this.server.bindAsync(`0.0.0.0:${this.configurationOptions.port}`, ServerCredentials.createInsecure(), (err: Error | null, bindPort: number) => { - if (err) { - throw err; - } + return new Promise((resolve, reject) => { + this.server.bindAsync(`127.0.0.1:${this.configurationOptions.port || 6565}`, ServerCredentials.createInsecure(), (err: Error | null, bindPort: number) => { + if (err) { + reject(err); + } + + this.server.start(); + this.logger.info(`Server port = ${bindPort} start success`, {label: 'midway:gRPC'}); + resolve(); + }); + }) + } - this.logger.info(`gRPC:Server:${bindPort}`, new Date().toLocaleString()); - this.server.start(); + public async beforeStop() { + this.server.tryShutdown(() => { + this.logger.info('Server shutdown success', { label: 'midway:gRPC' }); }); } diff --git a/packages/grpc/src/interface.ts b/packages/grpc/src/interface.ts index 13e2ead4622f..700a1b060a00 100644 --- a/packages/grpc/src/interface.ts +++ b/packages/grpc/src/interface.ts @@ -19,7 +19,7 @@ export interface IMidwayGRPConfigurationOptions { /** * protobuf package name */ - package: string; + package?: string; packageDefinition?: any; } diff --git a/packages/grpc/test/fixtures/base-app/src/interface.ts b/packages/grpc/test/fixtures/base-app/src/interface.ts new file mode 100644 index 000000000000..08081b12d9d9 --- /dev/null +++ b/packages/grpc/test/fixtures/base-app/src/interface.ts @@ -0,0 +1,14 @@ +import { Metadata } from '@grpc/grpc-js'; + +export namespace hero { + export interface HeroService { + findOne(data: HeroById, metadata?: Metadata): Promise; + } + export interface HeroById { + id?: number; + } + export interface Hero { + id?: number; + name?: string; + } +} diff --git a/packages/grpc/test/fixtures/base-app/src/producer/greeter.ts b/packages/grpc/test/fixtures/base-app/src/producer/greeter.ts index 7705879d422c..c35a679f5f1f 100644 --- a/packages/grpc/test/fixtures/base-app/src/producer/greeter.ts +++ b/packages/grpc/test/fixtures/base-app/src/producer/greeter.ts @@ -1,19 +1,7 @@ -import { - MetadataValue, - sendUnaryData, - ServerDuplexStream, - ServerReadableStream, - ServerUnaryCall, - ServerWritableStream, - status, - UntypedHandleCall -} from '@grpc/grpc-js'; -import { randomBytes } from 'crypto'; -import { ListValue, Struct, Value } from 'google-protobuf/google/protobuf/struct_pb'; - -import { IGreeterServer } from '../../models/helloworld_grpc_pb'; -import { HelloRequest, HelloResponse } from '../../models/helloworld_pb'; -import { logger, ServiceError } from '../utils'; +// import { +// sendUnaryData, +// ServerUnaryCall, +// } from '@grpc/grpc-js'; import { MSProducerType, Producer, Provide, GrpcMethod } from '@midwayjs/decorator'; @@ -23,89 +11,13 @@ import { MSProducerType, Producer, Provide, GrpcMethod } from '@midwayjs/decorat */ @Provide() @Producer(MSProducerType.GRPC) -export class Greeter implements IGreeterServer { - // Argument of type 'Greeter' is not assignable to parameter of type 'UntypedServiceImplementation'. - // Index signature is missing in type 'Greeter'.ts(2345) - [method: string]: UntypedHandleCall; +export class Greeter { @GrpcMethod() /** * Implements the SayHello RPC method. */ - public sayHello(call: ServerUnaryCall, callback: sendUnaryData): void { - logger.info('sayHello', Date.now()); - - const res: HelloResponse = new HelloResponse(); - const name: string = call.request.getName(); - logger.info('sayHelloName:', name); - - if (name === 'error') { - // https://grpc.io/grpc/node/grpc.html#.status__anchor - return callback(new ServiceError(status.INVALID_ARGUMENT, 'InvalidValue'), null); - } - - const metadataValue: MetadataValue[] = call.metadata.get('foo'); - logger.info('sayHelloMetadata:', metadataValue); - - res.setMessage(`Hello ${metadataValue.length > 0 ? metadataValue : name}`); - - const paramStruct: Struct | undefined = call.request.getParamStruct(); - const paramListValue: ListValue | undefined = call.request.getParamListValue(); - const paramValue: Value | undefined = call.request.getParamValue(); - logger.info('sayHelloStruct:', paramStruct?.toJavaScript()); - logger.info('sayHelloListValue:', paramListValue?.toJavaScript()); - logger.info('sayHelloValue:', paramValue?.toJavaScript()); - - if (paramStruct) { - // = res.setParamStruct(paramStruct); - res.setParamStruct(Struct.fromJavaScript(paramStruct.toJavaScript())); - } - res.setParamListValue(paramListValue); - res.setParamValue(paramValue); - - callback(null, res); - } - - public sayHelloStreamRequest(call: ServerReadableStream, callback: sendUnaryData): void { - logger.info('sayHelloStreamRequest:', call.getPeer()); - - const data: string[] = []; - call.on('data', (req: HelloRequest) => { - data.push(`${req.getName()} - ${randomBytes(5).toString('hex')}`); - }).on('end', () => { - const res: HelloResponse = new HelloResponse(); - res.setMessage(data.join('\n')); - - callback(null, res); - }).on('error', (err: Error) => { - callback(new ServiceError(status.INTERNAL, err.message), null); - }); - } - - public sayHelloStreamResponse(call: ServerWritableStream): void { - logger.info('sayHelloStreamResponse:', call.request.toObject()); - - const name: string = call.request.getName(); - - for (const text of Array(10).fill('').map(() => randomBytes(5).toString('hex'))) { - const res: HelloResponse = new HelloResponse(); - res.setMessage(`${name} - ${text}`); - call.write(res); - } - call.end(); - } - - public sayHelloStream(call: ServerDuplexStream): void { - logger.info('sayHelloStream:', call.getPeer()); - - call.on('data', (req: HelloRequest) => { - const res: HelloResponse = new HelloResponse(); - res.setMessage(`${req.getName()} - ${randomBytes(5).toString('hex')}`); - call.write(res); - }).on('end', () => { - call.end(); - }).on('error', (err: Error) => { - logger.error('sayHelloStream:', err); - }); + public sayHello(call: /*ServerUnaryCall*/ any, callback: /*sendUnaryData*/ any): void { + callback(null, { message: 'Hello ' + call.request.name }); } } diff --git a/packages/grpc/test/fixtures/base-app/src/producer/hero.ts b/packages/grpc/test/fixtures/base-app/src/producer/hero.ts new file mode 100644 index 000000000000..f5f1e5c6b952 --- /dev/null +++ b/packages/grpc/test/fixtures/base-app/src/producer/hero.ts @@ -0,0 +1,15 @@ +import { GrpcMethod, MSProducerType, Producer, Provide } from '@midwayjs/decorator'; +import { hero } from '../interface'; + +@Provide() +@Producer(MSProducerType.GRPC) +export class HeroService implements hero.HeroService{ + @GrpcMethod() + async findOne(data, metadata) { + const items = [ + { id: 1, name: 'John' }, + { id: 2, name: 'Doe' }, + ]; + return items.find(({ id }) => id === data.id); + } +} diff --git a/packages/grpc/test/fixtures/base-app/src/protos/helloworld.proto b/packages/grpc/test/fixtures/proto/helloworld.proto similarity index 100% rename from packages/grpc/test/fixtures/base-app/src/protos/helloworld.proto rename to packages/grpc/test/fixtures/proto/helloworld.proto diff --git a/packages/grpc/test/fixtures/proto/hero.proto b/packages/grpc/test/fixtures/proto/hero.proto new file mode 100644 index 000000000000..fa0c5d801a4b --- /dev/null +++ b/packages/grpc/test/fixtures/proto/hero.proto @@ -0,0 +1,16 @@ +syntax = "proto3"; + +package hero; + +service HeroService { + rpc FindOne (HeroById) returns (Hero) {} +} + +message HeroById { + int32 id = 1; +} + +message Hero { + int32 id = 1; + string name = 2; +} diff --git a/packages/grpc/test/index.test.ts b/packages/grpc/test/index.test.ts index 8b137891791f..3de6cf8df0cb 100644 --- a/packages/grpc/test/index.test.ts +++ b/packages/grpc/test/index.test.ts @@ -1 +1,15 @@ +import { createServer, closeApp } from './utils'; +import { join } from 'path'; +describe('/test/index.test.ts', function () { + + it('should create grpc server', async () => { + const app = await createServer('base-app', { + protoPath: join(__dirname, 'fixtures/proto/hero.proto'), + package: 'hero' + }); + expect(app.getAppDir()).toBeTruthy(); + expect(app.getApplicationContext()).toBeTruthy(); + await closeApp(app); + }); +}); diff --git a/packages/grpc/test/utils.ts b/packages/grpc/test/utils.ts index ada6d2a3ca53..928ecb652ded 100644 --- a/packages/grpc/test/utils.ts +++ b/packages/grpc/test/utils.ts @@ -9,7 +9,7 @@ import * as protoLoader from '@grpc/proto-loader'; * @param name * @param options */ -export async function creatApp(name: string, options: IMidwayGRPConfigurationOptions = {}): Promise { +export async function createServer(name: string, options: IMidwayGRPConfigurationOptions = {}): Promise { options.packageDefinition = protoLoader.loadSync(options.protoPath, { keepCase: true, longs: String, From 2dadb24793caf3e2f13da11c210b371e3b7d4b1a Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Sun, 3 Jan 2021 23:34:20 +0800 Subject: [PATCH 04/22] fix: close server when shutdown --- packages/decorator/package.json | 2 +- packages/mock/src/utils.ts | 8 ++++---- packages/socketio/test/index.test.ts | 4 ++-- packages/socketio/test/utils.ts | 2 +- packages/web-express/src/framework.ts | 4 ++++ packages/web-koa/src/framework.ts | 4 ++++ 6 files changed, 16 insertions(+), 8 deletions(-) diff --git a/packages/decorator/package.json b/packages/decorator/package.json index 1884d83b6307..b71e7e10b69e 100644 --- a/packages/decorator/package.json +++ b/packages/decorator/package.json @@ -14,7 +14,7 @@ "dependencies": { "@types/express": "^4.17.8", "@types/koa": "^2.11.4", - "camelcase": "^5.0.0", + "camelcase": "^6.2.0", "class-transformer": "^0.3.1", "joi": "^17.2.1", "reflect-metadata": "^0.1.13" diff --git a/packages/mock/src/utils.ts b/packages/mock/src/utils.ts index 3d29675d2a2f..e3dd04fed38f 100644 --- a/packages/mock/src/utils.ts +++ b/packages/mock/src/utils.ts @@ -156,11 +156,11 @@ export async function close( } if (isTestEnvironment()) { + // clean first + if (options.cleanLogsDir !== false && !isWin32()) { + await remove(join(newApp.getAppDir(), 'logs')); + } if (MidwayFrameworkType.WEB === newApp.getFrameworkType()) { - // clean first - if (options.cleanLogsDir !== false && !isWin32()) { - await remove(join(newApp.getAppDir(), 'logs')); - } if (options.cleanTempDir !== false && !isWin32()) { await remove(join(newApp.getAppDir(), 'run')); } diff --git a/packages/socketio/test/index.test.ts b/packages/socketio/test/index.test.ts index 3e8c4a334c4c..67a650ea9637 100644 --- a/packages/socketio/test/index.test.ts +++ b/packages/socketio/test/index.test.ts @@ -1,5 +1,5 @@ import * as socketClient from 'socket.io-client'; -import { closeApp, creatApp } from './utils'; +import { closeApp, createServer } from './utils'; function createClient(opts: SocketIOClient.ConnectOpts) { let url = 'http://127.0.0.1:' + opts.port; @@ -11,7 +11,7 @@ function createClient(opts: SocketIOClient.ConnectOpts) { describe('/test/index.test.ts', () => { it('should test create socket app and use default namespace', async () => { - const app = await creatApp('base-app', { port: 3000}); + const app = await createServer('base-app', { port: 3000}); const client = await createClient({ port: '3000', }); diff --git a/packages/socketio/test/utils.ts b/packages/socketio/test/utils.ts index 3c890957f74b..8a7d904fc2c0 100644 --- a/packages/socketio/test/utils.ts +++ b/packages/socketio/test/utils.ts @@ -7,7 +7,7 @@ import { close, createApp } from '@midwayjs/mock'; * @param name * @param options */ -export async function creatApp(name: string, options: IMidwaySocketIOConfigurationOptions = {}): Promise { +export async function createServer(name: string, options: IMidwaySocketIOConfigurationOptions = {}): Promise { return createApp(join(__dirname, 'fixtures', name), options, Framework); } diff --git a/packages/web-express/src/framework.ts b/packages/web-express/src/framework.ts index ee61d0c3f6cb..5a058b2739ce 100644 --- a/packages/web-express/src/framework.ts +++ b/packages/web-express/src/framework.ts @@ -346,6 +346,10 @@ export class MidwayExpressFramework extends BaseFramework< } } + public async beforeStop() { + this.server.close(); + } + public getServer() { return this.server; } diff --git a/packages/web-koa/src/framework.ts b/packages/web-koa/src/framework.ts index 6c0952f093ad..683da6ae609a 100644 --- a/packages/web-koa/src/framework.ts +++ b/packages/web-koa/src/framework.ts @@ -354,6 +354,10 @@ export class MidwayKoaFramework extends MidwayKoaBaseFramework< } } + public async beforeStop() { + this.server.close(); + } + public getFrameworkType(): MidwayFrameworkType { return MidwayFrameworkType.WEB_KOA; } From bcda934e83ad14e321a49e218091242acd7fa719 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Mon, 4 Jan 2021 00:52:45 +0800 Subject: [PATCH 05/22] chore: add coreLogger framework label --- packages/core/src/baseFramework.ts | 11 +++++++++-- packages/core/src/interface.ts | 6 +++++- packages/faas/src/framework.ts | 4 ++++ packages/faas/src/interface.ts | 7 ++++--- packages/grpc/src/framework.ts | 4 ++++ packages/grpc/src/interface.ts | 4 ++-- packages/rabbitmq/src/framework.ts | 4 ++++ packages/rabbitmq/src/interface.ts | 4 ++-- packages/socketio/src/framework.ts | 4 ++++ packages/socketio/src/interface.ts | 4 ++-- packages/web-express/src/framework.ts | 4 ++++ packages/web-express/src/interface.ts | 4 ++-- packages/web-koa/src/framework.ts | 4 ++++ packages/web-koa/src/interface.ts | 4 ++-- packages/web/src/framework/singleProcess.ts | 4 ++++ 15 files changed, 56 insertions(+), 16 deletions(-) diff --git a/packages/core/src/baseFramework.ts b/packages/core/src/baseFramework.ts index cc7e6d65afdf..4453f38dd58e 100644 --- a/packages/core/src/baseFramework.ts +++ b/packages/core/src/baseFramework.ts @@ -16,7 +16,7 @@ import { listModule, LOGGER_KEY, } from '@midwayjs/decorator'; -import { ILogger, loggers, LoggerOptions } from '@midwayjs/logger'; +import { ILogger, loggers, LoggerOptions, IMidwayLogger } from '@midwayjs/logger'; import { isAbsolute, join, dirname } from 'path'; import { createMidwayLogger } from './logger'; import { safeRequire } from './util'; @@ -48,6 +48,8 @@ export abstract class BaseFramework< public configure(options: T): BaseFramework { this.configurationOptions = options; + this.logger = options.logger; + this.appLogger = options.appLogger; return this; } @@ -108,11 +110,12 @@ export abstract class BaseFramework< protected async initializeLogger(options: IMidwayBootstrapOptions) { if (!this.logger) { this.logger = createMidwayLogger(this, 'coreLogger'); + (this.logger as IMidwayLogger).updateDefaultLabel(this.getFrameworkName()); } if (!this.appLogger) { this.appLogger = createMidwayLogger(this, 'logger', { fileLogName: 'midway-app.log', - }); + }) as IMidwayLogger; } } @@ -354,4 +357,8 @@ export abstract class BaseFramework< public getProjectName() { return this.pkg?.['name'] || ''; } + + public getFrameworkName() { + return this.getFrameworkType().toString(); + } } diff --git a/packages/core/src/interface.ts b/packages/core/src/interface.ts index ac35091b7f25..2df78b485917 100644 --- a/packages/core/src/interface.ts +++ b/packages/core/src/interface.ts @@ -331,7 +331,10 @@ export interface IMidwayBootstrapOptions { disableConflictCheck?: boolean; } -export interface IConfigurationOptions {} +export interface IConfigurationOptions { + logger?: ILogger; + appLogger?: ILogger; +} export interface IMidwayFramework { app: APP; @@ -345,6 +348,7 @@ export interface IMidwayFramework (context: FaaSContext, next: () => Promise) => any) | string; @@ -34,14 +35,14 @@ export interface FunctionHandler { } export interface FaaSContext extends FaaSHTTPContext { - logger: IMidwayLogger; + logger: ILogger; env: string; requestContext: MidwayRequestContainer; originContext: any; hooks: MidwayHooks; } -export interface IFaaSConfigurationOptions { +export interface IFaaSConfigurationOptions extends IConfigurationOptions { config?: object; middleware?: string[]; initializeContext?: object; diff --git a/packages/grpc/src/framework.ts b/packages/grpc/src/framework.ts index 90157d283e9f..716748f408f5 100644 --- a/packages/grpc/src/framework.ts +++ b/packages/grpc/src/framework.ts @@ -118,4 +118,8 @@ export class MidwayGRPCFramework extends BaseFramework< public getServer() { return this.server; } + + public getFrameworkName() { + return 'midway:gRPC' + } } diff --git a/packages/grpc/src/interface.ts b/packages/grpc/src/interface.ts index 700a1b060a00..61a9c7476441 100644 --- a/packages/grpc/src/interface.ts +++ b/packages/grpc/src/interface.ts @@ -1,4 +1,4 @@ -import { IMidwayApplication, IMidwayContext } from '@midwayjs/core'; +import { IConfigurationOptions, IMidwayApplication, IMidwayContext } from '@midwayjs/core'; import { Server } from '@grpc/grpc-js'; export type IMidwayGRPCContext = IMidwayContext & { @@ -6,7 +6,7 @@ export type IMidwayGRPCContext = IMidwayContext & { } export type IMidwayGRPCApplication = IMidwayApplication & Server; -export interface IMidwayGRPConfigurationOptions { +export interface IMidwayGRPConfigurationOptions extends IConfigurationOptions { /** * application gRPC port */ diff --git a/packages/rabbitmq/src/framework.ts b/packages/rabbitmq/src/framework.ts index 138e4fb3899c..688f43548033 100644 --- a/packages/rabbitmq/src/framework.ts +++ b/packages/rabbitmq/src/framework.ts @@ -118,4 +118,8 @@ export class MidwayRabbitMQFramework extends BaseFramework< } ); } + + public getFrameworkName() { + return 'midway:rabbitmq' + } } diff --git a/packages/rabbitmq/src/interface.ts b/packages/rabbitmq/src/interface.ts index adc69cd56034..0b1d532f9cdd 100644 --- a/packages/rabbitmq/src/interface.ts +++ b/packages/rabbitmq/src/interface.ts @@ -1,4 +1,4 @@ -import { IMidwayApplication, IMidwayContext } from '@midwayjs/core'; +import { IConfigurationOptions, IMidwayApplication, IMidwayContext } from '@midwayjs/core'; import { ConsumeMessage, Options } from 'amqplib/properties'; import { RabbitMQListenerOptions } from '@midwayjs/decorator'; import * as amqp from 'amqplib'; @@ -22,7 +22,7 @@ export interface IRabbitMQExchange { options?: Options.AssertExchange } -export type IMidwayRabbitMQConfigurationOptions = { +export interface IMidwayRabbitMQConfigurationOptions extends IConfigurationOptions { url: string | Options.Connect, socketOptions?: any; reconnectTime?: number; diff --git a/packages/socketio/src/framework.ts b/packages/socketio/src/framework.ts index 8330f872406e..91a58af863fa 100644 --- a/packages/socketio/src/framework.ts +++ b/packages/socketio/src/framework.ts @@ -225,4 +225,8 @@ export class MidwaySocketIOFramework extends BaseFramework< } } } + + public getFrameworkName() { + return 'midway:socketIO' + } } diff --git a/packages/socketio/src/interface.ts b/packages/socketio/src/interface.ts index f1d8ed4dce6b..b74395aec3d5 100644 --- a/packages/socketio/src/interface.ts +++ b/packages/socketio/src/interface.ts @@ -1,5 +1,5 @@ import * as SocketIO from 'socket.io'; -import { IMidwayApplication, IMidwayContext } from '@midwayjs/core'; +import { IConfigurationOptions, IMidwayApplication, IMidwayContext } from '@midwayjs/core'; import { Server as HttpServer } from 'http'; import { Server as HttpsServer } from 'https'; @@ -10,6 +10,6 @@ export type IMidwaySocketIOApplication = IMidwayApplication & { export type IMidwaySocketIOConfigurationOptions = { port?: number; webServer?: HttpServer | HttpsServer; -} & SocketIO.ServerOptions; +} & SocketIO.ServerOptions & IConfigurationOptions; export type IMidwaySocketIOContext = SocketIO.Socket & IMidwayContext; diff --git a/packages/web-express/src/framework.ts b/packages/web-express/src/framework.ts index 5a058b2739ce..25775756ffee 100644 --- a/packages/web-express/src/framework.ts +++ b/packages/web-express/src/framework.ts @@ -353,4 +353,8 @@ export class MidwayExpressFramework extends BaseFramework< public getServer() { return this.server; } + + public getFrameworkName() { + return 'midway:express' + } } diff --git a/packages/web-express/src/interface.ts b/packages/web-express/src/interface.ts index 02418a24b971..b7cb576bcc2f 100644 --- a/packages/web-express/src/interface.ts +++ b/packages/web-express/src/interface.ts @@ -1,4 +1,4 @@ -import { IMidwayApplication, IMidwayContext } from '@midwayjs/core'; +import { IConfigurationOptions, IMidwayApplication, IMidwayContext } from '@midwayjs/core'; import { Application, Request, Response, RequestHandler, NextFunction } from 'express'; import { RouterParamValue } from "@midwayjs/decorator"; @@ -27,7 +27,7 @@ export type IMidwayExpressApplication = IMidwayApplication & Application & { ): Middleware; }; -export interface IMidwayExpressConfigurationOptions { +export interface IMidwayExpressConfigurationOptions extends IConfigurationOptions { /** * application http port */ diff --git a/packages/web-koa/src/framework.ts b/packages/web-koa/src/framework.ts index 683da6ae609a..97d216b66543 100644 --- a/packages/web-koa/src/framework.ts +++ b/packages/web-koa/src/framework.ts @@ -362,6 +362,10 @@ export class MidwayKoaFramework extends MidwayKoaBaseFramework< return MidwayFrameworkType.WEB_KOA; } + public getFrameworkName() { + return 'midway:koa'; + } + public getServer() { return this.server; } diff --git a/packages/web-koa/src/interface.ts b/packages/web-koa/src/interface.ts index 90d0aec4623c..d47da133f7d7 100644 --- a/packages/web-koa/src/interface.ts +++ b/packages/web-koa/src/interface.ts @@ -1,4 +1,4 @@ -import { IMidwayApplication, IMidwayContext } from '@midwayjs/core'; +import { IConfigurationOptions, IMidwayApplication, IMidwayContext } from '@midwayjs/core'; import * as koa from 'koa'; import { Context, DefaultState, Middleware, Next } from 'koa'; import { RouterParamValue } from '@midwayjs/decorator'; @@ -19,7 +19,7 @@ export interface IMidwayKoaApplicationPlus { use(...args); } -export interface IMidwayKoaConfigurationOptions { +export interface IMidwayKoaConfigurationOptions extends IConfigurationOptions { /** * application http port */ diff --git a/packages/web/src/framework/singleProcess.ts b/packages/web/src/framework/singleProcess.ts index ad56b290b9dd..a655833056cf 100644 --- a/packages/web/src/framework/singleProcess.ts +++ b/packages/web/src/framework/singleProcess.ts @@ -127,4 +127,8 @@ export class SingleProcess public getServer() { return this.server; } + + public getFrameworkName() { + return 'midway:web' + } } From 69df61fb1de243e62ef7f465b99303921d51cafa Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Thu, 7 Jan 2021 10:46:00 +0800 Subject: [PATCH 06/22] chore: change name to provider --- packages/core/src/baseFramework.ts | 2 +- packages/decorator/src/common/constant.ts | 1 + .../src/microservice/{producer.ts => provider.ts} | 4 ++-- packages/grpc/src/comsumer/configuration.ts | 9 +++++++++ packages/grpc/src/index.ts | 3 ++- packages/grpc/src/{ => provider}/framework.ts | 10 +++++----- packages/grpc/src/{ => provider}/logger.ts | 2 +- .../base-app/src/{producer => provider}/greeter.ts | 4 ++-- .../base-app/src/{producer => provider}/hero.ts | 0 9 files changed, 23 insertions(+), 12 deletions(-) rename packages/decorator/src/microservice/{producer.ts => provider.ts} (93%) create mode 100644 packages/grpc/src/comsumer/configuration.ts rename packages/grpc/src/{ => provider}/framework.ts (95%) rename packages/grpc/src/{ => provider}/logger.ts (92%) rename packages/grpc/test/fixtures/base-app/src/{producer => provider}/greeter.ts (82%) rename packages/grpc/test/fixtures/base-app/src/{producer => provider}/hero.ts (100%) diff --git a/packages/core/src/baseFramework.ts b/packages/core/src/baseFramework.ts index 4453f38dd58e..34d208696f9f 100644 --- a/packages/core/src/baseFramework.ts +++ b/packages/core/src/baseFramework.ts @@ -109,7 +109,7 @@ export abstract class BaseFramework< protected async initializeLogger(options: IMidwayBootstrapOptions) { if (!this.logger) { - this.logger = createMidwayLogger(this, 'coreLogger'); + this.logger = new Proxy(createMidwayLogger(this, 'coreLogger'), {}); (this.logger as IMidwayLogger).updateDefaultLabel(this.getFrameworkName()); } if (!this.appLogger) { diff --git a/packages/decorator/src/common/constant.ts b/packages/decorator/src/common/constant.ts index 05a9e64c7ea4..efa7e80f431c 100644 --- a/packages/decorator/src/common/constant.ts +++ b/packages/decorator/src/common/constant.ts @@ -35,6 +35,7 @@ export const RPC_DUBBO_KEY = 'rpc:dubbo'; // microservice export const MS_CONSUMER_KEY = 'ms:consumer'; export const MS_PRODUCER_KEY = 'ms:producer'; +export const MS_PROVIDER_KEY = 'ms:provider'; // rpc method export const MS_GRPC_METHOD_KEY = 'ms:grpc:method'; diff --git a/packages/decorator/src/microservice/producer.ts b/packages/decorator/src/microservice/provider.ts similarity index 93% rename from packages/decorator/src/microservice/producer.ts rename to packages/decorator/src/microservice/provider.ts index fd594caeff40..5c90284edf65 100644 --- a/packages/decorator/src/microservice/producer.ts +++ b/packages/decorator/src/microservice/provider.ts @@ -10,13 +10,13 @@ import { } from '../'; import { Scope } from '../annotation'; -export enum MSProducerType { +export enum MSProviderType { DUBBO = 'dubbo', GRPC = 'gRPC', HSF = 'hsf', } -export function Producer(type: MSProducerType): ClassDecorator { +export function Provider(type: MSProviderType): ClassDecorator { return (target: any) => { saveModule(MS_PRODUCER_KEY, target); saveClassMetadata(MS_PRODUCER_KEY, type, target); diff --git a/packages/grpc/src/comsumer/configuration.ts b/packages/grpc/src/comsumer/configuration.ts new file mode 100644 index 000000000000..3a1f05f76f74 --- /dev/null +++ b/packages/grpc/src/comsumer/configuration.ts @@ -0,0 +1,9 @@ +import { Configuration } from '@midwayjs/decorator'; + +@Configuration({ + namespace: 'grpc' +}) +export class AutoConfiguration { + async onReady() { + } +} diff --git a/packages/grpc/src/index.ts b/packages/grpc/src/index.ts index 7382fadf3777..565d0326960e 100644 --- a/packages/grpc/src/index.ts +++ b/packages/grpc/src/index.ts @@ -1,2 +1,3 @@ export * from './interface'; -export { MidwayGRPCFramework as Framework } from './framework'; +export { MidwayGRPCFramework as Framework } from './provider/framework'; +export { AutoConfiguration as Configuration } from './comsumer/configuration'; diff --git a/packages/grpc/src/framework.ts b/packages/grpc/src/provider/framework.ts similarity index 95% rename from packages/grpc/src/framework.ts rename to packages/grpc/src/provider/framework.ts index 716748f408f5..b9f22f178eb6 100644 --- a/packages/grpc/src/framework.ts +++ b/packages/grpc/src/provider/framework.ts @@ -15,7 +15,7 @@ import { } from '@midwayjs/decorator'; import { IMidwayGRPCApplication, IMidwayGRPConfigurationOptions, -} from './interface'; +} from '../interface'; import { MidwayGRPCContextLogger } from './logger'; import { pascalCase } from 'pascal-case'; import * as camelCase from 'camelcase'; @@ -88,22 +88,22 @@ export class MidwayGRPCFramework extends BaseFramework< } public async run(): Promise { - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { this.server.bindAsync(`127.0.0.1:${this.configurationOptions.port || 6565}`, ServerCredentials.createInsecure(), (err: Error | null, bindPort: number) => { if (err) { reject(err); } this.server.start(); - this.logger.info(`Server port = ${bindPort} start success`, {label: 'midway:gRPC'}); + this.logger.info(`Server port = ${bindPort} start success`); resolve(); }); - }) + }); } public async beforeStop() { this.server.tryShutdown(() => { - this.logger.info('Server shutdown success', { label: 'midway:gRPC' }); + this.logger.info('Server shutdown success'); }); } diff --git a/packages/grpc/src/logger.ts b/packages/grpc/src/provider/logger.ts similarity index 92% rename from packages/grpc/src/logger.ts rename to packages/grpc/src/provider/logger.ts index e9e9c6504768..7e3e8821dd69 100644 --- a/packages/grpc/src/logger.ts +++ b/packages/grpc/src/provider/logger.ts @@ -1,5 +1,5 @@ import { MidwayContextLogger } from '@midwayjs/core'; -import { IMidwayGRPCContext } from './interface'; +import { IMidwayGRPCContext } from '../interface'; export class MidwayGRPCContextLogger extends MidwayContextLogger< IMidwayGRPCContext diff --git a/packages/grpc/test/fixtures/base-app/src/producer/greeter.ts b/packages/grpc/test/fixtures/base-app/src/provider/greeter.ts similarity index 82% rename from packages/grpc/test/fixtures/base-app/src/producer/greeter.ts rename to packages/grpc/test/fixtures/base-app/src/provider/greeter.ts index c35a679f5f1f..66c69fc88cc4 100644 --- a/packages/grpc/test/fixtures/base-app/src/producer/greeter.ts +++ b/packages/grpc/test/fixtures/base-app/src/provider/greeter.ts @@ -3,14 +3,14 @@ // ServerUnaryCall, // } from '@grpc/grpc-js'; -import { MSProducerType, Producer, Provide, GrpcMethod } from '@midwayjs/decorator'; +import { MSProviderType, Provider, Provide, GrpcMethod } from '@midwayjs/decorator'; /** * package helloworld * service Greeter */ @Provide() -@Producer(MSProducerType.GRPC) +@Provider(MSProviderType.GRPC) export class Greeter { @GrpcMethod() diff --git a/packages/grpc/test/fixtures/base-app/src/producer/hero.ts b/packages/grpc/test/fixtures/base-app/src/provider/hero.ts similarity index 100% rename from packages/grpc/test/fixtures/base-app/src/producer/hero.ts rename to packages/grpc/test/fixtures/base-app/src/provider/hero.ts From f41dc85c605be43a51a9e46f2586b62aeca65201 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Sat, 9 Jan 2021 10:57:13 +0800 Subject: [PATCH 07/22] feat: add consumer --- packages/decorator/src/index.ts | 2 +- packages/grpc/package.json | 13 +++--- packages/grpc/src/comsumer/configuration.ts | 41 ++++++++++++++++++- packages/grpc/src/interface.ts | 2 + packages/grpc/src/provider/framework.ts | 10 ++--- .../fixtures/base-app/src/provider/hero.ts | 4 +- 6 files changed, 57 insertions(+), 15 deletions(-) diff --git a/packages/decorator/src/index.ts b/packages/decorator/src/index.ts index b6ec3b9bfa45..c7a94135fabe 100644 --- a/packages/decorator/src/index.ts +++ b/packages/decorator/src/index.ts @@ -18,7 +18,7 @@ export * from './framework/plugin'; export * from './framework/app'; export * from './ws/webSocketController'; export * from './ws/webSocketEvent'; -export * from './microservice/producer'; +export * from './microservice/provider'; export * from './microservice/consumer'; export * from './microservice/rabbitmqListener'; export * from './util/index'; diff --git a/packages/grpc/package.json b/packages/grpc/package.json index 06d578e9c4ba..790f4afa6e94 100644 --- a/packages/grpc/package.json +++ b/packages/grpc/package.json @@ -6,8 +6,8 @@ "typings": "dist/index.d.ts", "scripts": { "build": "midway-bin build -c", - "test": "midway-bin test --forceExit", - "cov": "midway-bin cov --forceExit", + "test": "midway-bin test --ts", + "cov": "midway-bin cov --ts", "ci": "npm run test" }, "keywords": [ @@ -23,14 +23,15 @@ ], "license": "MIT", "devDependencies": { - "@midwayjs/cli": "^1.0.0", - "@midwayjs/mock": "^2.5.5", + "@midwayjs/cli": "^1.2.36", + "@midwayjs/mock": "^2.6.8", "@grpc/proto-loader": "^0.5.5", "fs-extra": "^8.0.1" }, "dependencies": { - "@midwayjs/core": "^2.5.5", - "@midwayjs/decorator": "^2.4.7", + "@midwayjs/core": "^2.6.8", + "@midwayjs/decorator": "^2.4.8", + "@midwayjs/logger": "^2.6.8", "@grpc/grpc-js": "^1.2.1", "camelcase": "^6.2.0", "pascal-case": "^3.1.2" diff --git a/packages/grpc/src/comsumer/configuration.ts b/packages/grpc/src/comsumer/configuration.ts index 3a1f05f76f74..eb87f47e2c60 100644 --- a/packages/grpc/src/comsumer/configuration.ts +++ b/packages/grpc/src/comsumer/configuration.ts @@ -1,9 +1,48 @@ -import { Configuration } from '@midwayjs/decorator'; +import { Config, Configuration, getProviderId, Logger } from '@midwayjs/decorator'; +import { IMidwayGRPCOptions } from '../interface'; +import { Server, ServerCredentials, setLogger, loadPackageDefinition } from '@grpc/grpc-js'; +import * as camelCase from 'camelcase'; +import { ILogger } from '@midwayjs/logger'; @Configuration({ namespace: 'grpc' }) export class AutoConfiguration { + + @Config() + grpcConfig: IMidwayGRPCOptions; + + @Logger() + logger: ILogger; + async onReady() { + setLogger(this.logger); + if (this.grpcConfig.packageDefinition) { + const definitions = loadPackageDefinition(this.grpcConfig.packageDefinition); + const protoModule = definitions[this.grpcConfig.package]; + + for (const module of gRPCModules) { + const provideId = getProviderId(module); + let serviceName = pascalCase(provideId); + + if (protoModule[serviceName]) { + const protoService = protoModule[serviceName]['service']; + const serviceInstance = {}; + for (const method in protoService) { + serviceInstance[method] = async (...args) => { + const ctx = {} as any; + ctx.requestContext = new MidwayRequestContainer(ctx, this.getApplicationContext()); + ctx.logger = new MidwayGRPCContextLogger(ctx, this.appLogger); + + const service = await ctx.requestContext.getAsync(gRPCModules); + return service[camelCase(method)]?.apply(this, args); + }; + } + this.server.addService(protoService, serviceInstance); + } else { + this.logger.warn(`Proto ${serviceName} not found and not add to gRPC server`, {label: 'midway:gRPC'}); + } + } + } } } diff --git a/packages/grpc/src/interface.ts b/packages/grpc/src/interface.ts index 61a9c7476441..7f306680abaa 100644 --- a/packages/grpc/src/interface.ts +++ b/packages/grpc/src/interface.ts @@ -23,3 +23,5 @@ export interface IMidwayGRPConfigurationOptions extends IConfigurationOptions { packageDefinition?: any; } + +export interface IMidwayGRPCOptions extends IMidwayGRPConfigurationOptions {} diff --git a/packages/grpc/src/provider/framework.ts b/packages/grpc/src/provider/framework.ts index b9f22f178eb6..9a6bfe1a4c02 100644 --- a/packages/grpc/src/provider/framework.ts +++ b/packages/grpc/src/provider/framework.ts @@ -10,8 +10,8 @@ import { import { getProviderId, - MS_PRODUCER_KEY, - MSProducerType + MS_PROVIDER_KEY, + MSProviderType } from '@midwayjs/decorator'; import { IMidwayGRPCApplication, IMidwayGRPConfigurationOptions, @@ -53,9 +53,9 @@ export class MidwayGRPCFramework extends BaseFramework< } protected async loadService() { - const gRPCModules = listModule(MS_PRODUCER_KEY, (module) => { - const type = getClassMetadata(MS_PRODUCER_KEY, module); - return type === MSProducerType.GRPC; + const gRPCModules = listModule(MS_PROVIDER_KEY, (module) => { + const type = getClassMetadata(MS_PROVIDER_KEY, module); + return type === MSProviderType.GRPC; }); if (this.configurationOptions.packageDefinition) { diff --git a/packages/grpc/test/fixtures/base-app/src/provider/hero.ts b/packages/grpc/test/fixtures/base-app/src/provider/hero.ts index f5f1e5c6b952..044d484d8765 100644 --- a/packages/grpc/test/fixtures/base-app/src/provider/hero.ts +++ b/packages/grpc/test/fixtures/base-app/src/provider/hero.ts @@ -1,8 +1,8 @@ -import { GrpcMethod, MSProducerType, Producer, Provide } from '@midwayjs/decorator'; +import { GrpcMethod, MSProviderType, Provider, Provide } from '@midwayjs/decorator'; import { hero } from '../interface'; @Provide() -@Producer(MSProducerType.GRPC) +@Provider(MSProviderType.GRPC) export class HeroService implements hero.HeroService{ @GrpcMethod() async findOne(data, metadata) { From 38c7bb9bc718af8d215eeb051932249f6c38b639 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Sat, 9 Jan 2021 23:27:53 +0800 Subject: [PATCH 08/22] feat: add consumer case --- packages/grpc/package.json | 6 +-- packages/grpc/src/comsumer/configuration.ts | 43 +++++-------------- packages/grpc/src/interface.ts | 7 ++- packages/grpc/src/provider/framework.ts | 2 +- .../base-app/src/config/config.default.ts | 11 +++++ .../fixtures/base-app/src/configuration.ts | 13 ++++++ .../base-app/src/consumer/greeter.service.ts | 34 +++++++++++++++ .../test/fixtures/base-app/src/interface.ts | 14 ++++++ .../fixtures/base-app/src/provider/hero.ts | 21 ++++++--- 9 files changed, 106 insertions(+), 45 deletions(-) create mode 100644 packages/grpc/test/fixtures/base-app/src/config/config.default.ts create mode 100644 packages/grpc/test/fixtures/base-app/src/configuration.ts create mode 100644 packages/grpc/test/fixtures/base-app/src/consumer/greeter.service.ts diff --git a/packages/grpc/package.json b/packages/grpc/package.json index 790f4afa6e94..82df9637576b 100644 --- a/packages/grpc/package.json +++ b/packages/grpc/package.json @@ -24,14 +24,14 @@ "license": "MIT", "devDependencies": { "@midwayjs/cli": "^1.2.36", - "@midwayjs/mock": "^2.6.8", + "@midwayjs/mock": "^2.6.9", "@grpc/proto-loader": "^0.5.5", "fs-extra": "^8.0.1" }, "dependencies": { - "@midwayjs/core": "^2.6.8", + "@midwayjs/core": "^2.6.9", "@midwayjs/decorator": "^2.4.8", - "@midwayjs/logger": "^2.6.8", + "@midwayjs/logger": "^2.6.9", "@grpc/grpc-js": "^1.2.1", "camelcase": "^6.2.0", "pascal-case": "^3.1.2" diff --git a/packages/grpc/src/comsumer/configuration.ts b/packages/grpc/src/comsumer/configuration.ts index eb87f47e2c60..b8ccaced6a2c 100644 --- a/packages/grpc/src/comsumer/configuration.ts +++ b/packages/grpc/src/comsumer/configuration.ts @@ -1,7 +1,6 @@ -import { Config, Configuration, getProviderId, Logger } from '@midwayjs/decorator'; -import { IMidwayGRPCOptions } from '../interface'; -import { Server, ServerCredentials, setLogger, loadPackageDefinition } from '@grpc/grpc-js'; -import * as camelCase from 'camelcase'; +import { Config, Configuration, Logger } from '@midwayjs/decorator'; +import { IMidwayGRPCConfigOptions } from '../interface'; +import { setLogger, loadPackageDefinition } from '@grpc/grpc-js'; import { ILogger } from '@midwayjs/logger'; @Configuration({ @@ -10,39 +9,19 @@ import { ILogger } from '@midwayjs/logger'; export class AutoConfiguration { @Config() - grpcConfig: IMidwayGRPCOptions; + grpcConfig: IMidwayGRPCConfigOptions; - @Logger() + @Logger('coreLogger') logger: ILogger; - async onReady() { + async onReady(container) { setLogger(this.logger); - if (this.grpcConfig.packageDefinition) { - const definitions = loadPackageDefinition(this.grpcConfig.packageDefinition); - const protoModule = definitions[this.grpcConfig.package]; - - for (const module of gRPCModules) { - const provideId = getProviderId(module); - let serviceName = pascalCase(provideId); - - if (protoModule[serviceName]) { - const protoService = protoModule[serviceName]['service']; - const serviceInstance = {}; - for (const method in protoService) { - serviceInstance[method] = async (...args) => { - const ctx = {} as any; - ctx.requestContext = new MidwayRequestContainer(ctx, this.getApplicationContext()); - ctx.logger = new MidwayGRPCContextLogger(ctx, this.appLogger); - - const service = await ctx.requestContext.getAsync(gRPCModules); - return service[camelCase(method)]?.apply(this, args); - }; - } - this.server.addService(protoService, serviceInstance); - } else { - this.logger.warn(`Proto ${serviceName} not found and not add to gRPC server`, {label: 'midway:gRPC'}); - } + for(const client of this.grpcConfig.clients) { + if (client.packageDefinition) { + const definitions = loadPackageDefinition(client.packageDefinition); + container.registerObject(`definitions:${client.package}`, definitions); } } + } } diff --git a/packages/grpc/src/interface.ts b/packages/grpc/src/interface.ts index 7f306680abaa..d0167605d789 100644 --- a/packages/grpc/src/interface.ts +++ b/packages/grpc/src/interface.ts @@ -6,7 +6,8 @@ export type IMidwayGRPCContext = IMidwayContext & { } export type IMidwayGRPCApplication = IMidwayApplication & Server; -export interface IMidwayGRPConfigurationOptions extends IConfigurationOptions { +export interface IMidwayGRPFrameworkOptions extends IConfigurationOptions { + host?: string; /** * application gRPC port */ @@ -24,4 +25,6 @@ export interface IMidwayGRPConfigurationOptions extends IConfigurationOptions { packageDefinition?: any; } -export interface IMidwayGRPCOptions extends IMidwayGRPConfigurationOptions {} +export interface IMidwayGRPCConfigOptions { + clients: IMidwayGRPFrameworkOptions[]; +} diff --git a/packages/grpc/src/provider/framework.ts b/packages/grpc/src/provider/framework.ts index 9a6bfe1a4c02..975b65ca376f 100644 --- a/packages/grpc/src/provider/framework.ts +++ b/packages/grpc/src/provider/framework.ts @@ -81,7 +81,7 @@ export class MidwayGRPCFramework extends BaseFramework< } this.server.addService(protoService, serviceInstance); } else { - this.logger.warn(`Proto ${serviceName} not found and not add to gRPC server`, {label: 'midway:gRPC'}); + this.logger.warn(`Proto ${serviceName} not found and not add to gRPC server`); } } } diff --git a/packages/grpc/test/fixtures/base-app/src/config/config.default.ts b/packages/grpc/test/fixtures/base-app/src/config/config.default.ts new file mode 100644 index 000000000000..85ce1e5c24ea --- /dev/null +++ b/packages/grpc/test/fixtures/base-app/src/config/config.default.ts @@ -0,0 +1,11 @@ +import { IMidwayGRPCConfigOptions } from '../../../../../src'; + +export const grpc = { + clients: [ + { + host: 'localhost', + port: 50051, + protoPath: '' + } + ] +} as IMidwayGRPCConfigOptions; diff --git a/packages/grpc/test/fixtures/base-app/src/configuration.ts b/packages/grpc/test/fixtures/base-app/src/configuration.ts new file mode 100644 index 000000000000..d84c1d127a80 --- /dev/null +++ b/packages/grpc/test/fixtures/base-app/src/configuration.ts @@ -0,0 +1,13 @@ +import { Configuration } from '@midwayjs/decorator'; +import * as grpc from '../src/../../../../src'; + +@Configuration({ + imports: [ + grpc + ] +}) +export class AutoConfiguration { + async onReady() { + console.log('on ready and load grpc component'); + } +} diff --git a/packages/grpc/test/fixtures/base-app/src/consumer/greeter.service.ts b/packages/grpc/test/fixtures/base-app/src/consumer/greeter.service.ts new file mode 100644 index 000000000000..de6e9c0bc090 --- /dev/null +++ b/packages/grpc/test/fixtures/base-app/src/consumer/greeter.service.ts @@ -0,0 +1,34 @@ +import { Config, Init, Inject, Provide, Scope, ScopeEnum } from '@midwayjs/decorator'; +import { helloworld } from '../interface'; +import { credentials } from '@grpc/grpc-js'; +import { IMidwayGRPCConfigOptions } from '../../../../../src'; + +@Provide() +@Scope(ScopeEnum.Singleton) +export class GreeterService implements helloworld.Greeter { + + client; + + @Inject('grpc:definitions:helloworld') + grpcDefinition; + + @Config('grpc') + grpcConfig: IMidwayGRPCConfigOptions; + + @Init() + async initService() { + const helloworld_proto = this.grpcDefinition['helloworld']; + this.client = new helloworld_proto.Greeter('localhost:50051', credentials.createInsecure()); + } + + async sayHello(request: helloworld.HelloRequest): Promise { + return new Promise((resolve, reject) => { + this.client.sayHello(request, (err, response) => { + if (err) { + reject(err); + } + resolve(response); + }); + }); + } +} diff --git a/packages/grpc/test/fixtures/base-app/src/interface.ts b/packages/grpc/test/fixtures/base-app/src/interface.ts index 08081b12d9d9..12447457d823 100644 --- a/packages/grpc/test/fixtures/base-app/src/interface.ts +++ b/packages/grpc/test/fixtures/base-app/src/interface.ts @@ -12,3 +12,17 @@ export namespace hero { name?: string; } } + +export namespace helloworld { + export interface Greeter { + sayHello (request: HelloRequest): Promise + } + + export interface HelloRequest { + name: string; + } + + export interface HelloReply { + message: string; + } +} diff --git a/packages/grpc/test/fixtures/base-app/src/provider/hero.ts b/packages/grpc/test/fixtures/base-app/src/provider/hero.ts index 044d484d8765..74c3e1752a41 100644 --- a/packages/grpc/test/fixtures/base-app/src/provider/hero.ts +++ b/packages/grpc/test/fixtures/base-app/src/provider/hero.ts @@ -1,15 +1,22 @@ -import { GrpcMethod, MSProviderType, Provider, Provide } from '@midwayjs/decorator'; +import { GrpcMethod, MSProviderType, Provider, Provide, Inject } from '@midwayjs/decorator'; import { hero } from '../interface'; +import { GreeterService } from '../consumer/greeter.service'; @Provide() @Provider(MSProviderType.GRPC) -export class HeroService implements hero.HeroService{ +export class HeroService implements hero.HeroService { + + @Inject() + greeterService: GreeterService; + @GrpcMethod() async findOne(data, metadata) { - const items = [ - { id: 1, name: 'John' }, - { id: 2, name: 'Doe' }, - ]; - return items.find(({ id }) => id === data.id); + const result = await this.greeterService.sayHello({ + name: 'harry' + }); + return { + id: 1, + name: result.message, + }; } } From 81f3cf74293e9b5275c2602d275593cc1e34d254 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Thu, 14 Jan 2021 00:54:09 +0800 Subject: [PATCH 09/22] feat: add autoload decorator --- packages/decorator/src/annotation/autoload.ts | 7 +++ packages/decorator/src/annotation/index.ts | 1 + packages/grpc/package.json | 2 +- packages/grpc/src/comsumer/clients.ts | 41 ++++++++++++++ packages/grpc/src/comsumer/configuration.ts | 17 +----- packages/grpc/src/index.ts | 1 + packages/grpc/src/interface.ts | 6 +- packages/grpc/src/provider/framework.ts | 55 +++++++++---------- packages/grpc/src/util.ts | 12 ++++ .../base-app/src/config/config.default.ts | 3 +- .../base-app/src/consumer/greeter.service.ts | 34 ------------ .../fixtures/base-app/src/provider/hero.ts | 17 ++++-- packages/grpc/test/utils.ts | 13 +---- 13 files changed, 113 insertions(+), 96 deletions(-) create mode 100644 packages/decorator/src/annotation/autoload.ts create mode 100644 packages/grpc/src/comsumer/clients.ts create mode 100644 packages/grpc/src/util.ts delete mode 100644 packages/grpc/test/fixtures/base-app/src/consumer/greeter.service.ts diff --git a/packages/decorator/src/annotation/autoload.ts b/packages/decorator/src/annotation/autoload.ts new file mode 100644 index 000000000000..20e6f362ab20 --- /dev/null +++ b/packages/decorator/src/annotation/autoload.ts @@ -0,0 +1,7 @@ +import { savePreloadModule } from '../common/decoratorManager'; + +export function Autoload() { + return function (target) { + savePreloadModule(target); + }; +} diff --git a/packages/decorator/src/annotation/index.ts b/packages/decorator/src/annotation/index.ts index a423baf81c54..07d34c3cba2b 100644 --- a/packages/decorator/src/annotation/index.ts +++ b/packages/decorator/src/annotation/index.ts @@ -8,3 +8,4 @@ export * from './pipeline'; export * from './validate'; export * from './rule'; export * from './aspect'; +export * from './autoload'; diff --git a/packages/grpc/package.json b/packages/grpc/package.json index 82df9637576b..bfd1e42b680d 100644 --- a/packages/grpc/package.json +++ b/packages/grpc/package.json @@ -25,7 +25,6 @@ "devDependencies": { "@midwayjs/cli": "^1.2.36", "@midwayjs/mock": "^2.6.9", - "@grpc/proto-loader": "^0.5.5", "fs-extra": "^8.0.1" }, "dependencies": { @@ -33,6 +32,7 @@ "@midwayjs/decorator": "^2.4.8", "@midwayjs/logger": "^2.6.9", "@grpc/grpc-js": "^1.2.1", + "@grpc/proto-loader": "^0.5.5", "camelcase": "^6.2.0", "pascal-case": "^3.1.2" }, diff --git a/packages/grpc/src/comsumer/clients.ts b/packages/grpc/src/comsumer/clients.ts new file mode 100644 index 000000000000..368d2f888635 --- /dev/null +++ b/packages/grpc/src/comsumer/clients.ts @@ -0,0 +1,41 @@ +import { Config, Init, Provide, Scope, ScopeEnum, Autoload } from '@midwayjs/decorator'; +import { credentials } from '@grpc/grpc-js'; +import { IMidwayGRPCConfigOptions } from '../interface'; +import { loadProto } from '../util'; + +@Provide('clients') +@Autoload() +@Scope(ScopeEnum.Singleton) +export class GRPCClients extends Map { + + @Config('grpc') + grpcConfig: IMidwayGRPCConfigOptions; + + @Init() + async initService() { + for(const cfg of this.grpcConfig['clients']) { + const packageDefinition = await loadProto(cfg); + const packageProtos = packageDefinition[cfg.package]; + for(const serviceName in packageProtos) { + const ProtoService = packageProtos[serviceName]['service']; + const connectionService = new ProtoService(cfg.host + ':' + cfg.port, credentials.createInsecure()); + this.set(serviceName, connectionService) + } + } + } + + getService(serviceName: string): T { + return this.get(serviceName); + } + + // async sayHello(request: helloworld.HelloRequest): Promise { + // return new Promise((resolve, reject) => { + // this.client.sayHello(request, (err, response) => { + // if (err) { + // reject(err); + // } + // resolve(response); + // }); + // }); + // } +} diff --git a/packages/grpc/src/comsumer/configuration.ts b/packages/grpc/src/comsumer/configuration.ts index b8ccaced6a2c..3e6b56b60ce0 100644 --- a/packages/grpc/src/comsumer/configuration.ts +++ b/packages/grpc/src/comsumer/configuration.ts @@ -1,6 +1,5 @@ -import { Config, Configuration, Logger } from '@midwayjs/decorator'; -import { IMidwayGRPCConfigOptions } from '../interface'; -import { setLogger, loadPackageDefinition } from '@grpc/grpc-js'; +import { Configuration, Logger } from '@midwayjs/decorator'; +import { setLogger } from '@grpc/grpc-js'; import { ILogger } from '@midwayjs/logger'; @Configuration({ @@ -8,20 +7,10 @@ import { ILogger } from '@midwayjs/logger'; }) export class AutoConfiguration { - @Config() - grpcConfig: IMidwayGRPCConfigOptions; - @Logger('coreLogger') logger: ILogger; - async onReady(container) { + async onReady() { setLogger(this.logger); - for(const client of this.grpcConfig.clients) { - if (client.packageDefinition) { - const definitions = loadPackageDefinition(client.packageDefinition); - container.registerObject(`definitions:${client.package}`, definitions); - } - } - } } diff --git a/packages/grpc/src/index.ts b/packages/grpc/src/index.ts index 565d0326960e..f240c4e1edac 100644 --- a/packages/grpc/src/index.ts +++ b/packages/grpc/src/index.ts @@ -1,3 +1,4 @@ export * from './interface'; export { MidwayGRPCFramework as Framework } from './provider/framework'; export { AutoConfiguration as Configuration } from './comsumer/configuration'; +export { GRPCClients as Clients } from './comsumer/clients'; diff --git a/packages/grpc/src/interface.ts b/packages/grpc/src/interface.ts index d0167605d789..908bad6495fa 100644 --- a/packages/grpc/src/interface.ts +++ b/packages/grpc/src/interface.ts @@ -1,5 +1,5 @@ import { IConfigurationOptions, IMidwayApplication, IMidwayContext } from '@midwayjs/core'; -import { Server } from '@grpc/grpc-js'; +import { Server, ServerCredentials } from '@grpc/grpc-js'; export type IMidwayGRPCContext = IMidwayContext & { startTime: number; @@ -22,7 +22,9 @@ export interface IMidwayGRPFrameworkOptions extends IConfigurationOptions { */ package?: string; - packageDefinition?: any; + loaderOptions?: object; + + credentials?: ServerCredentials; } export interface IMidwayGRPCConfigOptions { diff --git a/packages/grpc/src/provider/framework.ts b/packages/grpc/src/provider/framework.ts index 975b65ca376f..c9483e4b38f1 100644 --- a/packages/grpc/src/provider/framework.ts +++ b/packages/grpc/src/provider/framework.ts @@ -1,4 +1,4 @@ -import { Server, ServerCredentials, setLogger, loadPackageDefinition } from '@grpc/grpc-js'; +import { Server, ServerCredentials, setLogger } from '@grpc/grpc-js'; import { BaseFramework, getClassMetadata, @@ -14,21 +14,22 @@ import { MSProviderType } from '@midwayjs/decorator'; import { - IMidwayGRPCApplication, IMidwayGRPConfigurationOptions, + IMidwayGRPCApplication, IMidwayGRPFrameworkOptions, } from '../interface'; import { MidwayGRPCContextLogger } from './logger'; import { pascalCase } from 'pascal-case'; import * as camelCase from 'camelcase'; +import { loadProto } from '../util'; export class MidwayGRPCFramework extends BaseFramework< IMidwayGRPCApplication, - IMidwayGRPConfigurationOptions + IMidwayGRPFrameworkOptions > { public app: IMidwayGRPCApplication; private server: Server; public configure( - options: IMidwayGRPConfigurationOptions + options: IMidwayGRPFrameworkOptions ): MidwayGRPCFramework { this.configurationOptions = options; return this; @@ -58,31 +59,29 @@ export class MidwayGRPCFramework extends BaseFramework< return type === MSProviderType.GRPC; }); - if (this.configurationOptions.packageDefinition) { - const definitions = loadPackageDefinition(this.configurationOptions.packageDefinition); - const protoModule = definitions[this.configurationOptions.package]; - - for (const module of gRPCModules) { - const provideId = getProviderId(module); - let serviceName = pascalCase(provideId); - - if (protoModule[serviceName]) { - const protoService = protoModule[serviceName]['service']; - const serviceInstance = {}; - for (const method in protoService) { - serviceInstance[method] = async (...args) => { - const ctx = {} as any; - ctx.requestContext = new MidwayRequestContainer(ctx, this.getApplicationContext()); - ctx.logger = new MidwayGRPCContextLogger(ctx, this.appLogger); - - const service = await ctx.requestContext.getAsync(gRPCModules); - return service[camelCase(method)]?.apply(this, args); - }; - } - this.server.addService(protoService, serviceInstance); - } else { - this.logger.warn(`Proto ${serviceName} not found and not add to gRPC server`); + const definitions = await loadProto(this.configurationOptions); + const protoModule = definitions[this.configurationOptions.package]; + + for (const module of gRPCModules) { + const provideId = getProviderId(module); + let serviceName = pascalCase(provideId); + + if (protoModule[serviceName]) { + const protoService = protoModule[serviceName]['service']; + const serviceInstance = {}; + for (const method in protoService) { + serviceInstance[method] = async (...args) => { + const ctx = {} as any; + ctx.requestContext = new MidwayRequestContainer(ctx, this.getApplicationContext()); + ctx.logger = new MidwayGRPCContextLogger(ctx, this.appLogger); + + const service = await ctx.requestContext.getAsync(gRPCModules); + return service[camelCase(method)]?.apply(this, args); + }; } + this.server.addService(protoService, serviceInstance); + } else { + this.logger.warn(`Proto ${serviceName} not found and not add to gRPC server`); } } } diff --git a/packages/grpc/src/util.ts b/packages/grpc/src/util.ts new file mode 100644 index 000000000000..f74ac1e2d443 --- /dev/null +++ b/packages/grpc/src/util.ts @@ -0,0 +1,12 @@ +import * as protoLoader from '@grpc/proto-loader'; +import { IMidwayGRPFrameworkOptions } from './interface'; + +export const loadProto = async (options: IMidwayGRPFrameworkOptions) => { + return protoLoader.load(options.protoPath, Object.assign({ + keepCase: true, + longs: String, + enums: String, + defaults: true, + oneofs: true + }, options.loaderOptions)); +} diff --git a/packages/grpc/test/fixtures/base-app/src/config/config.default.ts b/packages/grpc/test/fixtures/base-app/src/config/config.default.ts index 85ce1e5c24ea..036417b99866 100644 --- a/packages/grpc/test/fixtures/base-app/src/config/config.default.ts +++ b/packages/grpc/test/fixtures/base-app/src/config/config.default.ts @@ -1,11 +1,12 @@ import { IMidwayGRPCConfigOptions } from '../../../../../src'; +import { join } from 'path'; export const grpc = { clients: [ { host: 'localhost', port: 50051, - protoPath: '' + protoPath: join(__dirname, '../proto/helloworld.proto') } ] } as IMidwayGRPCConfigOptions; diff --git a/packages/grpc/test/fixtures/base-app/src/consumer/greeter.service.ts b/packages/grpc/test/fixtures/base-app/src/consumer/greeter.service.ts deleted file mode 100644 index de6e9c0bc090..000000000000 --- a/packages/grpc/test/fixtures/base-app/src/consumer/greeter.service.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { Config, Init, Inject, Provide, Scope, ScopeEnum } from '@midwayjs/decorator'; -import { helloworld } from '../interface'; -import { credentials } from '@grpc/grpc-js'; -import { IMidwayGRPCConfigOptions } from '../../../../../src'; - -@Provide() -@Scope(ScopeEnum.Singleton) -export class GreeterService implements helloworld.Greeter { - - client; - - @Inject('grpc:definitions:helloworld') - grpcDefinition; - - @Config('grpc') - grpcConfig: IMidwayGRPCConfigOptions; - - @Init() - async initService() { - const helloworld_proto = this.grpcDefinition['helloworld']; - this.client = new helloworld_proto.Greeter('localhost:50051', credentials.createInsecure()); - } - - async sayHello(request: helloworld.HelloRequest): Promise { - return new Promise((resolve, reject) => { - this.client.sayHello(request, (err, response) => { - if (err) { - reject(err); - } - resolve(response); - }); - }); - } -} diff --git a/packages/grpc/test/fixtures/base-app/src/provider/hero.ts b/packages/grpc/test/fixtures/base-app/src/provider/hero.ts index 74c3e1752a41..2eac12bd7875 100644 --- a/packages/grpc/test/fixtures/base-app/src/provider/hero.ts +++ b/packages/grpc/test/fixtures/base-app/src/provider/hero.ts @@ -1,13 +1,20 @@ -import { GrpcMethod, MSProviderType, Provider, Provide, Inject } from '@midwayjs/decorator'; -import { hero } from '../interface'; -import { GreeterService } from '../consumer/greeter.service'; +import { GrpcMethod, MSProviderType, Provider, Provide, Inject, Init } from '@midwayjs/decorator'; +import { helloworld, hero } from '../interface'; +import { Clients } from '../../../../../src'; @Provide() @Provider(MSProviderType.GRPC) export class HeroService implements hero.HeroService { - @Inject() - greeterService: GreeterService; + @Inject('grpc:clients') + grpcClients: Clients; + + greeterService: helloworld.Greeter; + + @Init() + async init() { + this.greeterService = this.grpcClients.getService('Greeter'); + } @GrpcMethod() async findOne(data, metadata) { diff --git a/packages/grpc/test/utils.ts b/packages/grpc/test/utils.ts index 928ecb652ded..56438e58bd75 100644 --- a/packages/grpc/test/utils.ts +++ b/packages/grpc/test/utils.ts @@ -1,22 +1,13 @@ -import { Framework, IMidwayGRPCApplication, IMidwayGRPConfigurationOptions } from '../src'; +import { Framework, IMidwayGRPCApplication, IMidwayGRPFrameworkOptions } from '../src'; import { join } from 'path'; import { close, createApp } from '@midwayjs/mock'; -import * as protoLoader from '@grpc/proto-loader'; - /** * create a gRPC server * @param name * @param options */ -export async function createServer(name: string, options: IMidwayGRPConfigurationOptions = {}): Promise { - options.packageDefinition = protoLoader.loadSync(options.protoPath, { - keepCase: true, - longs: String, - enums: String, - defaults: true, - oneofs: true - }); +export async function createServer(name: string, options: IMidwayGRPFrameworkOptions = {}): Promise { return createApp(join(__dirname, 'fixtures', name), options, Framework); } From f01030fae062c64e6cd51118421233cdc4323b95 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Thu, 14 Jan 2021 10:48:24 +0800 Subject: [PATCH 10/22] chore: upper case --- .../decorator/src/common/decoratorManager.ts | 76 +++++++++---------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/packages/decorator/src/common/decoratorManager.ts b/packages/decorator/src/common/decoratorManager.ts index 2afab6c413dd..bbe5957ebb5a 100644 --- a/packages/decorator/src/common/decoratorManager.ts +++ b/packages/decorator/src/common/decoratorManager.ts @@ -27,7 +27,7 @@ import { getParamNames, classNamed, isNullOrUndefined } from '../util'; const debug = require('util').debuglog('decorator:manager'); -export type decoratorKey = string | symbol; +export type DecoratorKey = string | symbol; export const PRELOAD_MODULE_KEY = 'INJECTION_PRELOAD_MODULE_KEY'; @@ -57,21 +57,21 @@ export class DecoratorManager extends Map { this.set(key, new Set()); } - static getDecoratorClassKey(decoratorNameKey: decoratorKey) { + static getDecoratorClassKey(decoratorNameKey: DecoratorKey) { return decoratorNameKey.toString() + '_CLS'; } - static getDecoratorMethodKey(decoratorNameKey: decoratorKey) { + static getDecoratorMethodKey(decoratorNameKey: DecoratorKey) { return decoratorNameKey.toString() + '_METHOD'; } - static getDecoratorClsMethodPrefix(decoratorNameKey: decoratorKey) { + static getDecoratorClsMethodPrefix(decoratorNameKey: DecoratorKey) { return decoratorNameKey.toString() + '_CLS_METHOD'; } static getDecoratorClsMethodKey( - decoratorNameKey: decoratorKey, - methodKey: decoratorKey + decoratorNameKey: DecoratorKey, + methodKey: DecoratorKey ) { return ( DecoratorManager.getDecoratorClsMethodPrefix(decoratorNameKey) + @@ -81,8 +81,8 @@ export class DecoratorManager extends Map { } static getDecoratorMethod( - decoratorNameKey: decoratorKey, - methodKey: decoratorKey + decoratorNameKey: DecoratorKey, + methodKey: DecoratorKey ) { return ( DecoratorManager.getDecoratorMethodKey(decoratorNameKey) + @@ -195,7 +195,7 @@ export class DecoratorManager extends Map { * @param target target class * @param propertyName */ - saveMetadata(decoratorNameKey: decoratorKey, data, target, propertyName?) { + saveMetadata(decoratorNameKey: DecoratorKey, data, target, propertyName?) { if (propertyName) { const dataKey = DecoratorManager.getDecoratorMethod( decoratorNameKey, @@ -226,7 +226,7 @@ export class DecoratorManager extends Map { * @param propertyName */ attachMetadata( - decoratorNameKey: decoratorKey, + decoratorNameKey: DecoratorKey, data, target, propertyName?: string, @@ -262,7 +262,7 @@ export class DecoratorManager extends Map { * @param target * @param propertyName */ - getMetadata(decoratorNameKey: decoratorKey, target, propertyName?) { + getMetadata(decoratorNameKey: DecoratorKey, target, propertyName?) { if (propertyName) { const dataKey = DecoratorManager.getDecoratorMethod( decoratorNameKey, @@ -293,7 +293,7 @@ export class DecoratorManager extends Map { * @param propertyName */ savePropertyDataToClass( - decoratorNameKey: decoratorKey, + decoratorNameKey: DecoratorKey, data, target, propertyName @@ -319,7 +319,7 @@ export class DecoratorManager extends Map { * @param groupBy */ attachPropertyDataToClass( - decoratorNameKey: decoratorKey, + decoratorNameKey: DecoratorKey, data, target, propertyName, @@ -345,7 +345,7 @@ export class DecoratorManager extends Map { * @param propertyName */ getPropertyDataFromClass( - decoratorNameKey: decoratorKey, + decoratorNameKey: DecoratorKey, target, propertyName ) { @@ -365,7 +365,7 @@ export class DecoratorManager extends Map { * @param decoratorNameKey * @param target */ - listPropertyDataFromClass(decoratorNameKey: decoratorKey, target) { + listPropertyDataFromClass(decoratorNameKey: DecoratorKey, target) { const originMap = DecoratorManager.getMetadata( this.injectClassMethodKeyPrefix, target @@ -393,7 +393,7 @@ const manager = new DecoratorManager(); * @param target */ export function saveClassMetadata( - decoratorNameKey: decoratorKey, + decoratorNameKey: DecoratorKey, data, target ) { @@ -408,7 +408,7 @@ export function saveClassMetadata( * @param groupBy */ export function attachClassMetadata( - decoratorNameKey: decoratorKey, + decoratorNameKey: DecoratorKey, data: any, target, groupBy?: string @@ -422,14 +422,14 @@ export function attachClassMetadata( ); } -const testKeyMap = new Map(); +const testKeyMap = new Map(); /** * get data from class * @param decoratorNameKey * @param target */ -export function getClassMetadata(decoratorNameKey: decoratorKey, target) { +export function getClassMetadata(decoratorNameKey: DecoratorKey, target) { if (testKeyMap.size > 0 && testKeyMap.has(decoratorNameKey)) { throw testKeyMap.get(decoratorNameKey); } @@ -437,7 +437,7 @@ export function getClassMetadata(decoratorNameKey: decoratorKey, target) { } // TODO 因 https://github.com/microsoft/TypeScript/issues/38820 等 4.0 发布移除掉 -export function throwErrorForTest(key: decoratorKey, e: Error) { +export function throwErrorForTest(key: DecoratorKey, e: Error) { if (e) { testKeyMap.set(key, e); } else { @@ -455,7 +455,7 @@ export function throwErrorForTest(key: decoratorKey, e: Error) { * @param method */ export function saveMethodDataToClass( - decoratorNameKey: decoratorKey, + decoratorNameKey: DecoratorKey, data, target, method @@ -478,7 +478,7 @@ export function saveMethodDataToClass( * @param method */ export function attachMethodDataToClass( - decoratorNameKey: decoratorKey, + decoratorNameKey: DecoratorKey, data, target, method @@ -500,7 +500,7 @@ export function attachMethodDataToClass( * @param method */ export function getMethodDataFromClass( - decoratorNameKey: decoratorKey, + decoratorNameKey: DecoratorKey, target, method ) { @@ -514,7 +514,7 @@ export function getMethodDataFromClass( * @param target */ export function listMethodDataFromClass( - decoratorNameKey: decoratorKey, + decoratorNameKey: DecoratorKey, target ) { return manager.listPropertyDataFromClass(decoratorNameKey, target); @@ -529,7 +529,7 @@ export function listMethodDataFromClass( * @param method */ export function saveMethodMetadata( - decoratorNameKey: decoratorKey, + decoratorNameKey: DecoratorKey, data, target, method @@ -546,7 +546,7 @@ export function saveMethodMetadata( * @param method */ export function attachMethodMetadata( - decoratorNameKey: decoratorKey, + decoratorNameKey: DecoratorKey, data, target, method @@ -562,7 +562,7 @@ export function attachMethodMetadata( * @param method */ export function getMethodMetadata( - decoratorNameKey: decoratorKey, + decoratorNameKey: DecoratorKey, target, method ) { @@ -577,7 +577,7 @@ export function getMethodMetadata( * @param propertyName */ export function savePropertyDataToClass( - decoratorNameKey: decoratorKey, + decoratorNameKey: DecoratorKey, data, target, propertyName @@ -598,7 +598,7 @@ export function savePropertyDataToClass( * @param propertyName */ export function attachPropertyDataToClass( - decoratorNameKey: decoratorKey, + decoratorNameKey: DecoratorKey, data, target, propertyName @@ -618,7 +618,7 @@ export function attachPropertyDataToClass( * @param propertyName */ export function getPropertyDataFromClass( - decoratorNameKey: decoratorKey, + decoratorNameKey: DecoratorKey, target, propertyName ) { @@ -635,7 +635,7 @@ export function getPropertyDataFromClass( * @param target */ export function listPropertyDataFromClass( - decoratorNameKey: decoratorKey, + decoratorNameKey: DecoratorKey, target ) { return manager.listPropertyDataFromClass(decoratorNameKey, target); @@ -649,7 +649,7 @@ export function listPropertyDataFromClass( * @param propertyName */ export function savePropertyMetadata( - decoratorNameKey: decoratorKey, + decoratorNameKey: DecoratorKey, data, target, propertyName @@ -665,7 +665,7 @@ export function savePropertyMetadata( * @param propertyName */ export function attachPropertyMetadata( - decoratorNameKey: decoratorKey, + decoratorNameKey: DecoratorKey, data, target, propertyName @@ -680,7 +680,7 @@ export function attachPropertyMetadata( * @param propertyName */ export function getPropertyMetadata( - decoratorNameKey: decoratorKey, + decoratorNameKey: DecoratorKey, target, propertyName ) { @@ -699,7 +699,7 @@ export function savePreloadModule(target) { * list preload module */ export function listPreloadModule(): any[] { - return manager.listModule(PRELOAD_MODULE_KEY); + return listModule(PRELOAD_MODULE_KEY); } /** @@ -707,7 +707,7 @@ export function listPreloadModule(): any[] { * @param decoratorNameKey * @param target */ -export function saveModule(decoratorNameKey: decoratorKey, target) { +export function saveModule(decoratorNameKey: DecoratorKey, target) { return manager.saveModule(decoratorNameKey, target); } @@ -715,7 +715,7 @@ export function saveModule(decoratorNameKey: decoratorKey, target) { * list module from decorator key * @param decoratorNameKey */ -export function listModule(decoratorNameKey: decoratorKey, filter?:(module) => boolean): any[] { +export function listModule(decoratorNameKey: DecoratorKey, filter?:(module) => boolean): any[] { const modules = manager.listModule(decoratorNameKey); if (filter) { return modules.filter(filter); @@ -728,7 +728,7 @@ export function listModule(decoratorNameKey: decoratorKey, filter?:(module) => b * reset module * @param decoratorNameKey */ -export function resetModule(decoratorNameKey: decoratorKey): void { +export function resetModule(decoratorNameKey: DecoratorKey): void { return manager.resetModule(decoratorNameKey); } From 2567bb9a6c830b3ed6fad1f13649fe93c8a316bd Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Fri, 15 Jan 2021 01:30:15 +0800 Subject: [PATCH 11/22] fix: load definition --- .../core/test/context/midwayContainer.test.ts | 10 ++++++++++ .../fixtures/base-app-autoload/package.json | 3 +++ .../fixtures/base-app-autoload/src/home.ts | 17 +++++++++++++++++ .../decorator/src/microservice/provider.ts | 6 +++--- .../decorator/test/annotation/autoload.test.ts | 18 ++++++++++++++++++ packages/grpc/src/comsumer/clients.ts | 17 +++++++++-------- packages/grpc/src/comsumer/configuration.ts | 3 ++- packages/grpc/src/provider/framework.ts | 12 +++++------- packages/grpc/src/util.ts | 2 +- .../base-app/src/config/config.default.ts | 3 ++- .../fixtures/base-app/src/configuration.ts | 4 ++++ 11 files changed, 74 insertions(+), 21 deletions(-) create mode 100644 packages/core/test/fixtures/base-app-autoload/package.json create mode 100644 packages/core/test/fixtures/base-app-autoload/src/home.ts create mode 100644 packages/decorator/test/annotation/autoload.test.ts diff --git a/packages/core/test/context/midwayContainer.test.ts b/packages/core/test/context/midwayContainer.test.ts index f221e5d45e8e..55a711308bfd 100644 --- a/packages/core/test/context/midwayContainer.test.ts +++ b/packages/core/test/context/midwayContainer.test.ts @@ -208,4 +208,14 @@ describe('/test/context/midwayContainer.test.ts', () => { expect(sapp.getConfig().a).to.equal(3); }); + it('should test autoload', async () => { + const container = new MidwayContainer(); + container.load({ + loadDir: path.join(__dirname, '../fixtures/base-app-autoload/src'), + }); + + await container.ready(); + assert((container.registry as unknown as Map).has('userService')); + }); + }); diff --git a/packages/core/test/fixtures/base-app-autoload/package.json b/packages/core/test/fixtures/base-app-autoload/package.json new file mode 100644 index 000000000000..b7dd10831ca4 --- /dev/null +++ b/packages/core/test/fixtures/base-app-autoload/package.json @@ -0,0 +1,3 @@ +{ + "name": "ali-demo-aspect" +} diff --git a/packages/core/test/fixtures/base-app-autoload/src/home.ts b/packages/core/test/fixtures/base-app-autoload/src/home.ts new file mode 100644 index 000000000000..13881aa7e7d3 --- /dev/null +++ b/packages/core/test/fixtures/base-app-autoload/src/home.ts @@ -0,0 +1,17 @@ +import { Autoload, Init, Provide, Scope, ScopeEnum } from '@midwayjs/decorator'; + +@Autoload() +@Provide() +@Scope(ScopeEnum.Singleton) +export class UserService { + + idx = 0; + + @Init() + async initService() { + this.idx++; + } + + async getUser() { + } +} diff --git a/packages/decorator/src/microservice/provider.ts b/packages/decorator/src/microservice/provider.ts index 5c90284edf65..f6e702887dfd 100644 --- a/packages/decorator/src/microservice/provider.ts +++ b/packages/decorator/src/microservice/provider.ts @@ -2,7 +2,7 @@ import { ScopeEnum, saveClassMetadata, saveModule, - MS_PRODUCER_KEY, + MS_PROVIDER_KEY, attachClassMetadata, MS_GRPC_METHOD_KEY, MS_DUBBO_METHOD_KEY, @@ -18,8 +18,8 @@ export enum MSProviderType { export function Provider(type: MSProviderType): ClassDecorator { return (target: any) => { - saveModule(MS_PRODUCER_KEY, target); - saveClassMetadata(MS_PRODUCER_KEY, type, target); + saveModule(MS_PROVIDER_KEY, target); + saveClassMetadata(MS_PROVIDER_KEY, type, target); Scope(ScopeEnum.Request)(target); }; } diff --git a/packages/decorator/test/annotation/autoload.test.ts b/packages/decorator/test/annotation/autoload.test.ts new file mode 100644 index 000000000000..bac9275fc4fb --- /dev/null +++ b/packages/decorator/test/annotation/autoload.test.ts @@ -0,0 +1,18 @@ +import { listPreloadModule, Autoload } from '../../src'; + +describe('/test/annotation/autoload.test.ts', () => { + it('test preload key in module', () => { + + @Autoload() + class LoadA { + } + @Autoload() + class LoadB { + } + + const modules = listPreloadModule(); + expect(modules.length).toEqual(2); + expect(modules[0]).toEqual(LoadA); + expect(modules[1]).toEqual(LoadB); + }); +}); diff --git a/packages/grpc/src/comsumer/clients.ts b/packages/grpc/src/comsumer/clients.ts index 368d2f888635..550dc290f980 100644 --- a/packages/grpc/src/comsumer/clients.ts +++ b/packages/grpc/src/comsumer/clients.ts @@ -1,10 +1,9 @@ -import { Config, Init, Provide, Scope, ScopeEnum, Autoload } from '@midwayjs/decorator'; -import { credentials } from '@grpc/grpc-js'; +import { Config, Init, Provide, Scope, ScopeEnum } from '@midwayjs/decorator'; +import { credentials, loadPackageDefinition } from '@grpc/grpc-js'; import { IMidwayGRPCConfigOptions } from '../interface'; import { loadProto } from '../util'; @Provide('clients') -@Autoload() @Scope(ScopeEnum.Singleton) export class GRPCClients extends Map { @@ -15,11 +14,13 @@ export class GRPCClients extends Map { async initService() { for(const cfg of this.grpcConfig['clients']) { const packageDefinition = await loadProto(cfg); - const packageProtos = packageDefinition[cfg.package]; - for(const serviceName in packageProtos) { - const ProtoService = packageProtos[serviceName]['service']; - const connectionService = new ProtoService(cfg.host + ':' + cfg.port, credentials.createInsecure()); - this.set(serviceName, connectionService) + const packageProto: any = loadPackageDefinition(packageDefinition)[cfg.package]; + for (const definition in packageDefinition) { + if (!packageDefinition[definition]['format']) { + const serviceName = definition.replace(`${cfg.package}.`, ''); + const connectionService = new packageProto[serviceName](cfg.host + ':' + cfg.port, credentials.createInsecure()); + this.set(serviceName, connectionService) + } } } } diff --git a/packages/grpc/src/comsumer/configuration.ts b/packages/grpc/src/comsumer/configuration.ts index 3e6b56b60ce0..48da3970e14d 100644 --- a/packages/grpc/src/comsumer/configuration.ts +++ b/packages/grpc/src/comsumer/configuration.ts @@ -10,7 +10,8 @@ export class AutoConfiguration { @Logger('coreLogger') logger: ILogger; - async onReady() { + async onReady(container) { setLogger(this.logger); + await container.getAsync('grpc:clients'); } } diff --git a/packages/grpc/src/provider/framework.ts b/packages/grpc/src/provider/framework.ts index c9483e4b38f1..44236156e9a0 100644 --- a/packages/grpc/src/provider/framework.ts +++ b/packages/grpc/src/provider/framework.ts @@ -60,16 +60,15 @@ export class MidwayGRPCFramework extends BaseFramework< }); const definitions = await loadProto(this.configurationOptions); - const protoModule = definitions[this.configurationOptions.package]; for (const module of gRPCModules) { const provideId = getProviderId(module); let serviceName = pascalCase(provideId); + const serviceDefinition: any = definitions[`${this.configurationOptions.package}.${serviceName}`]; - if (protoModule[serviceName]) { - const protoService = protoModule[serviceName]['service']; + if (serviceDefinition) { const serviceInstance = {}; - for (const method in protoService) { + for (const method in serviceDefinition) { serviceInstance[method] = async (...args) => { const ctx = {} as any; ctx.requestContext = new MidwayRequestContainer(ctx, this.getApplicationContext()); @@ -79,9 +78,8 @@ export class MidwayGRPCFramework extends BaseFramework< return service[camelCase(method)]?.apply(this, args); }; } - this.server.addService(protoService, serviceInstance); - } else { - this.logger.warn(`Proto ${serviceName} not found and not add to gRPC server`); + this.server.addService(serviceDefinition, serviceInstance); + this.logger.info(`Proto ${this.configurationOptions.package}.${serviceName} found and add to gRPC server`); } } } diff --git a/packages/grpc/src/util.ts b/packages/grpc/src/util.ts index f74ac1e2d443..422f9ab47477 100644 --- a/packages/grpc/src/util.ts +++ b/packages/grpc/src/util.ts @@ -2,7 +2,7 @@ import * as protoLoader from '@grpc/proto-loader'; import { IMidwayGRPFrameworkOptions } from './interface'; export const loadProto = async (options: IMidwayGRPFrameworkOptions) => { - return protoLoader.load(options.protoPath, Object.assign({ + return protoLoader.loadSync(options.protoPath, Object.assign({ keepCase: true, longs: String, enums: String, diff --git a/packages/grpc/test/fixtures/base-app/src/config/config.default.ts b/packages/grpc/test/fixtures/base-app/src/config/config.default.ts index 036417b99866..8f365f8e8034 100644 --- a/packages/grpc/test/fixtures/base-app/src/config/config.default.ts +++ b/packages/grpc/test/fixtures/base-app/src/config/config.default.ts @@ -6,7 +6,8 @@ export const grpc = { { host: 'localhost', port: 50051, - protoPath: join(__dirname, '../proto/helloworld.proto') + protoPath: join(__dirname, '../../../proto/helloworld.proto'), + package: 'helloworld' } ] } as IMidwayGRPCConfigOptions; diff --git a/packages/grpc/test/fixtures/base-app/src/configuration.ts b/packages/grpc/test/fixtures/base-app/src/configuration.ts index d84c1d127a80..58fc38ef5e89 100644 --- a/packages/grpc/test/fixtures/base-app/src/configuration.ts +++ b/packages/grpc/test/fixtures/base-app/src/configuration.ts @@ -1,9 +1,13 @@ import { Configuration } from '@midwayjs/decorator'; import * as grpc from '../src/../../../../src'; +import { join } from 'path'; @Configuration({ imports: [ grpc + ], + importConfigs: [ + join(__dirname, './config'), ] }) export class AutoConfiguration { From 823aa8a6b02310abfaead76bf2618473c2190797 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Sat, 16 Jan 2021 16:00:41 +0800 Subject: [PATCH 12/22] chore: server test complete --- packages/grpc/src/provider/framework.ts | 15 ++++++---- .../fixtures/base-app/src/provider/hero.ts | 8 +++--- packages/grpc/test/index.test.ts | 28 +++++++++++++++++-- packages/grpc/test/utils.ts | 25 +++++++++++++++++ 4 files changed, 65 insertions(+), 11 deletions(-) diff --git a/packages/grpc/src/provider/framework.ts b/packages/grpc/src/provider/framework.ts index 44236156e9a0..60e2a27cca21 100644 --- a/packages/grpc/src/provider/framework.ts +++ b/packages/grpc/src/provider/framework.ts @@ -1,4 +1,4 @@ -import { Server, ServerCredentials, setLogger } from '@grpc/grpc-js'; +import { Server, ServerCredentials, setLogger, ServerUnaryCall, sendUnaryData } from '@grpc/grpc-js'; import { BaseFramework, getClassMetadata, @@ -69,13 +69,18 @@ export class MidwayGRPCFramework extends BaseFramework< if (serviceDefinition) { const serviceInstance = {}; for (const method in serviceDefinition) { - serviceInstance[method] = async (...args) => { - const ctx = {} as any; + serviceInstance[method] = async (call: ServerUnaryCall, callback: sendUnaryData) => { + const ctx = { metadata: call.metadata} as any; ctx.requestContext = new MidwayRequestContainer(ctx, this.getApplicationContext()); ctx.logger = new MidwayGRPCContextLogger(ctx, this.appLogger); - const service = await ctx.requestContext.getAsync(gRPCModules); - return service[camelCase(method)]?.apply(this, args); + try { + const service = await ctx.requestContext.getAsync(module); + const result = await service[camelCase(method)]?.apply(this, [call.request]); + callback(null, result); + } catch (err) { + callback(err); + } }; } this.server.addService(serviceDefinition, serviceInstance); diff --git a/packages/grpc/test/fixtures/base-app/src/provider/hero.ts b/packages/grpc/test/fixtures/base-app/src/provider/hero.ts index 2eac12bd7875..e3c68b10d733 100644 --- a/packages/grpc/test/fixtures/base-app/src/provider/hero.ts +++ b/packages/grpc/test/fixtures/base-app/src/provider/hero.ts @@ -18,12 +18,12 @@ export class HeroService implements hero.HeroService { @GrpcMethod() async findOne(data, metadata) { - const result = await this.greeterService.sayHello({ - name: 'harry' - }); + // const result = await this.greeterService.sayHello({ + // name: 'harry' + // }); return { id: 1, - name: result.message, + name: 'bbbb', }; } } diff --git a/packages/grpc/test/index.test.ts b/packages/grpc/test/index.test.ts index 3de6cf8df0cb..45ce7833d8ce 100644 --- a/packages/grpc/test/index.test.ts +++ b/packages/grpc/test/index.test.ts @@ -1,13 +1,37 @@ -import { createServer, closeApp } from './utils'; +import { createServer, closeApp, createGRPCConsumer } from './utils'; import { join } from 'path'; +// import { hero } from './fixtures/base-app/src/interface'; describe('/test/index.test.ts', function () { it('should create grpc server', async () => { const app = await createServer('base-app', { protoPath: join(__dirname, 'fixtures/proto/hero.proto'), - package: 'hero' + package: 'hero', + port: 6565 }); + + const service: any = await createGRPCConsumer({ + package: 'hero', + protoPath: join(__dirname, 'fixtures/proto/hero.proto'), + host: '127.0.0.1', + port: 6565 + }); + + const result = await new Promise((resolve, reject) => { + service.findOne({ + id: 123 + },(err, response) => { + if (err) { + reject(err); + } + console.log('Greeting:', response.message); + resolve(response); + }); + }) + + console.log(result); + expect(app.getAppDir()).toBeTruthy(); expect(app.getApplicationContext()).toBeTruthy(); await closeApp(app); diff --git a/packages/grpc/test/utils.ts b/packages/grpc/test/utils.ts index 56438e58bd75..c2604b44a588 100644 --- a/packages/grpc/test/utils.ts +++ b/packages/grpc/test/utils.ts @@ -1,6 +1,8 @@ import { Framework, IMidwayGRPCApplication, IMidwayGRPFrameworkOptions } from '../src'; import { join } from 'path'; import { close, createApp } from '@midwayjs/mock'; +import { loadProto } from '../src/util'; +import { credentials, loadPackageDefinition } from '@grpc/grpc-js'; /** * create a gRPC server @@ -14,3 +16,26 @@ export async function createServer(name: string, options: IMidwayGRPFrameworkOpt export async function closeApp(app) { return close(app); } + +export const createGRPCConsumer = async (options: IMidwayGRPFrameworkOptions): Promise => { + const packageDefinition = await loadProto(options); + const packageProto: any = loadPackageDefinition(packageDefinition)[options.package]; + for (const definition in packageDefinition) { + if (!packageDefinition[definition]['format']) { + const serviceName = definition.replace(`${options.package}.`, ''); + const connectionService = new packageProto[serviceName](options.host + ':' + options.port, credentials.createInsecure()); + return connectionService; + // return async (...args) => { + // return new Promise((resolve, reject) => { + // connectionService(args[0], (err, response) => { + // if (err) { + // reject(err); + // } + // console.log('Greeting:', response.message); + // resolve(response); + // }); + // }); + // }; + } + } +} From e60733f9b16de5f952decd1eba4646cb857549fb Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Sun, 17 Jan 2021 17:12:36 +0800 Subject: [PATCH 13/22] feat: support publish multiple gRPC service --- .../decorator/src/common/decoratorManager.ts | 2 +- packages/decorator/src/common/metadata.ts | 2 +- .../decorator/src/{common => }/constant.ts | 0 packages/decorator/src/index.ts | 2 +- packages/decorator/src/interface.ts | 22 +++++ .../decorator/src/microservice/provider.ts | 16 ++-- packages/grpc/src/comsumer/clients.ts | 47 ++++++---- packages/grpc/src/comsumer/config.default.ts | 1 + packages/grpc/src/comsumer/configuration.ts | 8 +- packages/grpc/src/index.ts | 1 + packages/grpc/src/interface.ts | 20 +++-- packages/grpc/src/provider/framework.ts | 35 ++++++-- packages/grpc/src/util.ts | 21 ++++- .../base-app-multiple-service/package.json | 3 + .../src/config/config.default.ts | 5 +- .../src/configuration.ts | 14 +++ .../src/interface.ts | 28 ++++++ .../src/provider/greeter.ts | 19 ++++ .../src/provider/hero.ts | 14 +-- .../fixtures/base-app/src/configuration.ts | 9 +- .../fixtures/base-app/src/provider/greeter.ts | 17 ++-- packages/grpc/test/index.test.ts | 90 ++++++++++++++----- packages/grpc/test/utils.ts | 27 +----- 23 files changed, 278 insertions(+), 125 deletions(-) rename packages/decorator/src/{common => }/constant.ts (100%) create mode 100644 packages/grpc/src/comsumer/config.default.ts create mode 100644 packages/grpc/test/fixtures/base-app-multiple-service/package.json rename packages/grpc/test/fixtures/{base-app => base-app-multiple-service}/src/config/config.default.ts (81%) create mode 100644 packages/grpc/test/fixtures/base-app-multiple-service/src/configuration.ts create mode 100644 packages/grpc/test/fixtures/base-app-multiple-service/src/interface.ts create mode 100644 packages/grpc/test/fixtures/base-app-multiple-service/src/provider/greeter.ts rename packages/grpc/test/fixtures/{base-app => base-app-multiple-service}/src/provider/hero.ts (68%) diff --git a/packages/decorator/src/common/decoratorManager.ts b/packages/decorator/src/common/decoratorManager.ts index bbe5957ebb5a..f364979cc1c6 100644 --- a/packages/decorator/src/common/decoratorManager.ts +++ b/packages/decorator/src/common/decoratorManager.ts @@ -15,7 +15,7 @@ import { TAGGED, TAGGED_CLS, TAGGED_PROP, -} from './constant'; +} from '../constant'; import { DUPLICATED_INJECTABLE_DECORATOR, diff --git a/packages/decorator/src/common/metadata.ts b/packages/decorator/src/common/metadata.ts index b29c25e414fa..069f4cf29cc1 100644 --- a/packages/decorator/src/common/metadata.ts +++ b/packages/decorator/src/common/metadata.ts @@ -1,4 +1,4 @@ -import { NAMED_TAG } from './constant'; +import { NAMED_TAG } from '../constant'; import { TagPropsMetadata } from '../interface'; export class Metadata implements TagPropsMetadata { diff --git a/packages/decorator/src/common/constant.ts b/packages/decorator/src/constant.ts similarity index 100% rename from packages/decorator/src/common/constant.ts rename to packages/decorator/src/constant.ts diff --git a/packages/decorator/src/index.ts b/packages/decorator/src/index.ts index c7a94135fabe..28bf306b0032 100644 --- a/packages/decorator/src/index.ts +++ b/packages/decorator/src/index.ts @@ -1,6 +1,6 @@ export * from './interface'; export * from './annotation'; -export * from './common/constant'; +export * from './constant'; export * from './common/decoratorManager'; export * from './common/errMsg'; export * from './common/metadata'; diff --git a/packages/decorator/src/interface.ts b/packages/decorator/src/interface.ts index 4184d9038d39..7d10558a32d3 100644 --- a/packages/decorator/src/interface.ts +++ b/packages/decorator/src/interface.ts @@ -40,3 +40,25 @@ export interface TagClsMetadata { export interface ReflectResult { [key: string]: TagPropsMetadata[]; } + +export enum MSProviderType { + DUBBO = 'dubbo', + GRPC = 'gRPC', + HSF = 'hsf', +} + +/** + * all decorator metadata format + */ +export namespace DecoratorMetadata { + + export interface GRPCClassMetadata { + serviceName?: string; + package?: string; + } + + export interface ProviderClassMetadata { + type: MSProviderType, + metadata: GRPCClassMetadata + } +} diff --git a/packages/decorator/src/microservice/provider.ts b/packages/decorator/src/microservice/provider.ts index f6e702887dfd..2d115785cdbe 100644 --- a/packages/decorator/src/microservice/provider.ts +++ b/packages/decorator/src/microservice/provider.ts @@ -7,19 +7,19 @@ import { MS_GRPC_METHOD_KEY, MS_DUBBO_METHOD_KEY, MS_HSF_METHOD_KEY, + MSProviderType, + DecoratorMetadata, } from '../'; import { Scope } from '../annotation'; -export enum MSProviderType { - DUBBO = 'dubbo', - GRPC = 'gRPC', - HSF = 'hsf', -} - -export function Provider(type: MSProviderType): ClassDecorator { +export function Provider(type: MSProviderType.GRPC, metadata?: DecoratorMetadata.GRPCClassMetadata): ClassDecorator; +export function Provider(type: MSProviderType, metadata: any = {}): ClassDecorator { return (target: any) => { saveModule(MS_PROVIDER_KEY, target); - saveClassMetadata(MS_PROVIDER_KEY, type, target); + saveClassMetadata(MS_PROVIDER_KEY, { + type, + metadata, + }, target); Scope(ScopeEnum.Request)(target); }; } diff --git a/packages/grpc/src/comsumer/clients.ts b/packages/grpc/src/comsumer/clients.ts index 550dc290f980..1d76674604f0 100644 --- a/packages/grpc/src/comsumer/clients.ts +++ b/packages/grpc/src/comsumer/clients.ts @@ -1,7 +1,9 @@ -import { Config, Init, Provide, Scope, ScopeEnum } from '@midwayjs/decorator'; +import { Config, Init, Logger, Provide, Scope, ScopeEnum } from '@midwayjs/decorator'; import { credentials, loadPackageDefinition } from '@grpc/grpc-js'; import { IMidwayGRPCConfigOptions } from '../interface'; import { loadProto } from '../util'; +import * as camelCase from 'camelcase'; +import { ILogger } from '@midwayjs/logger'; @Provide('clients') @Scope(ScopeEnum.Singleton) @@ -10,16 +12,40 @@ export class GRPCClients extends Map { @Config('grpc') grpcConfig: IMidwayGRPCConfigOptions; + @Logger() + logger: ILogger; + @Init() async initService() { - for(const cfg of this.grpcConfig['clients']) { - const packageDefinition = await loadProto(cfg); + if (!this.grpcConfig['services']) { + this.logger.error('Please set gRPC services in your config["grpc"]'); + return; + } + for(const cfg of this.grpcConfig['services']) { + const packageDefinition = await loadProto({ + loaderOptions: cfg.loaderOptions, + protoPath: cfg.protoPath, + }); const packageProto: any = loadPackageDefinition(packageDefinition)[cfg.package]; for (const definition in packageDefinition) { if (!packageDefinition[definition]['format']) { const serviceName = definition.replace(`${cfg.package}.`, ''); - const connectionService = new packageProto[serviceName](cfg.host + ':' + cfg.port, credentials.createInsecure()); - this.set(serviceName, connectionService) + const connectionService = new packageProto[serviceName](cfg.url, credentials.createInsecure()); + for(const methodName of Object.keys(packageDefinition[definition])) { + const originMethod = connectionService[methodName]; + connectionService[methodName] = async (...args) => { + return new Promise((resolve, reject) => { + originMethod.call(connectionService, args[0], (err, response) => { + if (err) { + reject(err); + } + resolve(response); + }); + }); + }; + connectionService[camelCase(methodName)] = connectionService[methodName]; + } + this.set(definition, connectionService); } } } @@ -28,15 +54,4 @@ export class GRPCClients extends Map { getService(serviceName: string): T { return this.get(serviceName); } - - // async sayHello(request: helloworld.HelloRequest): Promise { - // return new Promise((resolve, reject) => { - // this.client.sayHello(request, (err, response) => { - // if (err) { - // reject(err); - // } - // resolve(response); - // }); - // }); - // } } diff --git a/packages/grpc/src/comsumer/config.default.ts b/packages/grpc/src/comsumer/config.default.ts new file mode 100644 index 000000000000..e6a1c4b2d6ba --- /dev/null +++ b/packages/grpc/src/comsumer/config.default.ts @@ -0,0 +1 @@ +export const grpc = {}; diff --git a/packages/grpc/src/comsumer/configuration.ts b/packages/grpc/src/comsumer/configuration.ts index 48da3970e14d..9710eaa204ff 100644 --- a/packages/grpc/src/comsumer/configuration.ts +++ b/packages/grpc/src/comsumer/configuration.ts @@ -1,13 +1,17 @@ import { Configuration, Logger } from '@midwayjs/decorator'; import { setLogger } from '@grpc/grpc-js'; import { ILogger } from '@midwayjs/logger'; +import { join } from 'path'; @Configuration({ - namespace: 'grpc' + namespace: 'grpc', + importConfigs: [ + join(__dirname, 'config.default'), + ] }) export class AutoConfiguration { - @Logger('coreLogger') + @Logger() logger: ILogger; async onReady(container) { diff --git a/packages/grpc/src/index.ts b/packages/grpc/src/index.ts index f240c4e1edac..93e22ea83832 100644 --- a/packages/grpc/src/index.ts +++ b/packages/grpc/src/index.ts @@ -2,3 +2,4 @@ export * from './interface'; export { MidwayGRPCFramework as Framework } from './provider/framework'; export { AutoConfiguration as Configuration } from './comsumer/configuration'; export { GRPCClients as Clients } from './comsumer/clients'; +export { loadProto, createGRPCConsumer } from './util'; diff --git a/packages/grpc/src/interface.ts b/packages/grpc/src/interface.ts index 908bad6495fa..2e014ede9e2a 100644 --- a/packages/grpc/src/interface.ts +++ b/packages/grpc/src/interface.ts @@ -6,12 +6,11 @@ export type IMidwayGRPCContext = IMidwayContext & { } export type IMidwayGRPCApplication = IMidwayApplication & Server; -export interface IMidwayGRPFrameworkOptions extends IConfigurationOptions { - host?: string; +export interface IGRPCServiceOptions { /** - * application gRPC port + * application gRPC connection string */ - port?: number; + url?: string; /** * proto path */ @@ -27,6 +26,15 @@ export interface IMidwayGRPFrameworkOptions extends IConfigurationOptions { credentials?: ServerCredentials; } -export interface IMidwayGRPCConfigOptions { - clients: IMidwayGRPFrameworkOptions[]; +export interface IMidwayGRPFrameworkOptions extends IConfigurationOptions { + /** + * gRPC Server connection url, default is localhost:6565 + */ + url?: string; + services: Pick[]; + loaderOptions?: object; +} + +export interface IMidwayGRPCConfigOptions extends IConfigurationOptions { + services: IGRPCServiceOptions[]; } diff --git a/packages/grpc/src/provider/framework.ts b/packages/grpc/src/provider/framework.ts index 60e2a27cca21..7ae6765d64c1 100644 --- a/packages/grpc/src/provider/framework.ts +++ b/packages/grpc/src/provider/framework.ts @@ -9,6 +9,7 @@ import { } from '@midwayjs/core'; import { + DecoratorMetadata, getProviderId, MS_PROVIDER_KEY, MSProviderType @@ -20,6 +21,7 @@ import { MidwayGRPCContextLogger } from './logger'; import { pascalCase } from 'pascal-case'; import * as camelCase from 'camelcase'; import { loadProto } from '../util'; +import { PackageDefinition } from '@grpc/proto-loader'; export class MidwayGRPCFramework extends BaseFramework< IMidwayGRPCApplication, @@ -54,20 +56,35 @@ export class MidwayGRPCFramework extends BaseFramework< } protected async loadService() { + // find all code service const gRPCModules = listModule(MS_PROVIDER_KEY, (module) => { - const type = getClassMetadata(MS_PROVIDER_KEY, module); - return type === MSProviderType.GRPC; + const info: DecoratorMetadata.ProviderClassMetadata = getClassMetadata(MS_PROVIDER_KEY, module); + return info.type === MSProviderType.GRPC; }); - const definitions = await loadProto(this.configurationOptions); + this.logger.info(`Find ${gRPCModules.length} class has gRPC provider decorator`); + // get definition from proto file + const serviceClassDefinition: Map = new Map(); + for (const service of this.configurationOptions.services) { + const definitions = await loadProto({ + protoPath: service.protoPath, + loaderOptions: this.configurationOptions.loaderOptions, + }); + serviceClassDefinition.set(service.package, definitions); + } + + // register method to service for (const module of gRPCModules) { const provideId = getProviderId(module); - let serviceName = pascalCase(provideId); - const serviceDefinition: any = definitions[`${this.configurationOptions.package}.${serviceName}`]; + const info: DecoratorMetadata.ProviderClassMetadata = getClassMetadata(MS_PROVIDER_KEY, module); + const classMetadata = info.metadata as DecoratorMetadata.GRPCClassMetadata; + let serviceName = classMetadata.serviceName || pascalCase(provideId); - if (serviceDefinition) { + if (serviceClassDefinition.has(classMetadata?.package)) { const serviceInstance = {}; + const serviceDefinition: any = serviceClassDefinition.get(classMetadata.package)[`${classMetadata?.package}.${serviceName}`]; + for (const method in serviceDefinition) { serviceInstance[method] = async (call: ServerUnaryCall, callback: sendUnaryData) => { const ctx = { metadata: call.metadata} as any; @@ -76,7 +93,7 @@ export class MidwayGRPCFramework extends BaseFramework< try { const service = await ctx.requestContext.getAsync(module); - const result = await service[camelCase(method)]?.apply(this, [call.request]); + const result = await service[camelCase(method)]?.apply(service, [call.request]); callback(null, result); } catch (err) { callback(err); @@ -84,14 +101,14 @@ export class MidwayGRPCFramework extends BaseFramework< }; } this.server.addService(serviceDefinition, serviceInstance); - this.logger.info(`Proto ${this.configurationOptions.package}.${serviceName} found and add to gRPC server`); + this.logger.info(`Proto ${classMetadata?.package}.${serviceName} found and add to gRPC server`); } } } public async run(): Promise { return new Promise((resolve, reject) => { - this.server.bindAsync(`127.0.0.1:${this.configurationOptions.port || 6565}`, ServerCredentials.createInsecure(), (err: Error | null, bindPort: number) => { + this.server.bindAsync(`${this.configurationOptions.url || 'localhost:6565'}`, ServerCredentials.createInsecure(), (err: Error | null, bindPort: number) => { if (err) { reject(err); } diff --git a/packages/grpc/src/util.ts b/packages/grpc/src/util.ts index 422f9ab47477..58272bb15780 100644 --- a/packages/grpc/src/util.ts +++ b/packages/grpc/src/util.ts @@ -1,12 +1,27 @@ import * as protoLoader from '@grpc/proto-loader'; -import { IMidwayGRPFrameworkOptions } from './interface'; +import { IGRPCServiceOptions } from './interface'; +import { GRPCClients } from './comsumer/clients'; -export const loadProto = async (options: IMidwayGRPFrameworkOptions) => { +export const loadProto = (options: { + protoPath: string; + loaderOptions?: any; +}) => { return protoLoader.loadSync(options.protoPath, Object.assign({ keepCase: true, longs: String, enums: String, defaults: true, oneofs: true - }, options.loaderOptions)); + }, options.loaderOptions || {})); +}; + +export const createGRPCConsumer = async (options: IGRPCServiceOptions): Promise => { + const clients = new GRPCClients(); + options.url = options.url || 'localhost:6565'; + clients.grpcConfig = { + services: [options] + } + + await clients.initService(); + return Array.from(clients.values())[0]; } diff --git a/packages/grpc/test/fixtures/base-app-multiple-service/package.json b/packages/grpc/test/fixtures/base-app-multiple-service/package.json new file mode 100644 index 000000000000..621cdc6a4174 --- /dev/null +++ b/packages/grpc/test/fixtures/base-app-multiple-service/package.json @@ -0,0 +1,3 @@ +{ + "name": "ali-demo" +} diff --git a/packages/grpc/test/fixtures/base-app/src/config/config.default.ts b/packages/grpc/test/fixtures/base-app-multiple-service/src/config/config.default.ts similarity index 81% rename from packages/grpc/test/fixtures/base-app/src/config/config.default.ts rename to packages/grpc/test/fixtures/base-app-multiple-service/src/config/config.default.ts index 8f365f8e8034..2359f87803b5 100644 --- a/packages/grpc/test/fixtures/base-app/src/config/config.default.ts +++ b/packages/grpc/test/fixtures/base-app-multiple-service/src/config/config.default.ts @@ -2,10 +2,9 @@ import { IMidwayGRPCConfigOptions } from '../../../../../src'; import { join } from 'path'; export const grpc = { - clients: [ + services: [ { - host: 'localhost', - port: 50051, + url: 'localhost:6565', protoPath: join(__dirname, '../../../proto/helloworld.proto'), package: 'helloworld' } diff --git a/packages/grpc/test/fixtures/base-app-multiple-service/src/configuration.ts b/packages/grpc/test/fixtures/base-app-multiple-service/src/configuration.ts new file mode 100644 index 000000000000..524fbcb91431 --- /dev/null +++ b/packages/grpc/test/fixtures/base-app-multiple-service/src/configuration.ts @@ -0,0 +1,14 @@ +import { Configuration } from '@midwayjs/decorator'; +import * as grpc from '../../../../src'; +import { join } from 'path'; + +@Configuration({ + imports: [ + grpc + ], + importConfigs: [ + join(__dirname, './config'), + ] +}) +export class AutoConfiguration { +} diff --git a/packages/grpc/test/fixtures/base-app-multiple-service/src/interface.ts b/packages/grpc/test/fixtures/base-app-multiple-service/src/interface.ts new file mode 100644 index 000000000000..12447457d823 --- /dev/null +++ b/packages/grpc/test/fixtures/base-app-multiple-service/src/interface.ts @@ -0,0 +1,28 @@ +import { Metadata } from '@grpc/grpc-js'; + +export namespace hero { + export interface HeroService { + findOne(data: HeroById, metadata?: Metadata): Promise; + } + export interface HeroById { + id?: number; + } + export interface Hero { + id?: number; + name?: string; + } +} + +export namespace helloworld { + export interface Greeter { + sayHello (request: HelloRequest): Promise + } + + export interface HelloRequest { + name: string; + } + + export interface HelloReply { + message: string; + } +} diff --git a/packages/grpc/test/fixtures/base-app-multiple-service/src/provider/greeter.ts b/packages/grpc/test/fixtures/base-app-multiple-service/src/provider/greeter.ts new file mode 100644 index 000000000000..74a9fc15378a --- /dev/null +++ b/packages/grpc/test/fixtures/base-app-multiple-service/src/provider/greeter.ts @@ -0,0 +1,19 @@ +import { MSProviderType, Provider, Provide, GrpcMethod } from '@midwayjs/decorator'; +import { helloworld } from '../interface'; + +/** + * package helloworld + * service Greeter + */ +@Provide() +@Provider(MSProviderType.GRPC, { package: 'helloworld' }) +export class Greeter implements helloworld.Greeter { + + /** + * Implements the SayHello RPC method. + */ + @GrpcMethod() + async sayHello(request: helloworld.HelloRequest) { + return { message: 'Hello ' + request.name } + } +} diff --git a/packages/grpc/test/fixtures/base-app/src/provider/hero.ts b/packages/grpc/test/fixtures/base-app-multiple-service/src/provider/hero.ts similarity index 68% rename from packages/grpc/test/fixtures/base-app/src/provider/hero.ts rename to packages/grpc/test/fixtures/base-app-multiple-service/src/provider/hero.ts index e3c68b10d733..3dd6e26771fe 100644 --- a/packages/grpc/test/fixtures/base-app/src/provider/hero.ts +++ b/packages/grpc/test/fixtures/base-app-multiple-service/src/provider/hero.ts @@ -3,7 +3,7 @@ import { helloworld, hero } from '../interface'; import { Clients } from '../../../../../src'; @Provide() -@Provider(MSProviderType.GRPC) +@Provider(MSProviderType.GRPC, { package: 'hero' }) export class HeroService implements hero.HeroService { @Inject('grpc:clients') @@ -13,17 +13,17 @@ export class HeroService implements hero.HeroService { @Init() async init() { - this.greeterService = this.grpcClients.getService('Greeter'); + this.greeterService = this.grpcClients.getService('helloworld.Greeter'); } @GrpcMethod() - async findOne(data, metadata) { - // const result = await this.greeterService.sayHello({ - // name: 'harry' - // }); + async findOne(data) { + const result = await this.greeterService.sayHello({ + name: 'harry' + }); return { id: 1, - name: 'bbbb', + name: 'bbbb-' + result.message, }; } } diff --git a/packages/grpc/test/fixtures/base-app/src/configuration.ts b/packages/grpc/test/fixtures/base-app/src/configuration.ts index 58fc38ef5e89..023d2b63e20d 100644 --- a/packages/grpc/test/fixtures/base-app/src/configuration.ts +++ b/packages/grpc/test/fixtures/base-app/src/configuration.ts @@ -1,17 +1,10 @@ import { Configuration } from '@midwayjs/decorator'; -import * as grpc from '../src/../../../../src'; -import { join } from 'path'; +import * as grpc from '../../../../src'; @Configuration({ imports: [ grpc ], - importConfigs: [ - join(__dirname, './config'), - ] }) export class AutoConfiguration { - async onReady() { - console.log('on ready and load grpc component'); - } } diff --git a/packages/grpc/test/fixtures/base-app/src/provider/greeter.ts b/packages/grpc/test/fixtures/base-app/src/provider/greeter.ts index 66c69fc88cc4..20d8058bc4c1 100644 --- a/packages/grpc/test/fixtures/base-app/src/provider/greeter.ts +++ b/packages/grpc/test/fixtures/base-app/src/provider/greeter.ts @@ -1,23 +1,18 @@ -// import { -// sendUnaryData, -// ServerUnaryCall, -// } from '@grpc/grpc-js'; - -import { MSProviderType, Provider, Provide, GrpcMethod } from '@midwayjs/decorator'; +import { MSProviderType, Provider, Provide } from '@midwayjs/decorator'; +import { helloworld } from '../interface'; /** * package helloworld * service Greeter */ @Provide() -@Provider(MSProviderType.GRPC) -export class Greeter { +@Provider(MSProviderType.GRPC, { package: 'helloworld' }) +export class Greeter implements helloworld.Greeter { - @GrpcMethod() /** * Implements the SayHello RPC method. */ - public sayHello(call: /*ServerUnaryCall*/ any, callback: /*sendUnaryData*/ any): void { - callback(null, { message: 'Hello ' + call.request.name }); + async sayHello(request: helloworld.HelloRequest) { + return { message: 'Hello ' + request.name } } } diff --git a/packages/grpc/test/index.test.ts b/packages/grpc/test/index.test.ts index 45ce7833d8ce..475816290304 100644 --- a/packages/grpc/test/index.test.ts +++ b/packages/grpc/test/index.test.ts @@ -1,39 +1,83 @@ -import { createServer, closeApp, createGRPCConsumer } from './utils'; +import { createServer, closeApp } from './utils'; import { join } from 'path'; -// import { hero } from './fixtures/base-app/src/interface'; +import { createGRPCConsumer } from '../src'; + +export namespace hero { + export interface HeroService { + findOne(data: HeroById): Promise; + } + export interface HeroById { + id?: number; + } + export interface Hero { + id?: number; + name?: string; + } +} + +export namespace helloworld { + export interface Greeter { + sayHello (request: HelloRequest): Promise + } + + export interface HelloRequest { + name: string; + } + + export interface HelloReply { + message: string; + } +} describe('/test/index.test.ts', function () { - it('should create grpc server', async () => { + it('should create gRPC server', async () => { const app = await createServer('base-app', { - protoPath: join(__dirname, 'fixtures/proto/hero.proto'), - package: 'hero', - port: 6565 + services: [ + { + protoPath: join(__dirname, 'fixtures/proto/helloworld.proto'), + package: 'helloworld', + } + ] + }); + + const service = await createGRPCConsumer({ + package: 'helloworld', + protoPath: join(__dirname, 'fixtures/proto/helloworld.proto'), + }); + + const result = await service.sayHello({ + name: 'harry' + }); + + expect(result).toEqual({ message: 'Hello harry' }) + await closeApp(app); + }); + + it('should create multiple grpc service in one server', async () => { + const app = await createServer('base-app-multiple-service', { + services: [ + { + protoPath: join(__dirname, 'fixtures/proto/hero.proto'), + package: 'hero', + }, + { + protoPath: join(__dirname, 'fixtures/proto/helloworld.proto'), + package: 'helloworld', + } + ] }); const service: any = await createGRPCConsumer({ package: 'hero', protoPath: join(__dirname, 'fixtures/proto/hero.proto'), - host: '127.0.0.1', - port: 6565 }); - const result = await new Promise((resolve, reject) => { - service.findOne({ - id: 123 - },(err, response) => { - if (err) { - reject(err); - } - console.log('Greeting:', response.message); - resolve(response); - }); - }) - - console.log(result); + const result = await service.findOne({ + id: 123 + }); - expect(app.getAppDir()).toBeTruthy(); - expect(app.getApplicationContext()).toBeTruthy(); + expect(result).toEqual({ id: 1, name: 'bbbb-Hello harry' }) await closeApp(app); }); }); diff --git a/packages/grpc/test/utils.ts b/packages/grpc/test/utils.ts index c2604b44a588..191de6b59ca1 100644 --- a/packages/grpc/test/utils.ts +++ b/packages/grpc/test/utils.ts @@ -1,41 +1,16 @@ import { Framework, IMidwayGRPCApplication, IMidwayGRPFrameworkOptions } from '../src'; import { join } from 'path'; import { close, createApp } from '@midwayjs/mock'; -import { loadProto } from '../src/util'; -import { credentials, loadPackageDefinition } from '@grpc/grpc-js'; /** * create a gRPC server * @param name * @param options */ -export async function createServer(name: string, options: IMidwayGRPFrameworkOptions = {}): Promise { +export async function createServer(name: string, options: IMidwayGRPFrameworkOptions): Promise { return createApp(join(__dirname, 'fixtures', name), options, Framework); } export async function closeApp(app) { return close(app); } - -export const createGRPCConsumer = async (options: IMidwayGRPFrameworkOptions): Promise => { - const packageDefinition = await loadProto(options); - const packageProto: any = loadPackageDefinition(packageDefinition)[options.package]; - for (const definition in packageDefinition) { - if (!packageDefinition[definition]['format']) { - const serviceName = definition.replace(`${options.package}.`, ''); - const connectionService = new packageProto[serviceName](options.host + ':' + options.port, credentials.createInsecure()); - return connectionService; - // return async (...args) => { - // return new Promise((resolve, reject) => { - // connectionService(args[0], (err, response) => { - // if (err) { - // reject(err); - // } - // console.log('Greeting:', response.message); - // resolve(response); - // }); - // }); - // }; - } - } -} From a551a52db73cea3f9bbdcbcd01b4b4c961b77d77 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Tue, 19 Jan 2021 15:23:50 +0800 Subject: [PATCH 14/22] chore: export Application and Context for all framework --- packages/faas/src/interface.ts | 4 ++++ packages/grpc/src/interface.ts | 4 ++++ packages/rabbitmq/src/interface.ts | 4 ++++ packages/socketio/src/interface.ts | 5 +++++ packages/web-express/src/interface.ts | 8 ++++++-- packages/web-koa/src/interface.ts | 8 ++++++-- 6 files changed, 29 insertions(+), 4 deletions(-) diff --git a/packages/faas/src/interface.ts b/packages/faas/src/interface.ts index 0f61a80c5869..b9ce37b71740 100644 --- a/packages/faas/src/interface.ts +++ b/packages/faas/src/interface.ts @@ -42,6 +42,10 @@ export interface FaaSContext extends FaaSHTTPContext { hooks: MidwayHooks; } +export type Application = IMidwayFaaSApplication; + +export type Context = FaaSContext; + export interface IFaaSConfigurationOptions extends IConfigurationOptions { config?: object; middleware?: string[]; diff --git a/packages/grpc/src/interface.ts b/packages/grpc/src/interface.ts index 2e014ede9e2a..4116fcbba42e 100644 --- a/packages/grpc/src/interface.ts +++ b/packages/grpc/src/interface.ts @@ -6,6 +6,10 @@ export type IMidwayGRPCContext = IMidwayContext & { } export type IMidwayGRPCApplication = IMidwayApplication & Server; +export type Application = IMidwayGRPCApplication; + +export type Context = IMidwayGRPCContext; + export interface IGRPCServiceOptions { /** * application gRPC connection string diff --git a/packages/rabbitmq/src/interface.ts b/packages/rabbitmq/src/interface.ts index 0b1d532f9cdd..d6cb3116545e 100644 --- a/packages/rabbitmq/src/interface.ts +++ b/packages/rabbitmq/src/interface.ts @@ -43,3 +43,7 @@ export enum RabbitMQChannelEvent { CHANNEL_OPEN = 'ch_open', CHANNEL_DRAIN = 'ch_drain', } + +export type Application = IMidwayRabbitMQApplication; + +export type Context = IMidwayRabbitMQContext; diff --git a/packages/socketio/src/interface.ts b/packages/socketio/src/interface.ts index b74395aec3d5..15cbc4431505 100644 --- a/packages/socketio/src/interface.ts +++ b/packages/socketio/src/interface.ts @@ -13,3 +13,8 @@ export type IMidwaySocketIOConfigurationOptions = { } & SocketIO.ServerOptions & IConfigurationOptions; export type IMidwaySocketIOContext = SocketIO.Socket & IMidwayContext; + + +export type Application = IMidwaySocketIOApplication; + +export type Context = IMidwaySocketIOContext; diff --git a/packages/web-express/src/interface.ts b/packages/web-express/src/interface.ts index b7cb576bcc2f..f03e17b66cdd 100644 --- a/packages/web-express/src/interface.ts +++ b/packages/web-express/src/interface.ts @@ -1,5 +1,5 @@ import { IConfigurationOptions, IMidwayApplication, IMidwayContext } from '@midwayjs/core'; -import { Application, Request, Response, RequestHandler, NextFunction } from 'express'; +import { Application as ExpressApplication, Request, Response, RequestHandler, NextFunction } from 'express'; import { RouterParamValue } from "@midwayjs/decorator"; /** @@ -19,7 +19,7 @@ export type IMidwayExpressContext = IMidwayContext & { res: Response; startTime: number; } -export type IMidwayExpressApplication = IMidwayApplication & Application & { +export type IMidwayExpressApplication = IMidwayApplication & ExpressApplication & { generateController( controllerMapping: string, routeArgsInfo?: RouterParamValue[], @@ -53,3 +53,7 @@ export type Middleware = RequestHandler; export interface IWebMiddleware { resolve(): Middleware; } + +export type Application = IMidwayExpressApplication; + +export type Context = IMidwayExpressContext; diff --git a/packages/web-koa/src/interface.ts b/packages/web-koa/src/interface.ts index d47da133f7d7..5c87adb9e930 100644 --- a/packages/web-koa/src/interface.ts +++ b/packages/web-koa/src/interface.ts @@ -1,9 +1,9 @@ import { IConfigurationOptions, IMidwayApplication, IMidwayContext } from '@midwayjs/core'; import * as koa from 'koa'; -import { Context, DefaultState, Middleware, Next } from 'koa'; +import { Context as KoaContext, DefaultState, Middleware, Next } from 'koa'; import { RouterParamValue } from '@midwayjs/decorator'; -export type IMidwayKoaContext = IMidwayContext & Context; +export type IMidwayKoaContext = IMidwayContext & KoaContext; export type IMidwayKoaApplication = IMidwayApplication & koa & { generateController( controllerMapping: string, @@ -43,3 +43,7 @@ export type MiddlewareParamArray = Array; } + +export type Application = IMidwayKoaApplication; + +export type Context = IMidwayKoaContext; From 15695c7d29ab2bc1a4c6218eb041f613f54ce4b9 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Tue, 19 Jan 2021 22:51:55 +0800 Subject: [PATCH 15/22] chore: export DefaultConfig --- packages/grpc/src/comsumer/clients.ts | 4 ++-- packages/grpc/src/interface.ts | 2 +- .../base-app-multiple-service/src/config/config.default.ts | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/grpc/src/comsumer/clients.ts b/packages/grpc/src/comsumer/clients.ts index 1d76674604f0..480e13431a3c 100644 --- a/packages/grpc/src/comsumer/clients.ts +++ b/packages/grpc/src/comsumer/clients.ts @@ -1,6 +1,6 @@ import { Config, Init, Logger, Provide, Scope, ScopeEnum } from '@midwayjs/decorator'; import { credentials, loadPackageDefinition } from '@grpc/grpc-js'; -import { IMidwayGRPCConfigOptions } from '../interface'; +import { DefaultConfig } from '../interface'; import { loadProto } from '../util'; import * as camelCase from 'camelcase'; import { ILogger } from '@midwayjs/logger'; @@ -10,7 +10,7 @@ import { ILogger } from '@midwayjs/logger'; export class GRPCClients extends Map { @Config('grpc') - grpcConfig: IMidwayGRPCConfigOptions; + grpcConfig: DefaultConfig; @Logger() logger: ILogger; diff --git a/packages/grpc/src/interface.ts b/packages/grpc/src/interface.ts index 4116fcbba42e..eeffcfd675df 100644 --- a/packages/grpc/src/interface.ts +++ b/packages/grpc/src/interface.ts @@ -39,6 +39,6 @@ export interface IMidwayGRPFrameworkOptions extends IConfigurationOptions { loaderOptions?: object; } -export interface IMidwayGRPCConfigOptions extends IConfigurationOptions { +export interface DefaultConfig extends IConfigurationOptions { services: IGRPCServiceOptions[]; } diff --git a/packages/grpc/test/fixtures/base-app-multiple-service/src/config/config.default.ts b/packages/grpc/test/fixtures/base-app-multiple-service/src/config/config.default.ts index 2359f87803b5..c46e2bca9292 100644 --- a/packages/grpc/test/fixtures/base-app-multiple-service/src/config/config.default.ts +++ b/packages/grpc/test/fixtures/base-app-multiple-service/src/config/config.default.ts @@ -1,4 +1,4 @@ -import { IMidwayGRPCConfigOptions } from '../../../../../src'; +import { DefaultConfig } from '../../../../../src'; import { join } from 'path'; export const grpc = { @@ -9,4 +9,4 @@ export const grpc = { package: 'helloworld' } ] -} as IMidwayGRPCConfigOptions; +} as DefaultConfig; From 04dfce494abcf06c76194dd6d5272d037aa13ee4 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Tue, 19 Jan 2021 23:18:37 +0800 Subject: [PATCH 16/22] feat: use @Autoload replace run getAsync from container --- packages/grpc/src/comsumer/clients.ts | 3 ++- packages/grpc/src/comsumer/configuration.ts | 3 +-- packages/mock/test/new.test.ts | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/grpc/src/comsumer/clients.ts b/packages/grpc/src/comsumer/clients.ts index 480e13431a3c..3cf2236556fd 100644 --- a/packages/grpc/src/comsumer/clients.ts +++ b/packages/grpc/src/comsumer/clients.ts @@ -1,10 +1,11 @@ -import { Config, Init, Logger, Provide, Scope, ScopeEnum } from '@midwayjs/decorator'; +import { Autoload, Config, Init, Logger, Provide, Scope, ScopeEnum } from '@midwayjs/decorator'; import { credentials, loadPackageDefinition } from '@grpc/grpc-js'; import { DefaultConfig } from '../interface'; import { loadProto } from '../util'; import * as camelCase from 'camelcase'; import { ILogger } from '@midwayjs/logger'; +@Autoload() @Provide('clients') @Scope(ScopeEnum.Singleton) export class GRPCClients extends Map { diff --git a/packages/grpc/src/comsumer/configuration.ts b/packages/grpc/src/comsumer/configuration.ts index 9710eaa204ff..f29c816eae13 100644 --- a/packages/grpc/src/comsumer/configuration.ts +++ b/packages/grpc/src/comsumer/configuration.ts @@ -14,8 +14,7 @@ export class AutoConfiguration { @Logger() logger: ILogger; - async onReady(container) { + async onReady() { setLogger(this.logger); - await container.getAsync('grpc:clients'); } } diff --git a/packages/mock/test/new.test.ts b/packages/mock/test/new.test.ts index d55ac9ed0ade..83d3bbdd8f38 100644 --- a/packages/mock/test/new.test.ts +++ b/packages/mock/test/new.test.ts @@ -7,7 +7,6 @@ import { join } from 'path'; describe('/test/new.test.ts', () => { it('should test create app', async () => { const app = await createApp(join(__dirname, 'fixtures/base-app-decorator'), {}, Framework); - // TODO app 加上 egg-mock 的类型定义 const result = await createHttpRequest(app).get('/').query({ name: 'harry' }); expect(result.status).toBe(200); expect(result.text).toBe('hello world, harry'); From 38938ae22dbae2028b4396c7b2ec84bb89409d36 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Wed, 20 Jan 2021 00:15:09 +0800 Subject: [PATCH 17/22] test: add provider case --- .../decorator/src/microservice/provider.ts | 1 + .../test/microservice/provider.test.ts | 37 +++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 packages/decorator/test/microservice/provider.test.ts diff --git a/packages/decorator/src/microservice/provider.ts b/packages/decorator/src/microservice/provider.ts index 2d115785cdbe..0b286ece700d 100644 --- a/packages/decorator/src/microservice/provider.ts +++ b/packages/decorator/src/microservice/provider.ts @@ -13,6 +13,7 @@ import { import { Scope } from '../annotation'; export function Provider(type: MSProviderType.GRPC, metadata?: DecoratorMetadata.GRPCClassMetadata): ClassDecorator; +export function Provider(type: MSProviderType.DUBBO, metadata?: any): ClassDecorator; export function Provider(type: MSProviderType, metadata: any = {}): ClassDecorator { return (target: any) => { saveModule(MS_PROVIDER_KEY, target); diff --git a/packages/decorator/test/microservice/provider.test.ts b/packages/decorator/test/microservice/provider.test.ts new file mode 100644 index 000000000000..b7bd45e8a416 --- /dev/null +++ b/packages/decorator/test/microservice/provider.test.ts @@ -0,0 +1,37 @@ +import { + getClassMetadata, + getObjectDefProps, + listModule, + MS_PROVIDER_KEY, + ScopeEnum, + DecoratorMetadata, + MSProviderType, + Provider +} from '../../src'; +import ProviderClassMetadata = DecoratorMetadata.ProviderClassMetadata; + +@Provider(MSProviderType.GRPC, { package: 'test' }) +class TestFun { +} + +@Provider(MSProviderType.DUBBO) +class TestFun1 { +} + +describe('/test/microservice/provider.test.ts', () => { + it('test consumer decorator', () => { + const meta: ProviderClassMetadata = getClassMetadata(MS_PROVIDER_KEY, TestFun); + expect(meta).toEqual({ type: MSProviderType.GRPC, metadata: { package: 'test' } }); + + const meta2: ProviderClassMetadata = getClassMetadata(MS_PROVIDER_KEY, TestFun1); + expect(meta2).toEqual({ type: MSProviderType.DUBBO, metadata: {} }); + + const def = getObjectDefProps(TestFun); + expect(def).toEqual({ + scope: ScopeEnum.Request, + }); + + const m = listModule(MS_PROVIDER_KEY); + expect(m.length).toEqual(2); + }); +}); From 1d146d76242fd91d9f37031107e0b83e32772d54 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Thu, 21 Jan 2021 15:50:15 +0800 Subject: [PATCH 18/22] fix: typo --- packages/core/src/context/applicationContext.ts | 2 +- packages/core/test/baseFramework.test.ts | 2 +- packages/core/test/loader.test.ts | 2 +- packages/web-express/src/framework.ts | 2 +- packages/web-koa/src/framework.ts | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/core/src/context/applicationContext.ts b/packages/core/src/context/applicationContext.ts index 25fac445e52b..cb6fcb80932e 100644 --- a/packages/core/src/context/applicationContext.ts +++ b/packages/core/src/context/applicationContext.ts @@ -246,7 +246,7 @@ export class BaseApplicationContext const def = this.registry.getDefinition(identifier); if (!isPathEqual(definition.srcPath, def.srcPath)) { throw new Error( - `${identifier} path = ${definition.srcPath} is exist (${def.srcPath})!` + `${identifier} path = ${definition.srcPath} already exist (${def.srcPath})!` ); } } diff --git a/packages/core/test/baseFramework.test.ts b/packages/core/test/baseFramework.test.ts index 754cb61c52ea..9968684f99d0 100644 --- a/packages/core/test/baseFramework.test.ts +++ b/packages/core/test/baseFramework.test.ts @@ -244,7 +244,7 @@ describe('/test/baseFramework.test.ts', () => { // __dirname, // './fixtures/app-with-conflict/base-app-decorator/src/lib/' // ); - // const s = `baseService path = ${p}/userManager.ts is exist (${p}/service.ts)!`; + // const s = `baseService path = ${p}/userManager.ts already exist (${p}/service.ts)!`; // assert.ok(callback.withArgs(s).calledOnce); // }); diff --git a/packages/core/test/loader.test.ts b/packages/core/test/loader.test.ts index 14da43c0122f..5ff869654f23 100644 --- a/packages/core/test/loader.test.ts +++ b/packages/core/test/loader.test.ts @@ -409,7 +409,7 @@ describe('/test/loader.test.ts', () => { __dirname, './fixtures/app-with-conflict/base-app-decorator/src/lib/' ); - const s = `baseService path = ${p}/userManager.ts is exist (${p}/service.ts)!`; + const s = `baseService path = ${p}/userManager.ts already exist (${p}/service.ts)!`; assert.ok(callback.withArgs(s).calledOnce); }); diff --git a/packages/web-express/src/framework.ts b/packages/web-express/src/framework.ts index 25775756ffee..ce81f018f469 100644 --- a/packages/web-express/src/framework.ts +++ b/packages/web-express/src/framework.ts @@ -204,7 +204,7 @@ export class MidwayExpressFramework extends BaseFramework< const providerId = getProviderId(module); if (providerId) { if (this.controllerIds.indexOf(providerId) > -1) { - throw new Error(`controller identifier [${providerId}] is exists!`); + throw new Error(`controller identifier [${providerId}] already exists!`); } this.controllerIds.push(providerId); await this.preRegisterRouter(module, providerId); diff --git a/packages/web-koa/src/framework.ts b/packages/web-koa/src/framework.ts index 97d216b66543..e740c17eab90 100644 --- a/packages/web-koa/src/framework.ts +++ b/packages/web-koa/src/framework.ts @@ -132,7 +132,7 @@ export abstract class MidwayKoaBaseFramework< const providerId = getProviderId(module); if (providerId) { if (this.controllerIds.indexOf(providerId) > -1) { - throw new Error(`controller identifier [${providerId}] is exists!`); + throw new Error(`controller identifier [${providerId}] already exists!`); } this.controllerIds.push(providerId); await this.preRegisterRouter(module, providerId); From 66bf7f629303a1c5a7bf9c238ab17dae31c268e9 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Sat, 23 Jan 2021 18:51:18 +0800 Subject: [PATCH 19/22] feat: add createAnonymousContext and default contextLogger class --- packages/core/package.json | 4 +- packages/core/src/baseFramework.ts | 58 ++++++++++++++++--- packages/core/src/interface.ts | 23 +++++--- packages/core/src/logger.ts | 2 +- packages/core/test/baseFramework.test.ts | 15 +++++ packages/core/test/util.ts | 8 ++- packages/decorator/package.json | 4 +- packages/faas/src/framework.ts | 15 ++--- packages/faas/src/interface.ts | 19 +++--- packages/grpc/src/interface.ts | 6 +- packages/grpc/src/provider/framework.ts | 19 +++--- packages/grpc/src/provider/logger.ts | 4 ++ .../fixtures/base-app/src/provider/greeter.ts | 7 ++- packages/rabbitmq/package.json | 1 + packages/rabbitmq/src/framework.ts | 26 +++------ packages/rabbitmq/src/interface.ts | 2 +- packages/socketio/package.json | 1 + packages/socketio/src/framework.ts | 19 +++--- packages/socketio/src/interface.ts | 2 +- packages/web-express/package.json | 1 + packages/web-express/src/framework.ts | 21 ++----- packages/web-express/src/interface.ts | 3 +- packages/web-koa/package.json | 1 + packages/web-koa/src/framework.ts | 39 +++++-------- packages/web-koa/src/index.ts | 1 + packages/web-koa/src/interface.ts | 4 +- packages/web/src/framework/singleProcess.ts | 5 ++ packages/web/src/framework/web.ts | 10 +--- packages/web/src/interface.ts | 5 +- 29 files changed, 182 insertions(+), 143 deletions(-) diff --git a/packages/core/package.json b/packages/core/package.json index 285dcfcdc63b..a59d630c27c8 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -6,8 +6,8 @@ "typings": "dist/index.d.ts", "scripts": { "build": "midway-bin build -c", - "test": "midway-bin test --ts --forceExit", - "cov": "midway-bin cov --ts --forceExit", + "test": "midway-bin test --ts", + "cov": "midway-bin cov --ts", "link": "npm link" }, "keywords": [ diff --git a/packages/core/src/baseFramework.ts b/packages/core/src/baseFramework.ts index 34d208696f9f..01da4a1f7f05 100644 --- a/packages/core/src/baseFramework.ts +++ b/packages/core/src/baseFramework.ts @@ -3,7 +3,7 @@ import { ILifeCycle, IMidwayApplication, IMidwayBootstrapOptions, - IMidwayContainer, + IMidwayContainer, IMidwayContext, IMidwayFramework, MidwayFrameworkType, MidwayProcessTypeEnum, @@ -18,8 +18,9 @@ import { } from '@midwayjs/decorator'; import { ILogger, loggers, LoggerOptions, IMidwayLogger } from '@midwayjs/logger'; import { isAbsolute, join, dirname } from 'path'; -import { createMidwayLogger } from './logger'; +import { createMidwayLogger, MidwayContextLogger } from './logger'; import { safeRequire } from './util'; +import { MidwayRequestContainer } from './context/requestContainer'; function buildLoadDir(baseDir, dir) { if (!isAbsolute(dir)) { @@ -33,21 +34,25 @@ function setupAppDir(baseDir: string) { } export abstract class BaseFramework< - APP extends IMidwayApplication, - T extends IConfigurationOptions -> implements IMidwayFramework { + APP extends IMidwayApplication, + CTX extends IMidwayContext, + OPT extends IConfigurationOptions, +> implements IMidwayFramework { protected isTsMode = true; protected baseDir: string; protected appDir: string; protected applicationContext: IMidwayContainer; protected logger: ILogger; protected appLogger: ILogger; - public configurationOptions: T; + public configurationOptions: OPT; public app: APP; protected pkg: object; + protected defaultContext = {}; + protected BaseContextLoggerClass: any; - public configure(options: T): BaseFramework { + public configure(options: OPT): BaseFramework { this.configurationOptions = options; + this.BaseContextLoggerClass = options.ContextLoggerClass || this.getDefaultContextLoggerClass(); this.logger = options.logger; this.appLogger = options.appLogger; return this; @@ -217,6 +222,15 @@ export abstract class BaseFramework< public abstract run(): Promise; + protected setContextLoggerClass(BaseContextLogger: any) { + this.BaseContextLoggerClass = BaseContextLogger; + } + + protected createContextLogger(ctx: CTX, name?: string): ILogger { + const appLogger = this.getLogger(name); + return new this.BaseContextLoggerClass(ctx, appLogger); + } + public async stop(): Promise { await this.beforeStop(); await this.containerStop(); @@ -230,7 +244,8 @@ export abstract class BaseFramework< return this.baseDir; } - protected defineApplicationProperties(applicationProperties: object = {}) { + protected defineApplicationProperties(applicationProperties: object = {}, whiteList = []) { + const self = this; const defaultApplicationProperties = { getBaseDir: () => { return this.baseDir; @@ -279,7 +294,29 @@ export abstract class BaseFramework< getProjectName: () => { return this.getProjectName(); }, + + createAnonymousContext(extendCtx?: CTX) { + const ctx = extendCtx || Object.create(self.defaultContext); + ctx.startTime = ctx.startTime || Date.now(); + ctx.logger = ctx.logger || self.createContextLogger(ctx); + ctx.requestContext = new MidwayRequestContainer(ctx, this.getApplicationContext()); + ctx.requestContext.ready(); + if (!ctx.getLogger) { + ctx.getLogger = (name) => { + return self.createContextLogger(ctx, name); + }; + } + return ctx; + }, + + setContextLoggerClass(BaseContextLogger: any) { + return self.setContextLoggerClass(BaseContextLogger); + }, + }; + for (const method of whiteList) { + delete defaultApplicationProperties[method]; + } Object.assign( this.app, defaultApplicationProperties, @@ -361,4 +398,9 @@ export abstract class BaseFramework< public getFrameworkName() { return this.getFrameworkType().toString(); } + + public getDefaultContextLoggerClass(): any { + return MidwayContextLogger; + } + } diff --git a/packages/core/src/interface.ts b/packages/core/src/interface.ts index 2df78b485917..fcca24d48403 100644 --- a/packages/core/src/interface.ts +++ b/packages/core/src/interface.ts @@ -292,7 +292,18 @@ export enum MidwayProcessTypeEnum { */ export interface IMidwayLogger extends ILogger {} -export interface IMidwayApplication { +export interface IMidwayContext { + /** + * Custom properties. + */ + [key: string]: any; + requestContext: IMidwayContainer; + logger: ILogger; + getLogger(name?: string): ILogger; + startTime: number; +} + +export interface IMidwayApplication { getBaseDir(): string; getAppDir(): string; getEnv(): string; @@ -304,12 +315,8 @@ export interface IMidwayApplication { getCoreLogger(): ILogger; createLogger(name: string, options: LoggerOptions): ILogger; getProjectName(): string; -} - -export interface IMidwayContext { - getRequestContext?(): IMidwayContainer; - requestContext: IMidwayContainer; - logger: ILogger; + createAnonymousContext(...args): T; + setContextLoggerClass(BaseContextLoggerClass: any): void; } /** @@ -334,6 +341,7 @@ export interface IMidwayBootstrapOptions { export interface IConfigurationOptions { logger?: ILogger; appLogger?: ILogger; + ContextLoggerClass?: any; } export interface IMidwayFramework { @@ -355,6 +363,7 @@ export interface IMidwayFramework { protected contextLogger: ILogger; public ctx: T; - constructor(ctx, contextLogger: ILogger) { + constructor(ctx, contextLogger: ILogger, contextLabelHandler?) { this.ctx = ctx; this.contextLogger = contextLogger; } diff --git a/packages/core/test/baseFramework.test.ts b/packages/core/test/baseFramework.test.ts index 9968684f99d0..1f44886b739f 100644 --- a/packages/core/test/baseFramework.test.ts +++ b/packages/core/test/baseFramework.test.ts @@ -10,6 +10,7 @@ import * as path from 'path'; import { clearAllModule, clearContainerCache, + MidwayContextLogger, MidwayRequestContainer, } from '../src'; import * as mm from 'mm'; @@ -593,6 +594,20 @@ describe('/test/baseFramework.test.ts', () => { expect(framework.getApplication().getFrameworkType()).toEqual(framework.getFrameworkType()); expect(framework.getApplication().getProjectName()).toEqual(framework.getProjectName()); + // test context + class CustomContextLogger extends MidwayContextLogger { + formatContextLabel(): string { + return 'bbbb'; + } + } + framework.getApplication().setContextLoggerClass(CustomContextLogger); + expect(framework.getApplication().createAnonymousContext().startTime).toBeDefined(); + const ctxLogger = framework.getApplication().createAnonymousContext().getLogger(); + ctxLogger.info('ctx logger'); + + expect(framework.getApplication().createAnonymousContext().requestContext).toBeDefined(); + expect(framework.getApplication().createAnonymousContext().logger).toBeDefined(); + await framework.stop(); }); }); diff --git a/packages/core/test/util.ts b/packages/core/test/util.ts index 535bf8ef2737..9d0ed585d042 100644 --- a/packages/core/test/util.ts +++ b/packages/core/test/util.ts @@ -1,9 +1,10 @@ -import { BaseFramework, IMidwayApplication, IMidwayBootstrapOptions, MidwayFrameworkType } from '../src'; +import { BaseFramework, IMidwayApplication, IMidwayBootstrapOptions, MidwayFrameworkType, IMidwayContext } from '../src'; type mockApp = {} & IMidwayApplication; type mockAppOptions = {}; +type mockContext = IMidwayContext; -export class MockFramework extends BaseFramework { +export class MockFramework extends BaseFramework { getApplication(): mockApp { return this.app; @@ -21,4 +22,7 @@ export class MockFramework extends BaseFramework { this.app = {} as IMidwayApplication; } + getDefaultContextLoggerClass() { + return super.getDefaultContextLoggerClass(); + } } diff --git a/packages/decorator/package.json b/packages/decorator/package.json index b71e7e10b69e..54da7c7ec087 100644 --- a/packages/decorator/package.json +++ b/packages/decorator/package.json @@ -6,8 +6,8 @@ "typings": "dist/index.d.ts", "scripts": { "build": "midway-bin build -c", - "test": "midway-bin test --ts --forceExit", - "cov": "midway-bin cov --ts --forceExit", + "test": "midway-bin test --ts", + "cov": "midway-bin cov --ts", "ci": "npm run test", "link": "npm link" }, diff --git a/packages/faas/src/framework.ts b/packages/faas/src/framework.ts index 532050a41816..2ad4b346f3fc 100644 --- a/packages/faas/src/framework.ts +++ b/packages/faas/src/framework.ts @@ -14,7 +14,6 @@ import { listModule, listPreloadModule, MidwayFrameworkType, - MidwayRequestContainer, REQUEST_OBJ_CTX_KEY, } from '@midwayjs/core'; @@ -31,6 +30,7 @@ const LOCK_KEY = '_faas_starter_start_key'; export class MidwayFaaSFramework extends BaseFramework< IMidwayFaaSApplication, + FaaSContext, IFaaSConfigurationOptions > { protected defaultHandlerMethod = 'handler'; @@ -214,18 +214,13 @@ export class MidwayFaaSFramework extends BaseFramework< .getEnvironmentService() .getCurrentEnvironment(); } - if (!context.logger) { - context.logger = this.logger; - } - if (!context.requestContext) { - context.requestContext = new MidwayRequestContainer( - context, - this.getApplicationContext() - ); - } if (!context.hooks) { context.hooks = new MidwayHooks(context, this.app); } + if (!context.logger) { + context.logger = this.logger; + } + this.app.createAnonymousContext(context); return context; } diff --git a/packages/faas/src/interface.ts b/packages/faas/src/interface.ts index b9ce37b71740..bdc4a0c195e0 100644 --- a/packages/faas/src/interface.ts +++ b/packages/faas/src/interface.ts @@ -1,11 +1,19 @@ -import { MidwayRequestContainer, IMidwayApplication, IConfigurationOptions } from '@midwayjs/core'; +import { MidwayRequestContainer, IMidwayApplication, IConfigurationOptions, IMidwayContext } from '@midwayjs/core'; import { FaaSHTTPContext } from '@midwayjs/faas-typings'; import type { MidwayHooks } from './hooks'; import { ILogger } from '@midwayjs/logger'; +export interface FaaSContext extends FaaSHTTPContext, IMidwayContext { + logger: ILogger; + env: string; + requestContext: MidwayRequestContainer; + originContext: any; + hooks: MidwayHooks; +} + export type FaaSMiddleware = (() => (context: FaaSContext, next: () => Promise) => any) | string; -export interface IMidwayFaaSApplication extends IMidwayApplication { +export interface IMidwayFaaSApplication extends IMidwayApplication { getInitializeContext(); use(middleware: FaaSMiddleware); useMiddleware(mw: string[]); @@ -34,13 +42,6 @@ export interface FunctionHandler { handler(...args); } -export interface FaaSContext extends FaaSHTTPContext { - logger: ILogger; - env: string; - requestContext: MidwayRequestContainer; - originContext: any; - hooks: MidwayHooks; -} export type Application = IMidwayFaaSApplication; diff --git a/packages/grpc/src/interface.ts b/packages/grpc/src/interface.ts index eeffcfd675df..4478d1035343 100644 --- a/packages/grpc/src/interface.ts +++ b/packages/grpc/src/interface.ts @@ -1,10 +1,8 @@ import { IConfigurationOptions, IMidwayApplication, IMidwayContext } from '@midwayjs/core'; import { Server, ServerCredentials } from '@grpc/grpc-js'; -export type IMidwayGRPCContext = IMidwayContext & { - startTime: number; -} -export type IMidwayGRPCApplication = IMidwayApplication & Server; +export type IMidwayGRPCContext = IMidwayContext; +export type IMidwayGRPCApplication = IMidwayApplication & Server; export type Application = IMidwayGRPCApplication; diff --git a/packages/grpc/src/provider/framework.ts b/packages/grpc/src/provider/framework.ts index 7ae6765d64c1..a07656aa7fbd 100644 --- a/packages/grpc/src/provider/framework.ts +++ b/packages/grpc/src/provider/framework.ts @@ -5,7 +5,6 @@ import { IMidwayBootstrapOptions, listModule, MidwayFrameworkType, - MidwayRequestContainer, } from '@midwayjs/core'; import { @@ -15,7 +14,7 @@ import { MSProviderType } from '@midwayjs/decorator'; import { - IMidwayGRPCApplication, IMidwayGRPFrameworkOptions, + IMidwayGRPCApplication, IMidwayGRPCContext, IMidwayGRPFrameworkOptions, } from '../interface'; import { MidwayGRPCContextLogger } from './logger'; import { pascalCase } from 'pascal-case'; @@ -25,18 +24,12 @@ import { PackageDefinition } from '@grpc/proto-loader'; export class MidwayGRPCFramework extends BaseFramework< IMidwayGRPCApplication, + IMidwayGRPCContext, IMidwayGRPFrameworkOptions > { public app: IMidwayGRPCApplication; private server: Server; - public configure( - options: IMidwayGRPFrameworkOptions - ): MidwayGRPCFramework { - this.configurationOptions = options; - return this; - } - async applicationInitialize(options: Partial) { // set logger to grpc server setLogger(this.logger); @@ -88,9 +81,7 @@ export class MidwayGRPCFramework extends BaseFramework< for (const method in serviceDefinition) { serviceInstance[method] = async (call: ServerUnaryCall, callback: sendUnaryData) => { const ctx = { metadata: call.metadata} as any; - ctx.requestContext = new MidwayRequestContainer(ctx, this.getApplicationContext()); - ctx.logger = new MidwayGRPCContextLogger(ctx, this.appLogger); - + this.app.createAnonymousContext(ctx); try { const service = await ctx.requestContext.getAsync(module); const result = await service[camelCase(method)]?.apply(service, [call.request]); @@ -141,4 +132,8 @@ export class MidwayGRPCFramework extends BaseFramework< public getFrameworkName() { return 'midway:gRPC' } + + public getDefaultContextLoggerClass(): any { + return MidwayGRPCContextLogger; + } } diff --git a/packages/grpc/src/provider/logger.ts b/packages/grpc/src/provider/logger.ts index 7e3e8821dd69..99e9dff0b5f1 100644 --- a/packages/grpc/src/provider/logger.ts +++ b/packages/grpc/src/provider/logger.ts @@ -23,4 +23,8 @@ export class MidwayGRPCContextLogger extends MidwayContextLogger< // req.url return ''; } + + setFormatter() { + + } } diff --git a/packages/grpc/test/fixtures/base-app/src/provider/greeter.ts b/packages/grpc/test/fixtures/base-app/src/provider/greeter.ts index 20d8058bc4c1..abc7b070b6f2 100644 --- a/packages/grpc/test/fixtures/base-app/src/provider/greeter.ts +++ b/packages/grpc/test/fixtures/base-app/src/provider/greeter.ts @@ -1,5 +1,6 @@ -import { MSProviderType, Provider, Provide } from '@midwayjs/decorator'; +import { MSProviderType, Provider, Provide, Inject } from '@midwayjs/decorator'; import { helloworld } from '../interface'; +import { ILogger } from '@midwayjs/logger'; /** * package helloworld @@ -9,10 +10,14 @@ import { helloworld } from '../interface'; @Provider(MSProviderType.GRPC, { package: 'helloworld' }) export class Greeter implements helloworld.Greeter { + @Inject() + logger: ILogger; + /** * Implements the SayHello RPC method. */ async sayHello(request: helloworld.HelloRequest) { + this.logger.info('this is a context logger'); return { message: 'Hello ' + request.name } } } diff --git a/packages/rabbitmq/package.json b/packages/rabbitmq/package.json index 0249871e6555..2085fd9ef146 100644 --- a/packages/rabbitmq/package.json +++ b/packages/rabbitmq/package.json @@ -30,6 +30,7 @@ "dependencies": { "@midwayjs/core": "^2.6.10", "@midwayjs/decorator": "^2.6.8", + "@midwayjs/logger": "^2.6.9", "@types/amqplib": "^0.5.13", "amqplib": "^0.6.0" }, diff --git a/packages/rabbitmq/src/framework.ts b/packages/rabbitmq/src/framework.ts index 688f43548033..11c9cd6d4a4f 100644 --- a/packages/rabbitmq/src/framework.ts +++ b/packages/rabbitmq/src/framework.ts @@ -6,7 +6,6 @@ import { listModule, listPropertyDataFromClass, MidwayFrameworkType, - MidwayRequestContainer, } from '@midwayjs/core'; import { @@ -25,18 +24,12 @@ import { MidwayRabbitMQContextLogger } from './logger'; export class MidwayRabbitMQFramework extends BaseFramework< IMidwayRabbitMQApplication, + IMidwayRabbitMQContext, IMidwayRabbitMQConfigurationOptions > { public app: IMidwayRabbitMQApplication; public consumerList = []; - public configure( - options: IMidwayRabbitMQConfigurationOptions - ): MidwayRabbitMQFramework { - this.configurationOptions = options; - return this; - } - async applicationInitialize(options) { this.app = (new RabbitMQServer( this.configurationOptions @@ -101,19 +94,10 @@ export class MidwayRabbitMQFramework extends BaseFramework< async (data?: ConsumeMessage) => { const ctx = { channel: this.app.getChannel(), - startTime: Date.now(), queueName: listenerOptions.queueName, } as IMidwayRabbitMQContext; - ctx.logger = new MidwayRabbitMQContextLogger(ctx, this.appLogger); - const requestContainer = new MidwayRequestContainer( - ctx, - this.getApplicationContext() - ); - ctx.requestContext = requestContainer; - ctx.getRequestContext = () => { - return requestContainer; - }; - const ins = await requestContainer.getAsync(providerId); + this.app.createAnonymousContext(ctx); + const ins = await ctx.requestContext.getAsync(providerId); await ins[listenerOptions.propertyKey].call(ins, data); } ); @@ -122,4 +106,8 @@ export class MidwayRabbitMQFramework extends BaseFramework< public getFrameworkName() { return 'midway:rabbitmq' } + + public getDefaultContextLoggerClass(): any { + return MidwayRabbitMQContextLogger; + } } diff --git a/packages/rabbitmq/src/interface.ts b/packages/rabbitmq/src/interface.ts index d6cb3116545e..f38acb8fe2b6 100644 --- a/packages/rabbitmq/src/interface.ts +++ b/packages/rabbitmq/src/interface.ts @@ -14,7 +14,7 @@ export interface IRabbitMQApplication { close(): Promise; } -export type IMidwayRabbitMQApplication = IMidwayApplication & IRabbitMQApplication; +export type IMidwayRabbitMQApplication = IMidwayApplication & IRabbitMQApplication; export interface IRabbitMQExchange { name: string, diff --git a/packages/socketio/package.json b/packages/socketio/package.json index 44313f4e9db4..c1fcc32f741c 100644 --- a/packages/socketio/package.json +++ b/packages/socketio/package.json @@ -33,6 +33,7 @@ "dependencies": { "@midwayjs/core": "^2.6.10", "@midwayjs/decorator": "^2.6.8", + "@midwayjs/logger": "^2.6.9", "socket.io": "^2.3.0" }, "author": "Harry Chen ", diff --git a/packages/socketio/src/framework.ts b/packages/socketio/src/framework.ts index 91a58af863fa..e9e54b0380b5 100644 --- a/packages/socketio/src/framework.ts +++ b/packages/socketio/src/framework.ts @@ -5,7 +5,6 @@ import { IMidwayBootstrapOptions, listModule, MidwayFrameworkType, - MidwayRequestContainer, } from '@midwayjs/core'; import { @@ -21,21 +20,16 @@ import { WSEventInfo, WSEventTypeEnum, } from '@midwayjs/decorator'; +import { MidwaySocketIOContextLogger } from './logger'; export class MidwaySocketIOFramework extends BaseFramework< IMidwaySocketIOApplication, + IMidwaySocketIOContext, IMidwaySocketIOConfigurationOptions > { applicationInitialize(options: IMidwayBootstrapOptions) {} public app: IMidwaySocketIOApplication; - public configure( - options: IMidwaySocketIOConfigurationOptions - ): MidwaySocketIOFramework { - this.configurationOptions = options; - return this; - } - protected async afterContainerDirectoryLoad( options: Partial ) { @@ -51,10 +45,7 @@ export class MidwaySocketIOFramework extends BaseFramework< } this.app.use((socket, next) => { - socket.requestContext = new MidwayRequestContainer( - socket, - this.getApplicationContext() - ); + this.app.createAnonymousContext(socket); socket.requestContext.registerObject('socket', socket); next(); }); @@ -229,4 +220,8 @@ export class MidwaySocketIOFramework extends BaseFramework< public getFrameworkName() { return 'midway:socketIO' } + + public getDefaultContextLoggerClass(): any { + return MidwaySocketIOContextLogger + } } diff --git a/packages/socketio/src/interface.ts b/packages/socketio/src/interface.ts index 15cbc4431505..8e9cccb76e8e 100644 --- a/packages/socketio/src/interface.ts +++ b/packages/socketio/src/interface.ts @@ -3,7 +3,7 @@ import { IConfigurationOptions, IMidwayApplication, IMidwayContext } from '@midw import { Server as HttpServer } from 'http'; import { Server as HttpsServer } from 'https'; -export type IMidwaySocketIOApplication = IMidwayApplication & { +export type IMidwaySocketIOApplication = IMidwayApplication & { use(fn: (socket: IMidwaySocketIOContext, fn: (err?: any) => void) => void): SocketIO.Namespace; } & SocketIO.Server; diff --git a/packages/web-express/package.json b/packages/web-express/package.json index 811595033d68..8a23f31cd879 100644 --- a/packages/web-express/package.json +++ b/packages/web-express/package.json @@ -31,6 +31,7 @@ "dependencies": { "@midwayjs/core": "^2.6.10", "@midwayjs/decorator": "^2.6.8", + "@midwayjs/logger": "^2.6.9", "express": "^4.17.1" }, "author": "Harry Chen ", diff --git a/packages/web-express/src/framework.ts b/packages/web-express/src/framework.ts index ce81f018f469..c47d5dc93274 100644 --- a/packages/web-express/src/framework.ts +++ b/packages/web-express/src/framework.ts @@ -8,7 +8,6 @@ import { IMidwayBootstrapOptions, listModule, MidwayFrameworkType, - MidwayRequestContainer, } from '@midwayjs/core'; import { @@ -41,6 +40,7 @@ import { MidwayExpressContextLogger } from './logger'; export class MidwayExpressFramework extends BaseFramework< IMidwayExpressApplication, + IMidwayExpressContext, IMidwayExpressConfigurationOptions > { public app: IMidwayExpressApplication; @@ -52,13 +52,6 @@ export class MidwayExpressFramework extends BaseFramework< }> = []; private server: Server; - public configure( - options: IMidwayExpressConfigurationOptions - ): MidwayExpressFramework { - this.configurationOptions = options; - return this; - } - async applicationInitialize(options: Partial) { this.app = (express() as unknown) as IMidwayExpressApplication; this.defineApplicationProperties({ @@ -72,16 +65,10 @@ export class MidwayExpressFramework extends BaseFramework< }); this.app.use((req, res, next) => { const ctx = { req, res } as IMidwayExpressContext; - ctx.logger = new MidwayExpressContextLogger(ctx, this.appLogger); - ctx.startTime = Date.now(); - ctx.requestContext = new MidwayRequestContainer( - ctx, - this.getApplicationContext() - ); + this.app.createAnonymousContext(ctx); (req as any).requestContext = ctx.requestContext; ctx.requestContext.registerObject('req', req); ctx.requestContext.registerObject('res', res); - ctx.requestContext.ready(); next(); }); } @@ -357,4 +344,8 @@ export class MidwayExpressFramework extends BaseFramework< public getFrameworkName() { return 'midway:express' } + + public getDefaultContextLoggerClass() { + return MidwayExpressContextLogger; + } } diff --git a/packages/web-express/src/interface.ts b/packages/web-express/src/interface.ts index f03e17b66cdd..ef8a35490ebf 100644 --- a/packages/web-express/src/interface.ts +++ b/packages/web-express/src/interface.ts @@ -17,9 +17,8 @@ export type IMidwayExpressNext = NextFunction; export type IMidwayExpressContext = IMidwayContext & { req: Request; res: Response; - startTime: number; } -export type IMidwayExpressApplication = IMidwayApplication & ExpressApplication & { +export type IMidwayExpressApplication = IMidwayApplication & ExpressApplication & { generateController( controllerMapping: string, routeArgsInfo?: RouterParamValue[], diff --git a/packages/web-koa/package.json b/packages/web-koa/package.json index 0db574b07344..77f88c9d4a5a 100644 --- a/packages/web-koa/package.json +++ b/packages/web-koa/package.json @@ -32,6 +32,7 @@ "dependencies": { "@midwayjs/core": "^2.6.10", "@midwayjs/decorator": "^2.6.8", + "@midwayjs/logger": "^2.6.9", "koa": "^2.13.0", "koa-router": "^9.4.0" }, diff --git a/packages/web-koa/src/framework.ts b/packages/web-koa/src/framework.ts index e740c17eab90..d0215b5002f6 100644 --- a/packages/web-koa/src/framework.ts +++ b/packages/web-koa/src/framework.ts @@ -5,11 +5,9 @@ import { getPropertyDataFromClass, getPropertyMetadata, getProviderId, - IMidwayApplication, - IMidwayBootstrapOptions, + IMidwayBootstrapOptions, IMidwayContext, listModule, MidwayFrameworkType, - MidwayRequestContainer, } from '@midwayjs/core'; import { @@ -42,18 +40,18 @@ import { readFileSync } from 'fs'; import { Server } from 'net'; export abstract class MidwayKoaBaseFramework< - T, - U extends IMidwayApplication & IMidwayKoaApplicationPlus, - CustomContext -> extends BaseFramework { - public app: U; + APP extends IMidwayKoaApplicationPlus, + CTX extends IMidwayContext, + OPT +> extends BaseFramework { + public app: APP; private controllerIds: string[] = []; public prioritySortRouters: Array<{ priority: number; router: Router; }> = []; - public getApplication(): U { + public getApplication(): APP { return this.app; } @@ -273,32 +271,19 @@ export abstract class MidwayKoaBaseFramework< } export class MidwayKoaFramework extends MidwayKoaBaseFramework< - IMidwayKoaConfigurationOptions, IMidwayKoaApplication, - IMidwayKoaContext + IMidwayKoaContext, + IMidwayKoaConfigurationOptions > { private server: Server; - public configure( - options: IMidwayKoaConfigurationOptions - ): MidwayKoaFramework { - this.configurationOptions = options; - return this; - } - async applicationInitialize(options: Partial) { this.app = new koa< DefaultState, IMidwayKoaContext >() as IMidwayKoaApplication; this.app.use(async (ctx, next) => { - ctx.logger = new MidwayKoaContextLogger(ctx, this.appLogger); - ctx.startTime = Date.now(); - ctx.requestContext = new MidwayRequestContainer( - ctx, - this.getApplicationContext() - ); - await ctx.requestContext.ready(); + this.app.createAnonymousContext(ctx); await next(); }); @@ -369,4 +354,8 @@ export class MidwayKoaFramework extends MidwayKoaBaseFramework< public getServer() { return this.server; } + + public getDefaultContextLoggerClass() { + return MidwayKoaContextLogger; + } } diff --git a/packages/web-koa/src/index.ts b/packages/web-koa/src/index.ts index f55e61b0cc0d..453523828961 100644 --- a/packages/web-koa/src/index.ts +++ b/packages/web-koa/src/index.ts @@ -2,4 +2,5 @@ export { MidwayKoaFramework as Framework, MidwayKoaBaseFramework, } from './framework'; +export { MidwayKoaContextLogger } from './logger'; export * from './interface'; diff --git a/packages/web-koa/src/interface.ts b/packages/web-koa/src/interface.ts index 5c87adb9e930..714c51b207d7 100644 --- a/packages/web-koa/src/interface.ts +++ b/packages/web-koa/src/interface.ts @@ -4,7 +4,7 @@ import { Context as KoaContext, DefaultState, Middleware, Next } from 'koa'; import { RouterParamValue } from '@midwayjs/decorator'; export type IMidwayKoaContext = IMidwayContext & KoaContext; -export type IMidwayKoaApplication = IMidwayApplication & koa & { +export type IMidwayKoaApplication = IMidwayApplication & koa & { generateController( controllerMapping: string, routeArgsInfo?: RouterParamValue[], @@ -15,7 +15,7 @@ export type IMidwayKoaApplication = IMidwayApplication & koa extends IMidwayApplication { use(...args); } diff --git a/packages/web/src/framework/singleProcess.ts b/packages/web/src/framework/singleProcess.ts index a655833056cf..d69d838266d9 100644 --- a/packages/web/src/framework/singleProcess.ts +++ b/packages/web/src/framework/singleProcess.ts @@ -10,6 +10,7 @@ import { resolve } from 'path'; import { readFileSync } from 'fs'; import { Server } from 'net'; import { LoggerOptions } from '@midwayjs/logger'; +import { MidwayKoaContextLogger } from '@midwayjs/koa'; export class SingleProcess implements IMidwayFramework { @@ -131,4 +132,8 @@ export class SingleProcess public getFrameworkName() { return 'midway:web' } + + public getDefaultContextLoggerClass() { + return MidwayKoaContextLogger; + } } diff --git a/packages/web/src/framework/web.ts b/packages/web/src/framework/web.ts index 24ad13fd018a..e1b8a7d3a64a 100644 --- a/packages/web/src/framework/web.ts +++ b/packages/web/src/framework/web.ts @@ -12,9 +12,9 @@ import { Application, Context, Router, EggLogger } from 'egg'; import { loggers } from '@midwayjs/logger'; export class MidwayWebFramework extends MidwayKoaBaseFramework< - IMidwayWebConfigurationOptions, Application, - Context + Context, + IMidwayWebConfigurationOptions > { public app: Application; public configurationOptions: IMidwayWebConfigurationOptions; @@ -58,11 +58,7 @@ export class MidwayWebFramework extends MidwayKoaBaseFramework< // TODO 单进程模式下区分进程类型?? return MidwayProcessTypeEnum.APPLICATION; }, - - getLogger: name => { - return this.getLogger(name); - }, - }); + }, ['createAnonymousContext']); Object.defineProperty(this.app, 'applicationContext', { get() { diff --git a/packages/web/src/interface.ts b/packages/web/src/interface.ts index cd563c0ecc26..0dbcd758aeec 100644 --- a/packages/web/src/interface.ts +++ b/packages/web/src/interface.ts @@ -27,11 +27,14 @@ declare module 'egg' { generateController?(controllerMapping: string); generateMiddleware?(middlewareId: string): Promise>; createLogger(name: string, options: LoggerOptions); - getProjectName(); + getProjectName(): string; + setContextLoggerClass(BaseContextLoggerClass: any): void; } interface Context { requestContext: IMidwayContainer; + getLogger(name?: string): EggLogger & ILogger; + startTime: number; } } From f502d4aaf92b3c196168de705241a72c27860117 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Sat, 23 Jan 2021 20:50:20 +0800 Subject: [PATCH 20/22] fix: lint --- packages/bootstrap/test/index.test.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/bootstrap/test/index.test.ts b/packages/bootstrap/test/index.test.ts index cd2c2dd4e3e2..576b5b79d256 100644 --- a/packages/bootstrap/test/index.test.ts +++ b/packages/bootstrap/test/index.test.ts @@ -6,6 +6,7 @@ import { IMidwayContainer, IConfigurationOptions, MidwayFrameworkType, + MidwayContextLogger } from '@midwayjs/core'; import { clearAllLoggers } from '@midwayjs/logger'; import { join } from 'path'; @@ -90,6 +91,10 @@ class TestFrameworkUnit implements IMidwayFramework { From 3f82d1cc7b6f79ae5c07d06d7bedc2d76f60230a Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Sat, 23 Jan 2021 21:01:37 +0800 Subject: [PATCH 21/22] fix: set getter --- packages/core/src/baseFramework.ts | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/core/src/baseFramework.ts b/packages/core/src/baseFramework.ts index 01da4a1f7f05..8abc16e36e2f 100644 --- a/packages/core/src/baseFramework.ts +++ b/packages/core/src/baseFramework.ts @@ -297,10 +297,16 @@ export abstract class BaseFramework< createAnonymousContext(extendCtx?: CTX) { const ctx = extendCtx || Object.create(self.defaultContext); - ctx.startTime = ctx.startTime || Date.now(); - ctx.logger = ctx.logger || self.createContextLogger(ctx); - ctx.requestContext = new MidwayRequestContainer(ctx, this.getApplicationContext()); - ctx.requestContext.ready(); + if (!ctx.startTime) { + ctx.startTime = Date.now(); + } + if (!ctx.logger) { + ctx.logger = self.createContextLogger(ctx); + } + if (!ctx.requestContext) { + ctx.requestContext = new MidwayRequestContainer(ctx, this.getApplicationContext()); + ctx.requestContext.ready(); + } if (!ctx.getLogger) { ctx.getLogger = (name) => { return self.createContextLogger(ctx, name); From 4275f88137be488681bd99fd3cfd3272915b0c44 Mon Sep 17 00:00:00 2001 From: Harry Chen Date: Sun, 24 Jan 2021 22:16:10 +0800 Subject: [PATCH 22/22] refactor: add method for context logger --- packages/grpc/src/interface.ts | 7 ++++-- packages/grpc/src/provider/framework.ts | 2 +- packages/grpc/src/provider/logger.ts | 29 +++++++------------------ 3 files changed, 14 insertions(+), 24 deletions(-) diff --git a/packages/grpc/src/interface.ts b/packages/grpc/src/interface.ts index 4478d1035343..0f178b78639e 100644 --- a/packages/grpc/src/interface.ts +++ b/packages/grpc/src/interface.ts @@ -1,7 +1,10 @@ import { IConfigurationOptions, IMidwayApplication, IMidwayContext } from '@midwayjs/core'; -import { Server, ServerCredentials } from '@grpc/grpc-js'; +import { Server, ServerCredentials, Metadata } from '@grpc/grpc-js'; -export type IMidwayGRPCContext = IMidwayContext; +export interface IMidwayGRPCContext extends IMidwayContext { + metadata: Metadata; + method: string; +} export type IMidwayGRPCApplication = IMidwayApplication & Server; export type Application = IMidwayGRPCApplication; diff --git a/packages/grpc/src/provider/framework.ts b/packages/grpc/src/provider/framework.ts index a07656aa7fbd..00436b98de4f 100644 --- a/packages/grpc/src/provider/framework.ts +++ b/packages/grpc/src/provider/framework.ts @@ -80,7 +80,7 @@ export class MidwayGRPCFramework extends BaseFramework< for (const method in serviceDefinition) { serviceInstance[method] = async (call: ServerUnaryCall, callback: sendUnaryData) => { - const ctx = { metadata: call.metadata} as any; + const ctx = { method, metadata: call.metadata } as any; this.app.createAnonymousContext(ctx); try { const service = await ctx.requestContext.getAsync(module); diff --git a/packages/grpc/src/provider/logger.ts b/packages/grpc/src/provider/logger.ts index 99e9dff0b5f1..608bf67f3146 100644 --- a/packages/grpc/src/provider/logger.ts +++ b/packages/grpc/src/provider/logger.ts @@ -5,26 +5,13 @@ export class MidwayGRPCContextLogger extends MidwayContextLogger< IMidwayGRPCContext > { formatContextLabel() { - // format: '[$userId/$ip/$traceId/$use_ms $method $url]' - // const userId = req?.['session']?.['userId'] || '-'; - // const traceId = '-'; - // const use = Date.now() - this.ctx.startTime; - // return ( - // userId + - // '/' + - // req.ip + - // '/' + - // traceId + - // '/' + - // use + - // 'ms ' + - // req.method + - // ' ' + - // req.url - return ''; - } - - setFormatter() { - + const ctx = this.ctx; + const use = Date.now() - ctx.startTime; + return ( + ctx.method + + '/' + + use + + 'ms' + ); } }