Faça um processo termine antes do tempo limite
Pergunta
Parece que um processo de Erlang permanecerá vivo até o tempo limite padrão de 5 segundos, mesmo que tenha terminado seu trabalho.
Eu tenho chamado Gen_Server que emite um comando para a CLI da janela que pode ser concluído em menos de 1 segundos, mas o processo aguarda 5 segundos antes de ver o resultado da operação. O que está acontecendo? É muito para ver com o tempo limite, ou pode ser outra coisa.
EDITAR Esta chamada não faz nada por 5 segundos (o tempo limite padrão!)
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;
Solução
Suponho que o sistema operacional: CMD está demorando tanto para devolver os resultados. É possível que talvez o sistema operacional: CMD esteja tendo problemas para informar quando o comando Rails é concluído e não retornar até que o processo desencadeie o tempo limite. Mas, pelo seu código, eu diria que o culpado mais provável é o sistema operacional: CMD.
O retorno contém tudo o que você espera?
Outras dicas
Você ainda não adicionou nenhuma informação sobre qual é o problema. Mas vejo outras coisas que gostaria de comentar.
DIR de trabalho atual
Você está usando file:set_cwd(Path)
Portanto, o comando iniciado herdará esse caminho. A CWD do servidor de arquivos é global. Você provavelmente não deve usá -lo no código do aplicativo. É útil para definir a CWD para onde você deseja que o Erlang Crash Dumps seja escrito etc.
Seu desejo de deixar o Rail executar com a CWD de acordo com Path
é melhor servido com algo assim:
_ ->
Response = os:cmd(string:join(["cd", Path, "&&", "Rails", Name, Args], " ")),
{reply, Response, State}
Isto é, inicie um shell para analisar a linha de comando, faça com que o shell altere a CWD e os trilhos de partida.
Bloqueando um gen_server
O Gen_Server está lá para serializar o processamento. Ou seja, processa uma mensagem após a outra. Não lida com todos eles simultaneamente. É sua razão para a existência não lidar com eles simultaneamente.
Você está (em relação a outros custos) fazendo algum cálculo muito caro no Gen_Server: Iniciando um processo externo que executa esse aplicativo Rails. É sua intenção ter no máximo um aplicativo Rails em execução a qualquer momento? (Ouvi falar de Ruby em trilhos que exigem toneladas de memória por processo, por isso pode ser uma decisão sensata).
Se você não precisar atualizar o Estado com quaisquer valores de uma chamada dispendiosa, como no seu código de exemplo, poderá usar uma chamada gen_server explícita: Responder/2.
_ ->
spawn_link(fun () -> rails_cmd(From, Path, Name, Args) end),
{no_reply, State}
E então você tem
rails_cmd(From, Path, Name, Args) ->
Response = os:cmd(string:join(["cd", Path, "&&", "Rails", Name, Args], " ")),
gen_server:reply(From, Response).