Optimization: Add .clone() method to Ajv instance
What version of Ajv you are you using?
8.9.0
What problem do you want to solve?
Optimize Schema Compilation
What do you think is the correct solution to problem?
Allow Ajv instance to be cloned
Will you be able to implement it?
Unsure
Just wondering about a possible ajv.clone() method to help optimize schema compilation times. This would allow users to .clone() a partially configured Ajv instance, allowing additional configurations to be applied to the clone without impacting the initial instance. This with the hope of avoiding reinitialization of the whole instance in some scenarios.
Example
// -------------------------------------------------------------------------
// Partially Instance
// -------------------------------------------------------------------------
const ajv = addFormats(new Ajv({}), [
'date-time', 'time', 'date', 'email', 'hostname', 'ipv4',
'ipv6', 'uri', 'uri-reference', 'uuid', 'uri-template',
'json-pointer', 'relative-json-pointer', 'regex'
])
.addKeyword({ keyword: 'specialized', type: 'object', validate: validateSpecialized })
.addKeyword('maxByteLength')
.addKeyword('minByteLength')
.addKeyword('modifier')
.addKeyword('kind')
// ------------------------------------------------------------
// Full Instance
//
// The following clones the partial instance for the purpose
// of creating a validation context. The additional schemas
// A, B and C are added to the clone, leaving the original
// instance unchanged. This should help avoid any costly
// setup required configuring the partial instance (measured
// upwards of 100ms)
// ------------------------------------------------------------
const context = ajv.clone().addSchema([A, B, C])
const validate = context.compile(C)
What’s the use case for that?
@epoberezkin Hi
I'm currently working on an application that manages sets of schemas grouped into namespaces defined by the application. Each schema within a namespace has an associated $id; with some $id's colliding with $id's in other namespaces. To avoid $id collision, I am currently creating a fresh Ajv instance for each namespace. For example
export function createNamespace(schemas: AnySchema[]): Ajv {
return addFormats(new Ajv({}), [ ... ]).addSchema(schemas) // slow
}
However I've noticed that initializing fresh instances of Ajv tends to be quite expensive when using addFormats(...). As a possible suggestion avoid complete reinitialization; a .clone() function would allow one to partially configure an Ajv instance with common configurations (slow), with the .clone() function returning a new but preconfigured instance (fast). This would enable users to gradually apply additional configurations (such as addSchema()) to the clone without impacting the common instance, as well as avoiding re-initialization. So for example.
const commonAjv = addFormats(new Ajv({}), [ ... ]) // slow
export function createNamespace(schemas: AnySchema[]): Ajv {
return commonAjv.clone().addSchema(schemas) // fast
}
So this would solve my particular use case (which is mostly dealing with potential ID collisions) while potentially speeding app start up by an order of magnitude. I imagine such a feature could be useful to users in general by allowing gradual configuration of Ajv contexts from a singular instance.
Would something like this be relatively straightforward to implement?