-
-
Notifications
You must be signed in to change notification settings - Fork 286
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(common): Refactoring contextMiddleware to fix memory leaks
- Loading branch information
Showing
21 changed files
with
774 additions
and
69 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,47 +1,70 @@ | ||
import {InjectorService} from "@tsed/di"; | ||
import * as Express from "express"; | ||
import {RequestContext} from "../../mvc"; | ||
|
||
const onFinished = require("on-finished"); | ||
const uuidv4 = require("uuid/v4"); | ||
|
||
const whenFinished = (request: any, response: any) => async () => { | ||
const {injector} = request.ctx; | ||
const defaultReqIdBuilder = () => uuidv4().replace(/-/gi, ""); | ||
|
||
await injector.emit("$onResponse", request, response); | ||
await request.ctx.destroy(); | ||
delete request.ctx; | ||
delete request.log; | ||
}; | ||
export class ContextMiddleware { | ||
level: "debug" | "info" | "warn" | "error" | "off" | undefined; | ||
maxStackSize: number; | ||
ignoreUrlPatterns: string[]; | ||
reqIdBuilder: any; | ||
|
||
/** | ||
* Bind request and create a new context to store information during the request lifecycle. See @@RequestContext@@ for more details. | ||
* | ||
* @param injector | ||
*/ | ||
export function contextMiddleware(injector: InjectorService) { | ||
const {level, maxStackSize, ignoreUrlPatterns = [], reqIdBuilder = () => uuidv4().replace(/-/gi, "")} = injector.settings.logger || {}; | ||
constructor(private injector: InjectorService) { | ||
const {level, maxStackSize, ignoreUrlPatterns = [], reqIdBuilder = defaultReqIdBuilder} = injector.settings.logger || {}; | ||
|
||
this.level = level; | ||
this.maxStackSize = maxStackSize!; | ||
this.ignoreUrlPatterns = ignoreUrlPatterns; | ||
this.reqIdBuilder = reqIdBuilder; | ||
} | ||
|
||
async use(request: any, response: any, next: any) { | ||
const {level, ignoreUrlPatterns, maxStackSize} = this; | ||
|
||
const id = this.reqIdBuilder(); | ||
|
||
return async (request: Express.Request, response: Express.Response, next: Express.NextFunction) => { | ||
const id = reqIdBuilder(); | ||
request.ctx = new RequestContext({ | ||
id, | ||
logger: injector.logger, | ||
logger: this.injector.logger, | ||
url: request.originalUrl || request.url, | ||
ignoreUrlPatterns, | ||
level, | ||
maxStackSize, | ||
injector | ||
injector: this.injector | ||
}); | ||
|
||
request.id = id; | ||
// deprecated | ||
request.log = request.ctx.logger; | ||
|
||
onFinished(response, whenFinished(request, response)); | ||
onFinished(response, ContextMiddleware.onClose); | ||
|
||
await injector.emit("$onRequest", request, response); | ||
await this.injector.emit("$onRequest", request, response); | ||
|
||
next(); | ||
}; | ||
} | ||
|
||
static async onClose(err: any, response: any) { | ||
const {req: request} = response; | ||
try { | ||
await request.ctx.emit("$onResponse", request, response); | ||
await request.ctx.destroy(); | ||
} catch (er) {} | ||
|
||
delete request.ctx; | ||
delete request.log; | ||
} | ||
} | ||
|
||
/** | ||
* Bind request and create a new context to store information during the request lifecycle. See @@RequestContext@@ for more details. | ||
* | ||
* @param injector | ||
*/ | ||
export function contextMiddleware(injector: InjectorService) { | ||
const middleware = new ContextMiddleware(injector); | ||
|
||
return middleware.use.bind(middleware); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
stats.json | ||
.tmp |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
############################################################################### | ||
############################################################################### | ||
## _______ _____ ______ _____ ## | ||
## |__ __/ ____| ____| __ \ ## | ||
## | | | (___ | |__ | | | | ## | ||
## | | \___ \| __| | | | | ## | ||
## | | ____) | |____| |__| | ## | ||
## |_| |_____/|______|_____/ ## | ||
## ## | ||
## description : Dockerfile for TsED Application ## | ||
## author : TsED team ## | ||
## date : 20190820 ## | ||
## version : 1.0 ## | ||
############################################################################### | ||
############################################################################### | ||
FROM node:12.13.0-alpine | ||
|
||
RUN apk update && apk add build-base git python | ||
|
||
COPY package.json . | ||
COPY ./src ./src | ||
COPY ./lib ./lib | ||
|
||
RUN yarn install --production | ||
|
||
EXPOSE 8081 | ||
ENV PORT 8081 | ||
ENV NODE_ENV production | ||
|
||
CMD ["yarn", "start:prod"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
version: '3.3' | ||
services: | ||
server: | ||
build: | ||
context: ./ | ||
dockerfile: Dockerfile | ||
args: | ||
- http_proxy | ||
- https_proxy | ||
- no_proxy | ||
image: tsed/test-artillery:latest | ||
ports: | ||
- "3000:3000" | ||
- "9229:9229" | ||
stdin_open: true # -i | ||
tty: true # -t | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
{ | ||
"name": "@tsed/test-artillery", | ||
"version": "5.42.1", | ||
"description": "Artillery test packages", | ||
"main": "./lib/index.js", | ||
"typings": "./lib/index.d.ts", | ||
"scripts": { | ||
"start": "node --expose-gc -r ts-node/register -r tsconfig-paths/register src/index.ts", | ||
"start:express": "node --inspect --expose-gc test/server/express.js", | ||
"start:prod": "node --expose-gc lib/index.js", | ||
"build": "tsc --build tsconfig.compile.json", | ||
"test:artillery": "artillery run test/test.yml", | ||
"docker:build": "docker-compose build", | ||
"docker:upd": "docker-compose up -d", | ||
"docker:up": "docker-compose up", | ||
"docker:down": "docker-compose down", | ||
"plot": "yarn start && python plot.py", | ||
"plot:express": "yarn start:express && python plot.py" | ||
}, | ||
"dependencies": { | ||
"@tsed/ajv": "5.42.1", | ||
"@tsed/common": "5.42.1", | ||
"@tsed/core": "5.42.1", | ||
"@tsed/di": "5.42.1", | ||
"@tsed/graphql": "5.42.1", | ||
"@tsed/mongoose": "5.42.1", | ||
"@tsed/multipartfiles": "5.42.1", | ||
"@tsed/passport": "5.42.1", | ||
"@tsed/seq": "5.42.1", | ||
"@tsed/servestatic": "5.42.1", | ||
"@tsed/swagger": "5.42.1", | ||
"@tsed/testing": "5.42.1", | ||
"@tsed/typeorm": "5.42.1", | ||
"express": "4.17.1", | ||
"compression": "1.7.4", | ||
"body-parser": "1.19.0", | ||
"cookie-parser": "1.4.4", | ||
"method-override": "3.0.0" | ||
}, | ||
"devDependencies": { | ||
"@types/compression": "1.7.0", | ||
"@types/body-parser": "1.19.0", | ||
"@types/method-override": "0.0.31", | ||
"artillery": "^1.6.0-29", | ||
"heapdump": "0.3.15" | ||
}, | ||
"private": true | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#!/usr/bin/env python | ||
|
||
import matplotlib.pyplot as plt | ||
import json | ||
|
||
statsFile = open('.tmp/stats.json', 'r') | ||
stats = json.load(statsFile) | ||
heapSizes = stats[1] | ||
timestamps = stats[0] | ||
|
||
print('Plotting %s' % ', '.join(map(str, heapSizes))) | ||
|
||
plt.plot(timestamps, heapSizes) | ||
plt.ylabel('Heap Size') | ||
plt.xlabel('timestamp (ms)') | ||
plt.show() |
Oops, something went wrong.