我想编写一个模块,需要能够在Erlang中将消息推送到pusher。我发现这个仓库https://github.com/bradfordw/pusherl已经不再维护了,但我认为我可以适应它。我跟着README,我成功运行了所有的Rebar命令。然后我通过命令
打开钢筋控制台./rel/pusherl/bin/pusherl console
所以服务器应该启动。但是当我试着打电话时
gen_server:call(pusherl_server, {push, {"ChannelName", "EventName", "Payload"}}).
然后它抛出错误:
exception exit: {noproc,{gen_server,call,
[pusherl_server,
{push,
{"ChannelName","EventName","Payload"}}]}}
in function gen_server:call/2 (gen_server.erl, line 182)
我对Erlang和OTP很新,我花了一半的时间让它工作但没有成功。请帮我解决这个问题。我真的很感激。
顺便说一句,如果您认识任何其他推送客户,请建议我。非常感谢。
以下是gen_server回调的代码:
-module(pusherl_server).
-behaviour(gen_server).
-define(SERVER, ?MODULE).
-define(JP, fun(K,V) -> string:join([K,V],"=") end).
-record(state,{app_id, key, secret}).
-export([start_link/0]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
start_link() ->
gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
init(_) ->
{ok, PusherAppId} = application:get_env(pusher_app_id),
{ok, PusherKey} = application:get_env(pusher_key),
{ok, PusherSecret} = application:get_env(pusher_secret),
{ok, #state{app_id=PusherAppId, key=PusherKey, secret=PusherSecret}}.
handle_call({push, {ChannelName, EventName, Payload}}, _From, State) ->
case http_request(ChannelName, EventName, Payload, State) of
{ok, _} -> {reply, ok, State};
{error, _} -> {reply, error, State}
end;
handle_call(_Request, _From, State) ->
{noreply, ok, State}.
handle_cast({push, {ChannelName, EventName, Payload}}, State) ->
case http_request(ChannelName, EventName, Payload, State) of
{ok, _} -> {noreply, ok, State};
{error, _} -> {noreply, error, State}
end;
handle_cast(_Msg, State) ->
{noreply, State}.
handle_info(_Info, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
http_request(ChannelName, EventName, Payload, Config) when is_list(ChannelName), is_record(Config, state) ->
{ok, ReqProps} = http_request_props(Payload, EventName, ChannelName, Config),
httpc:request(post, ReqProps, [], []).
http_request_props(Payload, EventName, ChannelName, #state{app_id=AppId, key=AppKey, secret=AppSecret}) ->
Md5String = lists:flatten([io_lib:format("~2.16.0b",[N]) || <<N>> <= crypto:md5(Payload)]),
ToSign = ["POST",
lists:flatten(["/apps/", AppId, "/channels/", ChannelName, "/events"]),
string:join([?JP("auth_key", AppKey),
?JP("auth_timestamp", get_time_as_string()),
?JP("auth_version", "1.0"),
?JP("body_md5", Md5String),
?JP("name", EventName)
],"&")
],
AuthSignature = signed_params(ToSign, AppSecret),
QueryParams = [
?JP("auth_key", AppKey),
?JP("auth_timestamp", get_time_as_string()),
?JP("auth_version","1.0"),
?JP("body_md5", Md5String),
?JP("auth_signature", AuthSignature),
?JP("name", EventName)
],
Url = http_api_url(AppId, ChannelName, QueryParams),
{ok, {Url, [], "application/x-www-form-urlencoded", Payload}}.
http_api_url(AppId, ChannelName, QueryParams) ->
QueryString = string:join(QueryParams,"&"),
lists:flatten(["http://api.pusherapp.com/apps/",AppId,"/channels/",ChannelName,"/events?", QueryString]).
get_time_as_string() ->
{M, S, _} = now(),
integer_to_list(((M * 1000000) + S)).
signed_params(Params, Secret) ->
lists:flatten([io_lib:format("~2.16.0b",[N]) || <<N:8>> <= sha2:hmac_sha256(Secret, string:join(Params,"\n"))]).
答案 0 :(得分:0)
noproc
表示您尝试调用的进程未运行。你需要用:
pusherl_server:start_link().
请注意,这会将pusherl_server
进程链接到调用进程。如果您在shell中运行它,然后执行导致错误的操作,则错误将通过链接传播到pusherl_server
进程并将其终止,因此您必须再次启动它。
为避免这种情况,您可以在启动后取消链接:
{ok, Pid} = pusherl_server:start_link().
unlink(Pid).
或向模块添加start
功能,与start_link
的功能相同,只是它调用gen_server:start
而不是gen_server:start_link
。