From 1a22ef4a5809954cee0b86487b9d95b1a9b66bec Mon Sep 17 00:00:00 2001 From: Becca Wye <68872214+0bex0@users.noreply.github.com> Date: Tue, 20 May 2025 17:00:24 +0100 Subject: [PATCH] Revert "Optimise Ajv cache usage (#1062)" This reverts commit 990995b89f84397852c79eec4cecccb9e8fb6fc2. --- src/middlewares/openapi.request.validator.ts | 12 +++++------- src/middlewares/openapi.response.validator.ts | 9 ++++----- src/middlewares/util.ts | 19 +------------------ 3 files changed, 10 insertions(+), 30 deletions(-) diff --git a/src/middlewares/openapi.request.validator.ts b/src/middlewares/openapi.request.validator.ts index afaf4064..06b869f8 100644 --- a/src/middlewares/openapi.request.validator.ts +++ b/src/middlewares/openapi.request.validator.ts @@ -20,7 +20,6 @@ import { ContentType, ajvErrorsToValidatorError, augmentAjvErrors, - useAjvCache, } from './util'; type OperationObject = OpenAPIV3.OperationObject; @@ -29,6 +28,7 @@ type ReferenceObject = OpenAPIV3.ReferenceObject; type SecurityRequirementObject = OpenAPIV3.SecurityRequirementObject; type SecuritySchemeObject = OpenAPIV3.SecuritySchemeObject; type ApiKeySecurityScheme = OpenAPIV3.ApiKeySecurityScheme; + export class RequestValidator { private middlewareCache: { [key: string]: RequestHandler } = {}; private apiDoc: OpenAPIV3.DocumentV3 | OpenAPIV3.DocumentV3_1; @@ -79,7 +79,7 @@ export class RequestValidator { const key = `${req.method}-${path}-${contentTypeKey}`; if (!this.middlewareCache[key]) { - const middleware = this.buildMiddleware(path, reqSchema, contentType, key); + const middleware = this.buildMiddleware(path, reqSchema, contentType); this.middlewareCache[key] = middleware; } return this.middlewareCache[key](req, res, next); @@ -103,7 +103,6 @@ export class RequestValidator { path: string, reqSchema: OperationObject, contentType: ContentType, - ajvCacheKey: string ): RequestHandler { const apiDoc = this.apiDoc; const schemaParser = new ParametersSchemaParser(this.ajv, apiDoc); @@ -113,7 +112,7 @@ export class RequestValidator { const validator = new Validator(this.apiDoc, parameters, body, { general: this.ajv, body: this.ajvBody, - }, ajvCacheKey); + }); const allowUnknownQueryParameters = !!( reqSchema['x-eov-allow-unknown-query-parameters'] ?? @@ -306,7 +305,6 @@ class Validator { general: Ajv; body: Ajv; }, - ajvCacheKey: string ) { this.apiDoc = apiDoc; this.schemaGeneral = this._schemaGeneral(parametersSchema); @@ -315,8 +313,8 @@ class Validator { ...(this.schemaGeneral).properties, // query, header, params props body: (this.schemaBody).properties.body, // body props }; - this.validatorGeneral = useAjvCache(ajv.general, this.schemaGeneral, ajvCacheKey); - this.validatorBody = useAjvCache(ajv.body, this.schemaBody, ajvCacheKey); + this.validatorGeneral = ajv.general.compile(this.schemaGeneral); + this.validatorBody = ajv.body.compile(this.schemaBody); } private _schemaGeneral(parameters: ParametersSchema): object { diff --git a/src/middlewares/openapi.response.validator.ts b/src/middlewares/openapi.response.validator.ts index 41c60992..75b467ea 100644 --- a/src/middlewares/openapi.response.validator.ts +++ b/src/middlewares/openapi.response.validator.ts @@ -6,7 +6,7 @@ import { augmentAjvErrors, ContentType, ajvErrorsToValidatorError, - findResponseContent, useAjvCache, + findResponseContent, } from './util'; import { OpenAPIV3, @@ -109,7 +109,7 @@ export class ResponseValidator { let validators = this.validatorsCache[key]; if (!validators) { - validators = this.buildValidators(responses, key); + validators = this.buildValidators(responses); this.validatorsCache[key] = validators; } return validators; @@ -212,7 +212,7 @@ export class ResponseValidator { * @param responses * @returns a map of validators */ - private buildValidators(responses: OpenAPIV3.ResponsesObject, ajvCacheKey: string): { + private buildValidators(responses: OpenAPIV3.ResponsesObject): { [key: string]: ValidateFunction; } { const validationTypes = (response) => { @@ -295,10 +295,9 @@ export class ResponseValidator { const schema = contentTypeSchemas[contentType]; schema.paths = this.spec.paths; // add paths for resolution with multi-file schema.components = this.spec.components; // add components for resolution w/ multi-file - const validator = useAjvCache(this.ajvBody, schema, `${ajvCacheKey}-${code}-${contentType}`) validators[code] = { ...validators[code], - [contentType]: validator, + [contentType]: this.ajvBody.compile(schema), }; } } diff --git a/src/middlewares/util.ts b/src/middlewares/util.ts index c316c29e..4c2524d8 100644 --- a/src/middlewares/util.ts +++ b/src/middlewares/util.ts @@ -1,6 +1,6 @@ import type { ErrorObject } from 'ajv-draft-04'; import { Request } from 'express'; -import { AjvInstance, ValidationError } from '../framework/types'; +import { ValidationError } from '../framework/types'; export class ContentType { public readonly mediaType: string = null; @@ -174,20 +174,3 @@ export const zipObject = (keys, values) => return acc }, {}) -/** - * Tries to fetch a schema from ajv instance by the provided key otherwise adds (and - * compiles) the schema under provided key. We provide a key to avoid ajv library - * using the whole schema as a cache key, leading to a lot of unnecessary memory - * usage - this is not recommended by the library either: - * https://ajv.js.org/guide/managing-schemas.html#cache-key-schema-vs-key-vs-id - * - * @param ajvCacheKey - Key which will be used for ajv cache - */ -export function useAjvCache(ajv: AjvInstance, schema: object, ajvCacheKey: string) { - let validator = ajv.getSchema(ajvCacheKey); - if (!validator) { - ajv.addSchema(schema, ajvCacheKey); - validator = ajv.getSchema(ajvCacheKey); - } - return validator -}