October 23

Как решать реальные задачи no-code сервисами

Не так давно я успешно закончил небольшой эксперимент, реализацию которого наконец-то доверил сервисам по автоматизации. Фигурантом сегодняшнего дела будет выступать сервис Make.com, бывший Integromat. В то время как в сети можно найти множество информации, где рассказывается о том, как платформы вроде Zapier и других уже давно заменили разработчиков, реальных примеров использования для более сложных задач, чем простая отправка нескольких полей в CRM или рассылка приветственных писем без строгих требований ко времени, найти практически невозможно. Я решил усложнить им задачу и получил неплохие результаты.

Подписывайтесь на мой Телеграм.

Задача и мотивация выбора инструмента

Задача: выдавать ключи раннего доступа к продукту, которые хранятся в Google Sheets табличке. Выдача должна проходить быстро, если не моментально, а так же нужно отправить письмо с этим кодом юзеру на почту. Под капотом несколько простых проверок на уникальность юзера.

Таска это маркетинговая, а значит требования будут меняться каждый день 🙃 В текущей нагрузке остальными задачами качество реализации такой штуки своими руками напрямую зависело бы от качества менеджмента этого проекта, а времени у компетентных людей естественно не было. Почему бы не попробовать собрать такую задачу с помощью сервиса автоматизации, чтобы даже сами маркетологи смогли что-то поправить и посмотреть?

У меня так же не было времени вникать во все детали — я не знаю откуда брались вообще изначально коды, кто и как их генерировал и т.п. Я лишь видел Гугл табличку, куда руками кто-то забивал пачками новые коды. Там уже даже вели учет, кому выдали какой код, поэтому менять эту систему желания не было. Впрочем, оно и выглядело нормально на тот момент.

В общем, я наконец-то нашел подходящую задачу, чтобы дать шанс ноу-коду!
Забегая вперед, после этого опыта я остановился на немного другом подходе для определенных задач, но убедился в том, что сервисы автоматизации это очень даже рабочий метод.

Инструменты

1. Источником данных были стандартные Google Sheets.

2. На входе для юзера — форма для опросов TypeFrom. Это как Гугл Формс, но для натуралов. Объективно никакого смысла создавать свою кастомную форму на сайте нет, поэтому я сразу пропушил этот вариант. Я вижу этот сервис чуть ли не везде, где есть опросы, и точно уверен, что он стабильно работает. Так же я знал, что там можно строить сложные схемы опросов с различными проверками и условиями, что само по себе полезно.

3. Форма редиректила юзера на сайт, где ему выводился присвоенный для него код. Тут в ход вступил небольшой бекенд, который уже давно существовал и работал. Добавили в него простой запрос, который принимает на вход имейл и платформу юзера, а в ответ он отдавал присвоенный код из таблички. Но на самом деле это не третий шаг обработки, потому что до этого код надо было выбрать и записать для юзера. Сейчас бы этот бекенд я сделал бы на облачных функциях.

4. В качестве платформы автоматизации я остановился на Make.com. Я уже пользовался им давно, чтобы отправлять сообщения в Телеграм при появлении новой записи в табличке. Тогда я уперся в какую-то проблему, которую не осилил решить, поэтому забил и накодил вручную. Мейк вступал в работу сразу после сабмита формы. ТайпФорма отправляла вебхук с результатами формы, который ловил Мейк и уже реализовывал логику выбора кода и присваивал его за юзером.

5. Brevo. Это просто сервис, который исторически использовали для имейл рассылок. Здесь мог быть MailChimp и любой другой аналог. Он не так интересен в данном случае.

6. Slack. Я любитель обложить логами все, что только можно, поэтому репорты о том как завершаются операции отправлялись в отдельный канал в Слаке. Это еще и способ увидеть когда что-то сломалось — если сообщения прекратились, то ставим свечку 🕯️

Реализация

Typefrom

Тайпформа немного впечатлила меня инструментарием, по которому можно создать фильтрацию ответов. Я рассчитывал все проверки делать в Мейке, но это даже не понадобилось, потому что юзеры маркировались еще на этапе формы.

У нас были разные условия выдачи кодов, которые менялись со временем. Сначала мы раздавали ключи только для PC юзеров, а консольщиков собирали в базу, чтобы дослать им приглашения, когда откроется доступ. В последствие добивлась одна консоль, для нее пришлось доработать логику.
Не все ПК-бояре могли получить ключ. Так как это был закрытый тест, то мы хотели допустить только тех, у кого сильное железо. В опросе маркетинг создал множество вариантов ответов по железу и по нему мы фильтровали. Благо видеокарт и процессоров существует не так много, поэтому все они шли одним списком. В ход пошла обычная логика if then. Но далее идет самое интересное.

Стандартная логика ТайпФормы подразумевает, что в зависимости от ответа тебя отправит на определенный следующий вопрос. Других опций во флоу особо нет. А мне нужно было как-то сложить три разных ответа (проц, видюха, память) и, если только все три вместе соответствуют критерию, тогда выдать ключ.

Сначала я думал направлять юзера на какую-то отдельную карточку или вопрос, по наличию ответа на который я бы определил результат. Если все три ответа подходят, то юзер увидит специальную бесполезную страницу перед концом формы. А далее уже в Мейке проверять наличие ответа на этот вопрос и выдавать ключ. Но затея оказалась не очень рабочая и выглядела тупо. Покопавшись в ТайпФорме я обнаружил, что у них есть переменные, значения которым можно выставлять по той же самой логике с if-ами. В итоге я взял дефолтную переменную score, и инкрементировал ее при каждом правильном ответе на вопрос. Итого, если чувак попал по критериями ЦПУ и видюхи, но не прошел по памяти, то его скор будет 2, а не 3. Идеально.
В последствие маркетинг несколько раз понижал критерии отбора, и это сводилось к тому, что кто-то заходил на тайпформу и добавлял пару новых ответов в уже созданное условие.

Еще одно условие — это 🌍 region-based ключи. Регионов было всего два, что упростило задачу. Юзера спрашивали страну, и в зависимости от этого нужно было выбрать код из разных табличек. Сбор информации был в форме, а обработка уже на стороне Мейка. Я снова воспользовался переменной.
На этот раз создал новую строчную и заполнял ее в зависимости от ответа. Так как варианта было всего да, значение выставлялось только для одного региона, а второй был дефолтным.

С точки зрения предоставления информации бекенду, то тут оказалось просто. В конце опроса ТайпФорма может редиректить юзера на внешний URL. К этому урлу можно подставить любые нужные параметры, наполнив их информацией из ответов. Туда отправились имейл и платформа, которые ловил фронтенд и формировал из них запрос на бек.

Еще крутая фишка редиректов в ТайпФорме — hidden fields. Лонг стори шорт, но когда появились коды для другой платформы я просто создал новую форму и редиректил юзеров туда. Было глупо спрашивать юзера заново тот же имейл, поэтому нужно было предзаполнение. И как раз передача скрытых полей в квери к новой форме позволило определить все известные данные в новой форме.

Никаких нареканий к ТайпФорме за все время не было. Она работала быстро, ничего не потеряла. Единственный тупой минус — это плохая валидация формата имейла. Эта штука пару раз ломала мне автоматизацию в Мейке, хорошо что никто не абьюзил этот нюанс. У них есть отдельный тип вопроса для имейла, но в нем нет нормальной валидации того, чтобы юзер не указал там какую-то хрень. Их ответ на это замечание был прекрасным: "email verification, while helpful, doesn’t work 100% of the time". Лол, ну, спасибо.

Реализация формы

В конечном итоге флоу формы сократился вот до такой краткой схемы, но пока во всем не разобрались и не причесали там была полная дичь. Что-то типа этого.

ТайпФорма не очень дешевая, но и не сказать, что сильно дорогая. Максимальный лимит ответов в месяц — 50к, что может быть недостаточно для больших ланчей, поэтому придется с ними общаться про ентерпрайз тариф.

Make.com

Флоу автоматизации в Мейке называется Сценарием. В моем случае сценарий запускался по факту приходящего сообщения на вебхук. Примерно так выглядел сценарий под конец этого проекта:

Какие-то части тут уже отключены. У меня было два сценария под обе формы для разных платформ.

Особенность сценариев в Мейк в том, что, если он завершился с ошибкой, то он просто выключится. Придет имейл, что сценарий остановлен, и все. Нужно идти и вручную разруливать ошибку. Поэтому очень важно на каждый шаг добавить обработку ошибок. Как ее использовать я узнал благодаря их новому AI чату. На самом деле именно из-за этого чата я вообще осмелился выбрать эту тулзу. Раньше пришлось бы лзеть в документацию или гуглить как решить какую-то проблему со сценарием, а сейчас с этим успешно сравляется их чатбот. Он даже умеет сам строить флоу, но получается это так себе. Разве что только для примеров использовать.

Первым шагом в Мейк прилетал вебхук и он проверяли переменные. После вебхука стоит так называемый роутер, который отвечает за проверку. Он смотрел в поле переменной и если там >3, то дальше проверял вторую переменную со страной. В зависимости от второй переменной он направлял флоу либо наверх, либо вниз. Это были два абсолютно идентичных флоу, но работали по разным табличкам.
Далее выполнялся поиск по таблице, чтобы найти этот имейл в таблице. Если он уже был, то ничего делать не надо — фронтенд отобразит юзеру тот же ключ из таблицы, а имейл юзер уже получал ранее.
Поиск по таблице это одно действие, которое вернет некий результат. Проверить его на том же шаге нельзя, для этого как раз и существуют эти роутеры, которые принимают результат предыдущего шага и что-то с ним делают. Поэтому далее идет роутер, который смотрит результат поиска. Если поиск вернул не пустой результат, то отправляем сообщение в Слак, что какой-то клоун пытается получить код второй раз, и на этом работа завершается. Если же ничего не было найдено, то идем далее.
Сценарий выбирает первый не занятый код из таблицы, затем записывает к нему имейл юзера из данных, полученных с вебхука, и помечает его использованным.
Затем мы создаем контакт в Brevo, куда сразу же в проперти кладем выбранный ранее из таблички код юзера. Верхний сценарий на скрине немного костыльно учитывает, что контакт уже создан в Брево и следующим шагом дополнительно апдейтит проперти. По идее надо было сделать обработку определенной ошибки от Брево и только тогда апдейтить, но этот кейс всплыл под конец этого проекта и я уже не заморачивался.
Последним шагом отправляем письмо и репортим в Слак.

Примерно так работала выдача кодов юзерам для закрытого доступа. И на удивление процесс хорошо отработал за все время и прожил до самого конца евента. Но не обошлось и без проблем.

Проблема 1. Параллельная обработка Гугл таблиц.

Это проблема не Мейка как такового, а скорее того, что Гугл таблицы это не подходящий инструмент для таких автоматизаций. Это просто табличка, а не нормальная база данных, поэтому там нет блокировок. Соответственно выполнять какие-то манипуляции с ней можно только последовательно. По началу, когда количество ответов в форме росло, юзеры получали одинаковые коды, а записывался в табличку только последний. Благо в Мейке есть соответствующая настройка, когда можно указать сценарию выполняться последовательно.

Но такой подход значительно влияет на скорость работы. Каждый проход занимал примерно 5 сек, если нужно пройти все шаги, а выполнять мы могли их только последовательно. Пришлось добавлять костыли в виде ретраев и принудительных делеев с анимациями на фронтенде. Радует то, что в конечном итоге каждый юзер получал свой код, потому что он рано или поздно приходил ему на имейл. Но отсуствие кода при редиректе на веб уменьшало конверсию для самых ленивых.

С этим пришлось смириться, потому что процесс сохранения кодов в табличке на тот момент никто менять был не готов.

Проблема 2. Скорость.

По мимо того, что мы были ограничены последовательным операциями, по мере увеличения нагрузки и количества ответов на форме, сценарий не справлялся с нагрузкой достаточно быстро. Частично помог переход на самый высокий план, но даже на нем в пиковые моменты были постоянные задержки. Выражалось это в том, что, когда собралась очередь сообщений на вебхуке, то он не разбирал ее моментально раз за разом. Все время была какая-то пауза с тем, чтобы он выгребал новые сообщения, такое ощущение, что он ждал освобождения ресурсов. Будто под капотом там несколько сценариев разных пользователей платформы складываются в один семафор)

И это на самом деле самый большой минус всех этих сервисов, когда речь идет о серьезном их использовании, связанном с каким-никаким хайлоудом. Они резко становится слишком дорогими и бессмысленными.

Проблема 3. Баги веб интерфейса.

Как-то раз я ошибся в настройке сценария и он у меня зациклился. Интерфейс дико залагал, операция выполнялась по кругу с дикой скоростью и я не мог даже ничего сделать: ни остановить, не поправить его. Долго наблюдать как оно выжирает баланс я не стал, пришлось тупо его удалить. Хорошо догадался перед этим сделать копию, а то пришлось бы собирать весь сценарий заново.

И тут дело даже скорее не в баге, а концептуальный минус того, что ты можешь где-то наткнуться на глюк интерфейса и ничего с этим не сделаешь. А так как нормального метода потестить свои изменения там не сделано (особенно с хуками, которые не могут смотреть на два разных сценария), то такие ситуации вполне реальны.

Проблема 4. Зависимость от инструментов.

Возвращаемся к мысли о том, что контроль над ситуацией ограничен предоставленными инструментами. Например, Мейк не смог правильно разобрать массив переменных от ТайпФормы. Он мог поделить их только по типам: строка и инт, и выбирал оттуда первое значение. Я не мог обработать правильно все переменные тайпформы, если это были два инта или две строки. Может и есть какой-то воркараунд, но выглядело как баг интеграции.

Если сценарий ломается, то все стопается, и ничего не сделаешь. Если нактнешься на какой-то редкий кейс, захендлить который не будет нормального инструмента, то ты ничего с этим тоже не сделаешь. Это один из главных минусов всех этих сервисов — отсуствие контроля вне предоставленных инструментов. Но с другой стороны никто и не ожидает от этих сервисов решения всех проблем.

Еще детали про Make

Оплата в Мейк за кол-во операций. Поэтому чем проще и чище сценарий, тем дешевле. Операции можно докупать бесконечно.

На каждую функцию с таблицей был повешен хендлер остановки сценария (Break). На случай если Гугл вернет 503 или 502, а такое бывало. С этим ничего не сделаешь, кроме ретрая. В настройках сценария есть такая опция, можно указать количество ретраев. Выполнение кладется в очередь, потом ретраится. На сообщениях в Слак стоит обработчик игнора (Ignore). Если в сообщение в Слак не отправлиось, хер бы с ним, мы это просто игнорим и не блокируем очередь — ради этого ретраить весь процесс излишне.

Каждое выполнение сценария в Мейк это стейтлесс процесс. Они ничего не знают друг о друге, поэтому нужно держать это в голове, когда создаешь логику сценария.

Brevo

Повезло, что у Мейка была интеграция с этим сервисом, а то пришлось бы как-то костылить напрямую запросы в их API. Как я уже писал, при создании юзер контакта в Брево я сразу присваивал код, и он использовался в шаблоне имейла, который сдизайнили и подготовили заранее. Тут все работало складно, никаких проблем за все время не было вообще, классный сервис.

Вывод

Я убедился, что ноукод сервисы очень даже имеют право на жизнь. У них очевидно есть свои минусы, но так же и плюсы. Для временного проекта или задачи, которые не чувствительны к задержкам и не содержат комплексной логики, это прекрасный выбор. В истории о том, что люди подобным образом строят MVP продуктов, тоже можно поверить.

Я не готов полностью посчитать затраты на все это мероприятие, но учитывая что этот процесс больше уже никому не нужен и все эти подписки благополучно отключили, то эти траты можно просто назвать определенным бюджетом на подобную кампанию.

Заключение

В процессе работы я наткнулся на более дешевый аналог тайпформы — YouForm. Попробовать я его не успел.

У Гугл таблиц довольно низкие рейт лимиты, в которые легко упереться. Учтя болезненный опыт работы с Гугл табличками, для будущих подобных проектов я бы выбрал резервный метод сохранения данных. Если нужно работать с входными данными, то можно использовать любую простую облачную БД типа Dynamo на AWS. Рейт лимиты Гугла никак не пофиксить, поэтому придется дублировать данные в более доступное хранилище.
На еще одном краткосрочном проекте, где планировался большой всплеск активности на несколько дней, я предложил воспользоваться связкой CloudFlare Workers и DynamoDB. Сервис облачных функций идеально подходит для очень простого обработчика, который принимает данные и складывает их в те же Гугл таблицы и нормальную БД. Он бесконечно масштабируется, стоит копейки, а код можно вообще написать в GPT за несколько минут, не думая о его качестве. Там же рядом можно положить интерфейс поиска данных в БД для быстрого доступа любым участникам процесса. Воркеры на CF мне нравятся тем, что там сразу можно подключить домен и легко настроить различные правила защиты от ботов.
Эта штука в итоге до сих пор работает более чем отлично и потребовала пары часов работы одного человека, при этом не требуя никакого внимания после.