- marked as major
- edited description
Optimize schema object transformation with caching
I would like to use web request validation based on an OpenAPI specification in a productive environment with a maximum response time of 10 ms. This number should be achievable with web requests with an array of 500 entries, and with an object of depth equal to two for each entry.
Former tickets , #259, #250, #225 and #214 could give a performance boost to the request validation.#213
Former ticket #273 illustrates a serious time-consuming operation related to the reading of the request body
and its conversion into a JsonNode; this ticket should be treated as well.
Another time-consuming operation is the systematic construction of a schema object based on the Swagger schema and its transformation by iterations to finally get a JsonNode. After analysis, I notice that this result is the same for each call on a given endpoint, so it is reasonable to want to keep this result for reuse.
Setting up a cache using a ConcurrentHashMap allows a drastic improvement in response time. The caching key must be able to identify the current API operation, including the target, i.e. a URL variable, a query parameter, or the body of the request.
For example:
public class SchemaValidator {
...
private Map<String, JsonNode> transformedSchemaCache = new ConcurrentHashMap<>();
public ValidationReport validate(@Nonnull final String operationId,
@Nonnull final String value,
@Nullable final Schema schema,
@Nullable final String keyPrefix) {
...
content = readContent(value, schema);
final String validationKey = String.format("%s.%s", keyPrefix, operationId);
final JsonNode schemaObject = readAndTransformSchemaObject(validationKey, schema, keyPrefix);
...
}
private JsonNode readAndTransformSchemaObject(final String key, final Schema schema, @Nullable final String keyPrefix) {
return transformedSchemaCache.computeIfAbsent(key, o -> {
final ObjectNode schemaObject = Json.mapper().convertValue(schema, ObjectNode.class);
final SchemaTransformationContext transformationContext = SchemaTransformationContext.create()
.forRequest("request.body".equalsIgnoreCase(keyPrefix))
.forResponse("response.body".equalsIgnoreCase(keyPrefix))
.withAdditionalPropertiesValidation(additionalPropertiesValidationEnabled())
.withDefinitions(definitions)
.build();
transformers.forEach(t -> t.apply(schemaObject, transformationContext));
checkForKnownGotchasAndLogMessage(schemaObject);
return schemaObject;
});
}
...
}
Convinced by the usefulness of an executable API specification for syntax and semantic live validation, I allow myself to set a high level of priority.
Thanks for your feedback,
Kind regards
Comments (2)
-
reporter -
- changed status to resolved
Available in 2.11.5
- Log in to comment