Свои скрипты на Python

«Скрипты» — дополнение для случаев, когда готовых возможностей не хватило: забрать данные из внешней системы, отправить их куда нужно, посчитать что-то по-своему. Скрипт — это небольшой самостоятельный код на языке Python, который живёт рядом с данными продукта, включается и выключается по надобности и оставляет запись о каждом прогоне.

Зачем свой код

У продукта широкий набор готовых действий, но жизнь изобретательна: у одного заказчика складской учёт остался в старой системе, у другого цены считаются в таблице на общем диске, третьему нужно каждую ночь сверять клиентов с внешним сервисом. Писать отдельную возможность в самом продукте под каждый такой случай — долго, а иногда и просто невозможно предугадать заранее. Скрипты закрывают эту нишу: свой код пишет ваш инженер или ИИ-агент, а продукт берёт на себя запуск, доступы, журнал и ограничения.

Где живёт описание скрипта

Описание скрипта лежит в дереве настроек рядом с данными продукта: отдельный файл на каждый скрипт, а имя файла и есть имя скрипта. Рядом лежит файл настроек самого раздела: общий выключатель скриптов, время ожидания по умолчанию, число одновременных прогонов и срок хранения журнала. Всё это — обычные настройки, которые попадают в общую историю правок вместе с остальными данными продукта, так что видно, кто и когда что менял.

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

Если скриптам нужны сторонние библиотеки, их список лежит в той же папке, а продукт один раз установит их в общее окружение, которым пользуются все скрипты. Отдельного набора библиотек на каждый скрипт не бывает — это осознанное упрощение: так проще обновлять и не держать десяток разных окружений.

Четыре точки подключения

Один и тот же скрипт можно использовать четырьмя способами:

  • По расписанию. В описании указывается «каждые N минут». Продукт сам следит, что пора запускать, не запускает один и тот же скрипт дважды одновременно и не сбивается, если один прогон оказался неудачным: расписание остаётся, следующий запуск придёт в свой срок.
  • Вручную. Кнопка «Запустить скрипт» — для проверки и разовых задач. Что происходило при последних запусках, видно тут же, в консоли скриптов.
  • На приём внешних данных. У скрипта может быть защищённый адрес, по которому внешняя система присылает данные, предъявляя секретный ключ. Так любой внешний сервис — сайт, складская программа, платёжка — может отдавать события прямо в продукт, без доработки самого продукта. Ключ хранится в скрытом виде и обратно не показывается; чужая попытка без ключа получает отказ и не запускает ничего. Есть и защита от вала обращений: слишком частые запросы притормаживаются.
  • Шагом автоматизации. В правиле или процессе появляется действие «запустить скрипт» с указанием имени и параметров. Если указано несуществующее имя, правило просто не сохранится — продукт назовёт его. Если шаг не удался, причина будет видна в журнале шага.

Что видит скрипт и что он возвращает

У скрипта простой договор с продуктом. На вход он получает описание того, что произошло: из какой точки подключения запущен, по какой причине (по расписанию, вручную, по внешнему обращению, шагом автоматизации), о какой записи идёт речь и какие данные пришли вместе с событием. Отвечает скрипт одним ответом в оговорённом формате, а всё, что он печатал по дороге для собственной отладки, продукт просто игнорирует.

Для своих нужд — запомнить, на чём остановились, сохранить промежуточный файл — у каждого скрипта есть своя рабочая папка, содержимое которой сохраняется между запусками.

Переменные окружения скрипт видит только свои: те, что перечислены в его описании. Ключ управления продуктом, пароли и адрес хранилища данных скрипту недоступны — он получает ровно то, что ему выписали. Значения секретных переменных на чтение заменяются звёздочками: посмотреть секрет через описание нельзя, а записать поверх него случайную пустоту не получится.

Журнал и ограничения

Каждый прогон оставляет ровно одну запись в журнале — даже если скрипт упал насмерть. Видно: имя скрипта, точка подключения, причина запуска, время начала и длительность, чем закончилось, код возврата и причину ошибки. Аварийные случаи различимы по виду: скрипты выключены, недоступен Python, превышено время, ошибка в коде, недопустимый ответ, слишком большой объём данных. Журнал хранится 30 дней по умолчанию, срок настраивается.

Ограничения — тоже видимые числа:

  • Время одного прогона — минута по умолчанию, до десяти минут максимум; если скрипт завис, он и все запущенные им процессы снимаются принудительно.
  • Одновременных прогонов — два по умолчанию: скрипты не могут занять все силы сервера.
  • Объём данных на входе и в ответе — до одного мегабайта; всё, что больше, отклоняется с понятной причиной, а не обрезается молча.
  • Общий выключатель — одна настройка гасит все скрипты сразу. Тогда прогон честно запишет «отключено», а не сделает вид, что всё хорошо.

Границы доверия

Скажем прямо: песочницы нет. Скрипт выполняется с правами самого продукта — он видит те же файлы и имеет тот же доступ к сети, что и сервер, на котором всё работает. Это осознанный выбор: код считается доверенным, его пишет ваш инженер или агент, и он лежит в дереве настроек рядом с данными, то есть попадает в общую историю правок.

Из этого следуют простые правила:

  • запускать стоит только те скрипты, в которых вы уверены, как в собственном коде;
  • поддерживается только Python — другой язык не подойдёт;
  • ссылки на файлы с кодом разрешены только внутри папки скриптов — выйти из неё нельзя;
  • секреты из описания продукт не показывает обратно и не сохраняет в журналах;
  • если нужна настоящая изоляция, запускайте скрипты на отдельном экземпляре продукта.

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

Дальше → Управление агентом по API

← Оглавление документации