Комментарии 6
О, я в свое время тоже шаблонизатор писал: https://habr.com/ru/articles/560722/
Им, похоже, даже периодически кто-то помимо меня пользуется. Основные идеи: поточная обработка, независимость от моделей и их динамический анализ, расширяемость синтаксиса. Ну и сверху от этого второй компонент, который умеет генерировать репорты в CSV, HTML, PDF и Excel.
Спасибо, прочитал! Насчет GetSourceSchemeAsync у нас похожая идея, когда шаблон определяет, какие данные нужно загрузить. Только у меня она выросла из полей и связей CRM. Вы пишете, что полученную схему можно использовать для SQL или GraphQL. Дошло ли до реализации такого адаптера? Было бы интересно посмотреть.
Ответил мимо.
Любой из этих движков мог собрать наше уведомление из готовых значений. Сложность начиналась раньше: определить нужные поля, пройти по связям и загрузить их без отдельного обработчика на каждый новый параметр.
...и вы пустились в парсинг шаблонов с этой задачей?
Мне кажется, я проще сделал на готовом шаблонизаторе (liquidjs). Точнее, в моём случае подгрузка значений вообще не касается шаблонов, и liquidjs можно заменить на что угодно.
---
Любой сервис может бросить "сухое" событие. Уже на этом этапе ясно, что нужно подгружать.
{
event: "order-placed",
customer: { userId: "u1" },
ord: { orderId: "o1" }
}Сервис уведомлений принимает такие события (или команды) и наполняет их как свой контекст в тех местах, где видит поля userId, orderId и т.п. Получается:
{
event: "order-placed",
customer: { userId: "u1", firstName: "Yegor", lastName: _, phone: _, email: _, ... },
ord: { orderId: "o1", items: [_], placedAt: _, ... }
}И всё, полный контекст для любого распространённого подстановщика уже готов. Можно сразу рендерить шаблон `Hi, {{ customer.fullName }}! Your order for {{ ord.total | money }} has been placed.`
Не, я понимаю, что в теории может быть хитрый шаблон для order-placed, который не использует поля из customer, и в таком случае мы зря читаем таблицу users. Но на практике такого не бывает: всё равно же есть связь между формой сухого контекста и набором полей, которые задействованы в шаблоне.
Кстати связь между users и orders не важна. Она требуется только чтобы сформировать join-запрос, но можно и просто отдельные select'ы вызвать параллельно. Шаблону-то какая потом разница?
Это что касается рендеринга шаблонов для отправки. Авторинг шаблонов я бы рассматривал отдельно - там можно было бы что-то распарсить для подсказок в конструкторе.
У нас как раз было важно, чтобы можно было добавлять в шаблон данные, которых раньше в нём не было, без доработки кода загрузки. Если нужного параметра ещё нет, администратор создаёт его в каталоге: выбирает поле и путь к нему по доступным связям CRM. Дальше движок сам определяет, что загрузить. Убрали параметр из шаблона и данные для него больше не запрашиваются, если они не нужны остальным параметрам.
В вашем примере менять шаблон удобно, пока нужные значения уже входят в подготовленный контекст. А если завтра понадобится, например, телефон подразделения менеджера заказа, которого там пока нет? У вас такую загрузку можно добавить настройками или потребуется менять код обогащения события?

Что стоит за простым уведомлением: история разработки шаблонизатора на C#