#erlang #erlang-otp
#erlang #erlang-otp
Вопрос:
Кажется, что процесс erlang будет работать до истечения тайм-аута по умолчанию в 5 секунд, даже если он завершил свою работу.
У меня есть вызов gen_server, который выдает команду командной строке window CLI, которая может быть завершена менее чем за 1 секунду, но процесс ожидает 5 секунд, прежде чем я увижу результат операции. Что происходит? это как-то связано с временем ожидания, или это может быть что-то другое.
РЕДАКТИРОВАТЬ Этот вызов ничего не делает в течение 5 секунд (время ожидания по умолчанию!)
handle_call({create_app, Path, Name, Args}, _From, State) ->
case filelib:ensure_dir(Path) of
{error, Reason} ->
{reply, Reason, State};
_ ->
file:set_cwd(Path),
Response = os:cmd(string:join(["Rails", Name, Args], " ")),
{reply, Response, State}
end;
Комментарии:
1. Не могли бы вы опубликовать какой-нибудь пример кода, демонстрирующий проблему?
2. Убедитесь, что запущен sasl (application:start (sasl)), чтобы получать правильные отчеты об ошибках.
Ответ №1:
Я предполагаю, что os: cmd занимает столько времени, чтобы вернуть результаты. Возможно, у os: cmd возникают проблемы с определением того, когда команда rails завершена, и она не возвращается до тех пор, пока процесс не запустит время ожидания. Но из вашего кода я бы сказал, что наиболее вероятным виновником является вызов os: cmd.
Содержит ли возврат все, что вы ожидаете от него?
Комментарии:
1. Да, результат — это именно то, что я ожидал (список созданных файлов), и я согласен, что это должен быть вызов os: cmd, поскольку ванильный процесс возвращается почти мгновенно. Я думаю, вы ответили на мой вопрос, и я был довольно глуп. Я думаю, что именно это делает для вас изучение нового языка, когда вы не спите до 3 часов ночи. Но вы учитесь на своих ошибках, и я многому учусь благодаря ответам ваших парней, спасибо
2. нет проблем. Я совершил свою долю глупых ошибок, поверьте мне. Как вы сказали, это часть того, как мы учимся.
Ответ №2:
Вы по-прежнему не добавили никакой информации о том, в чем проблема. Но я вижу некоторые другие вещи, которые я хотел бы прокомментировать.
Текущий рабочий каталог
Вы используете file:set_cwd(Path)
, поэтому запущенная команда унаследует этот путь. cwd файлового сервера является глобальным. Вероятно, вам вообще не следует использовать его в коде приложения. Это полезно для настройки cwd на то, куда вы хотите записывать аварийные дампы erlang и т.д.
Ваше желание разрешить rail выполняться с cwd в соответствии с Path
лучше удовлетворить чем-то вроде этого:
_ ->
Response = os:cmd(string:join(["cd", Path, "amp;amp;", "Rails", Name, Args], " ")),
{reply, Response, State}
То есть запустите оболочку для анализа командной строки, измените cwd оболочки и запустите Rails.
Блокировка gen_server
gen_server предназначен для сериализации обработки. То есть он обрабатывает одно сообщение за другим. Он не обрабатывает их все одновременно. Причина его существования заключается в том, чтобы не обрабатывать их одновременно.
Вы (в связи с другими затратами) выполняете некоторые очень дорогостоящие вычисления на gen_server: запускаете внешний процесс, который запускает это приложение rails. Собираетесь ли вы запускать не более одного приложения rails одновременно? (Я слышал о ruby on rails, требующем тонны памяти для каждого процесса, так что это может быть разумным решением).
Если вам не нужно обновлять состояние какими-либо значениями из дорогостоящего вызова, как в вашем примере кода, то вы можете использовать явный вызов gen_server:reply /2.
_ ->
spawn_link(fun () -> rails_cmd(From, Path, Name, Args) end),
{no_reply, State}
И тогда у вас есть
rails_cmd(From, Path, Name, Args) ->
Response = os:cmd(string:join(["cd", Path, "amp;amp;", "Rails", Name, Args], " ")),
gen_server:reply(From, Response).
Комментарии:
1. Спасибо за ваш ответ, это очень помогло мне в процессе изучения erlang. Тем не менее, я попробовал ваше предложение использовать gen_server:reply / 2, и, похоже, это не дало мне ничего другого. Я не понимаю цели. Я очень рад, что это действие выполняется синхронно (я хочу дождаться его завершения, прежде чем делать что-либо еще), но, похоже, возврат занимает больше времени, чем фактическое действие Rails.
2. Мне кажется, что действие Rails выполняется, скажем, в течение 2 секунд, но я не вижу результатов до истечения времени ожидания gen_server через 5 секунд. Правильно ли я понимаю, что время ожидания по умолчанию составляет 5 секунд? Извините, если я веду себя глупо, но я начал изучать erlang всего 3 дня назад и ценю всю помощь, которую я могу получить.
3. Я не уверен, что ошибка erlang в том, что вы не видите результат быстрее. Тайм-ауты не должны приводить к тому, что возврат процесса erlang занимает больше времени. Я бы предположил, что ваша команда rails занимает больше времени или результат команды rails возвращается erlang дольше. Вы пробовали запускать ванильный процесс, который просто возвращает, ничего не делая? Держу пари, тогда у вас не будет замедления.
4. Черт! вы правы, это ошибка Rails, 5-секундная вещь сбила меня с толку