-
Notifications
You must be signed in to change notification settings - Fork 52
Ru:TaggableSmartHandler
Пока проще всего получилось описать работу этих классов на примерах.
Пусть у нас есть две таблицы и соотвествующие бизнес объекты - User и City (таблицы users и cities). Каждый из пользователей имеет обязательное свойство city ссылающееся на город. У этих таблиц/объектов могут быть дополнительные поля/аттрибуты, вроде name.
Если мы хотим получить список всех пользователей, то делаем запрос вида SELECT * FROM users;
При этом единственный тэг который можно привязать к такому запросу - это тег с названием таблицы. При изменении любого пользователя запросы по этому тэгу должны раскешиваться.
Тоже самое касается и запросов SELECT * FROM users WHERE users.name = 'Ivan'
или, например, ... WHERE users.birthday IS NOT NULL
. Все эти запросы привязываются к единственному тегу на основе названия таблицы users.
Если нужно искать пользователей которые живут в конкретном городе SELECT * FROM users WHERE city_id = 33
, то запрос будет привязан к тегу "cities|33". Почему такой запрос повешенный на тэг из другой таблицы будет актуален (или что нужно делать что бы он был актуален)?
Обновим пользователя (c id=55) у которого city_id = 33. В таком случае необходимо обновить следующие теги:
- тег users|55 (т.е. раскешиваем самого пользователя)
- тег users (нужно сделать неактуальными все общие запросы на таблицу users описанные двумя абзацами выше)
- теги связанных объектов (городов) на которые ссылается текущий (пользователь), в данном случае cities|33
- если у пользователя меняется само свойство city_id, то нужно раскешить как тэг старого города так и нового
Т.к. в списке тегов для раскешивания есть cities|33, то приведённый выше запрос будет всегда актуален при измении пользователя связанного с запросом. При этом при изменении пользователя не связанного с городом раскешивание происходить не будет. Тоже самое касается и обновления города. Как только мы изменяем город 33, то раскешиваются запросы с тегом cities|33 и запрос сохранит актуальность при изменении города.
Если попадаются сложные запрос с JOIN'ами, то тэги создаются по названию таблиц, т.к. запрос вида SELECT * FROM users JOIN cities ON cities.id = users.city_id WHERE cities.name = 'Moscow'
будет бесхитростно повешен на два тега cities и users. При измении/добавлении записей в любой из этих таблиц следующий такой запрос будет браться из базы.
Плюсы подобного подхода:
- Не раскешиваются запросы основанные на связях OneToMany (дай мне список пользователей из такого-то города)
- Запросы на несколько таблиц изменяются при редактировании любой из таблиц
Минусы подобного подхода:
- Для кэширования необходима хитрая логика анализа SQL запроса что бы решить по каким тегам необходимо закешировать запрос.
- Для раскешивания необходимо смотреть свойства объекта и соседние с ним объекты.