Валидация JSON-схем в Ajv основана на предварительной компиляции схем в исполняемые функции. Основная идея кеширования заключается в том, чтобы избежать повторной компиляции одной и той же схемы при многократной валидации данных. Это критически важно для производительности, особенно в серверных приложениях и высоконагруженных API.
Кеш в Ajv работает на нескольких уровнях:
Компиляция схемы является дорогой операцией, поэтому Ajv стремится выполнить её ровно один раз на каждую уникальную схему.
Каждая JSON-схема при первом использовании проходит этап компиляции в JavaScript-функцию. Результат сохраняется внутри экземпляра Ajv.
Если одна и та же схема запрашивается повторно через методы
compile или validate, возвращается уже
существующая функция из кеша.
Ключевым элементом кеширования является идентификатор схемы:
$id (или id в старых версиях);При наличии $id схема становится доступной глобально
внутри конкретного экземпляра Ajv и может переиспользоваться через
getSchema.
Метод compile(schema) возвращает функцию-валидатор. При
повторном вызове с той же схемой:
Метод validate(schemaKey, data) также опирается на кеш:
если схема уже была зарегистрирована через addSchema, её
валидатор не пересобирается.
Повторное использование особенно эффективно при частой валидации однотипных структур данных (например, DTO в API).
Система идентификации схем играет ключевую роль в механизме кеширования.
$id как ключ кешаСхемы с $id автоматически регистрируются внутри
экземпляра Ajv:
const schema = {
$id: "userSchema",
type: "object",
properties: {
id: { type: "number" }
}
};
После добавления:
getSchema("userSchema");$ref, используют
кешированный результат.$ref и
переиспользованиеПри использовании ссылок $ref Ajv не компилирует
подсхемы заново. Вместо этого происходит обращение к уже сохранённым
валидаторам в кеше.
Метод addSchema добавляет схему в кеш экземпляра
Ajv:
ajv.addSchema(schema);
Поведение:
$id;$ref.Если схема уже существует, повторное добавление не пересобирает
валидатор, если $id совпадает.
Метод getSchema извлекает скомпилированную функцию из
кеша:
const validate = ajv.getSchema("userSchema");
Особенности:
validate.Удаление схемы из кеша выполняется через
removeSchema:
ajv.removeSchema("userSchema");
Последствия удаления:
$ref перестают разрешаться;При этом уже полученные ссылки на валидатор продолжают существовать как обычные функции JavaScript.
В длительно работающих процессах кеш может накапливать большое количество схем. Для управления этим состоянием используются механизмы очистки.
В некоторых конфигурациях Ajv поддерживается удаление неиспользуемых схем:
Полная очистка экземпляра Ajv приводит к сбросу всех скомпилированных схем и валидаторов:
$ref перестают работать до повторной регистрации
схем;Такой подход используется в сценариях с динамической перезагрузкой схем.
Каждый экземпляр Ajv имеет собственный кеш. Это означает:
const ajv1 = new Ajv();
const ajv2 = new Ajv();
В этом случае кеши полностью независимы, даже при одинаковых
$id.
Некоторые опции Ajv влияют на поведение кеша:
schemas при инициализации позволяет предзагрузить
кеш;removeAdditional и другие флаги влияют на структуру
компиляции;code и source опции могут изменять способ
генерации функций, но не принцип кеширования.Важно учитывать, что изменение опций после компиляции схемы не приводит к пересборке уже закешированного валидатора.
Эффективность кеширования в Ajv напрямую влияет на производительность:
Оптимальная стратегия обычно включает:
$id для всех ключевых структур
данных.При динамическом добавлении большого количества уникальных схем без удаления кеш может расти бесконтрольно.
$idПовторное использование одинаковых $id для разных схем
приводит к перезаписи кеша и потенциально некорректной валидации.
Изменение схемы без удаления старой версии из кеша не приводит к
обновлению зависимых $ref, что создаёт рассинхронизацию
логики.
Повторное использование уже скомпилированных функций может приводить
к тому, что изменения схемы не отражаются в валидации до очистки кеша
или смены $id.