Skip to content

Commit

Permalink
Add memoization to improve performance
Browse files Browse the repository at this point in the history
  • Loading branch information
Igor Savin committed Jun 25, 2019
1 parent 80974a3 commit a1318ab
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 9 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@
"author": "Idan Tovi",
"license": "Apache-2.0",
"dependencies": {
"api-schema-builder": "^1.0.9"
"api-schema-builder": "^1.0.9",
"memoizee": "^0.4.14"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^1.9.0",
Expand Down
6 changes: 4 additions & 2 deletions src/middleware.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict';

const schemaEndpointResolver = require('./utils/schemaEndpointResolver');
const SchemaEndpointResolver = require('./utils/schemaEndpointResolver');

const InputValidationError = require('./inputValidationError'),
apiSchemaBuilder = require('api-schema-builder');
Expand All @@ -9,6 +9,7 @@ const allowedFrameworks = ['express', 'koa'];
let schemas = {};
let middlewareOptions;
let framework;
let schemaEndpointResolver;

function init(swaggerPath, options) {
middlewareOptions = options || {};
Expand All @@ -17,9 +18,10 @@ function init(swaggerPath, options) {
});

framework = frameworkToLoad ? require(`./frameworks/${frameworkToLoad}`) : require('./frameworks/express');
schemaEndpointResolver = new SchemaEndpointResolver();

// build schema for requests only
let schemaBuilderOptions = Object.assign({}, options, {buildRequests: true, buildResponses: false});
let schemaBuilderOptions = Object.assign({}, options, { buildRequests: true, buildResponses: false });
return apiSchemaBuilder.buildSchema(swaggerPath, schemaBuilderOptions).then((receivedSchemas) => {
schemas = receivedSchemas;
});
Expand Down
15 changes: 11 additions & 4 deletions src/utils/schemaEndpointResolver.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
function getMethodSchema(schemas, path, method) {
const memoize = require('memoizee');

// This logic is wrapped into class to have isolated memoization contexts
class SchemaEndpointResolver {
constructor() {
this.getMethodSchema = memoize(getMethodSchemaInternal);
}
}

function getMethodSchemaInternal(schemas, path, method) {
const methodLowerCase = method.toLowerCase();
const routePath = pathMatcher(schemas, path);
const route = schemas[routePath];
Expand Down Expand Up @@ -28,6 +37,4 @@ function pathMatcher(routes, path) {
});
}

module.exports = {
getMethodSchema
};
module.exports = SchemaEndpointResolver;
66 changes: 66 additions & 0 deletions test/openapi3/pets-parametrized.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,72 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/error_model'
put:
summary: update pet
security:
- public-key: []
description: >-
tags:
- pets

requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/pet'
parameters:
- name: petId
in: path
required: true
description: The id of the pet to retrieve
schema:
type: string
operationId: updatePet
responses:
'200':
description: pet
headers:
x-zooz-request-id:
description: request id
schema:
type: string
content:
application/json:
schema:
$ref: '#/components/schemas/pet'
'400':
description: Bad request
headers:
x-zooz-request-id:
description: request id
schema:
type: string
content:
application/json:
schema:
$ref: '#/components/schemas/error_model'
'401':
description: Unauthorize
headers:
x-zooz-request-id:
description: request id
schema:
type: string
content:
application/json:
schema:
$ref: '#/components/schemas/error_model'
'500':
description: Internal error
headers:
x-zooz-request-id:
description: request id
schema:
type: string
content:
application/json:
schema:
$ref: '#/components/schemas/error_model'
components:
parameters:
public-key:
Expand Down
19 changes: 17 additions & 2 deletions test/utils/schemaEndpointResolver-test.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
const chai = require('chai'),
expect = chai.expect;
const apiSchemaBuilder = require('api-schema-builder');
const schemaEndpointResolver = require('../../src/utils/schemaEndpointResolver');
const SchemaEndpointResolver = require('../../src/utils/schemaEndpointResolver');
const swaggerPath = 'test/openapi3/pets-parametrized.yaml';

describe('schemaEndpointResolver', () => {
let schemas;
let schemaEndpointResolver;
before(() => {
let schemaBuilderOptions = { buildRequests: true, buildResponses: true };
let schemaBuilderOptions = {buildRequests: true, buildResponses: true};
return apiSchemaBuilder.buildSchema(swaggerPath, schemaBuilderOptions).then((receivedSchemas) => {
schemas = receivedSchemas;
});
});
beforeEach(() => {
schemaEndpointResolver = new SchemaEndpointResolver();
});

it('resolves exact path correctly', () => {
const endpoint = schemaEndpointResolver.getMethodSchema(schemas, '/pets/:petId', 'get');
Expand All @@ -27,4 +31,15 @@ describe('schemaEndpointResolver', () => {
const endpoint = schemaEndpointResolver.getMethodSchema(schemas, '/pets/:id', 'GET');
expect(endpoint).to.be.ok;
});

it('uses all three params to memoize result', () => {
const endpointGet = schemaEndpointResolver.getMethodSchema(schemas, '/pets/:id', 'GET');
expect(endpointGet.body).to.be.undefined;

const endpointPut = schemaEndpointResolver.getMethodSchema(schemas, '/pets/:id', 'PUT');
expect(endpointPut.body).to.be.ok;

const endpointGet2 = schemaEndpointResolver.getMethodSchema(schemas, '/pets/:id', 'GET');
expect(endpointGet2.body).to.be.undefined;
});
});

0 comments on commit a1318ab

Please sign in to comment.