Весною 2012 року за рекомендаціями наших постійних клієнтів до нас звернувся молодий, амбітний та наполегливий бізнесмен з Москви з замовленням, яке поставило нас в ступор… І хоча на той момент ми працювали на ринку Друпал-розробки біля 5 років, проте таких складних завдань перед нами ще не ставилося. Проект називався HiConversion і передбачав наступний функціонал:
- публікація та управління рекламними оголошеннями в соц.мережі VK;
- збір статистики по всім опублікованим оголошенням із зовнішніх джерел, таких як VK, Google Analytics, Yandex.Metrica;
- можливість перегляду статистики по опублікованим оголошенням за будь-який період часу;
- автоматичне або ручне управління, в залежності від результатів зібраної статистики;
- можливість налаштовувати всі таргетинги як в індивідуальному порядку, так і масово;
- інтерфейси для роботи рекламних агенцій, ієрархічна система ролей та доступів;
- контроль стану рахунку клієнта: можливість його поповнення, автоматична зупинка оголошень.
І це далеко не вичерпний список. Але давайте розглянемо архітектурний підхід до реалізації такого технічно складного проекту більш детально.
Як бачите, поставлені перед проектом задачі були далеко не тривіальні для веб-додатку, тим більше, вони повністю виходити за рамки “рідного” для Drupal функціоналу. Необхідність оновлювати десятки тисяч запитів за хвилину інформацією з зовнішніх джерел змусила нас шукати нетрадиційні рішення для подолання обмежень більшості механізмів як ядра Drupal, так і сторонніх сервісів.
Для найбільш ефективного використання обмежень сторонніх сервісів на запити, враховуючи різний формат даних, їх принципів комунікації та аутентифікації, нам довелося переосмислити формат збереження та обробки черг в Drupal. Черга оброблялася не завдяки повільним запитам за розкладом (cron), а php-демоном, який постійно моніторив наявність елементів у черзі та виконував задачі настільки швидко, наскільки це взагалі було можливо. За лімітами ресурсів вела спостереження складна система “семафорів”, побудована на механізмі замків Drupal (Lock API), а створені нами інтерфейси дозволяли зручно та комфортно додавати нові типи елементів черги.
Оскільки нам доводилося зберігати величезні об’єми статичних даних (близько мільйона записів) і постійно їх оновлювати, ми були змушені глибоко модифікувати принцип обробки полів в Drupal. Для того, щоб зовсім не відходити від філософії Drupal та мати можливість використовувати максимальну кількість стандартних рішень, ми не тільки створили нові, більш підлаштовані до наших потреб типи полів, але й використали можливості Drupal Field Storage API на всі 100%. В нашому випадку більшість операцій вимагали великої кількості полів однотипної інформації за один раз, тому ми значно виграли в продуктивності, додавши можливість масового оновлення полів із подальшим викликом необхідних хуків. Пізніше такий підхід дозволив нам використовувати готові модулі для побудови складних представлень (views) із заплутаними наборами фільтрів і можливістю їх збереження.
Незважаючи на всю складність побудованої нами системи, ми також заклали в її фундамент можливість розширення функціоналу та додавання обробників подій черги з гнучкими налаштуваннями. У юзер-інтерфейсі це виглядало як додавання нового елемента Field Collection із набором полів налаштувань, а з боку коду необхідно було лише додати обробник цих налаштувань і правил реакції на події, розширивши базовий клас поведінки (reaction handler-a).