Сон не для всех… и не для каждого сценария

Когда я пишу это, я не спал около 36 часов — достаточно, чтобы понять важность сна. Тем не менее, это обсуждение касается того, как заставить скрипт bash или JavaScript на NodeJS заснуть на определенное время.

#!/usr/bin/env bash
echo "Feeling drowsy...";
sleep 10;
echo "Woof! Back up after 10 seconds!";

Команда sleep в unix позволяет приостановить выполнение скрипта на указанное время. Это очень удобный инструмент, когда скрипту нужно дождаться завершения какой-то другой асинхронной работы. (детский сад говорит за многих!)

Что за суета?

В моем случае я работал над созданием скрипта, который запускает сервер SailsJS и запускает проверку работоспособности API сервера с помощью Newman. Сервер должен был быть запущен как демон, чтобы мы могли запустить сервер, а затем выполнить команду для запуска тестов. pm2 или foreverjs — хорошие инструменты для демонизации серверов NodeJS.

#!/usr/bin/env bash
echo "Starting server...";
pm2 start app.js;
echo "Running tests...";
newman -x -y 10 -c test/sanity.json.postman_collection;
echo "Stopping server...";
pm2 stop app.js;

Вышеприведенный скрипт может показаться прекрасным, но на самом деле никакие тесты не выполняются. Причина проста: серверам SailsJS часто требуется добрых 10 секунд, чтобы выполнить все сценарии инициализации и начать работу. pm2 инициирует запуск сервера и сразу же переходит к выполнению тестов Ньюмана, и за это время сервер еще не готов принимать запросы API.

Прогноз: заставьте скрипт заснуть на несколько секунд перед выполнением тестов Ньюмана. Мы уже знаем, как это сделать :-)

К сожалению, это не простое решение, которое действительно решит проблему. Виновников довольно много

  • Если в ваших bash-скриптах есть команда SLEEP, она не будет работать в ряде сервисов непрерывной интеграции, таких как Shippable, Travis-CI и т. д. Во всех этих сервисах есть другой способ приостановить выполнение с помощью конфигурации варианты — но это нежизнеспособный вариант, если вы собираетесь иметь общий сценарий как для локального тестирования, так и для тестирования CI. (Хорошая практика.)
  • Он не работает в командной строке Windows® (что делает?)

Решение

Вместо команды sleep мы могли бы написать строку кода JavaScript, которая запускает бесконечный цикл до тех пор, пока не будет достигнуто указанное время. Мы могли бы использовать параметр -e узла, чтобы передать строку сценария для выполнения. Аккуратный! (Это?)

node -e "n=Date.now;s=n();while(n()-s<5000);"; # 5 seconds delay

or

node -e "setTimeout(null,5000)"; # 5 seconds delay

Я решил упростить ситуацию, опубликовав это как модуль под названием sleep-ms, который предоставил бы команду CLI, чтобы сделать то же самое, что и выше. Поскольку я уже запускал скрипт на системах с Node, добавить дополнительный глобальный модуль не составило труда.



При этом приведенный выше код изменяется и становится совместимым между локальными и ограниченными системами.

#!/usr/bin/env bash
echo "Starting server...";
pm2 start app.js;
echo "Waiting 5 seconds to complete server boot...";
sleepms 5000;
echo "Running tests...";
newman -x -y 10 -c test/sanity.json.postman_collection;
echo "Stopping server...";
pm2 stop app.js;

Обложка баннера предоставлена: buzzfarmers
Первоначально опубликовано на shamasis.net