fix
This commit is contained in:
parent
c5ee4eec0a
commit
ad518db266
@ -6,7 +6,7 @@
|
|||||||
%%% @end
|
%%% @end
|
||||||
%%% Created : 02. 4月 2025 19:09
|
%%% Created : 02. 4月 2025 19:09
|
||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
-module(dimension_apn_pusher).
|
-module(dimension_apn_worker).
|
||||||
-author("anlicheng").
|
-author("anlicheng").
|
||||||
|
|
||||||
-behaviour(gen_server).
|
-behaviour(gen_server).
|
||||||
@ -14,7 +14,6 @@
|
|||||||
%% API
|
%% API
|
||||||
-export([start_link/1]).
|
-export([start_link/1]).
|
||||||
-export([push/4]).
|
-export([push/4]).
|
||||||
-export([test/1]).
|
|
||||||
|
|
||||||
%% gen_server callbacks
|
%% gen_server callbacks
|
||||||
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
|
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
|
||||||
@ -30,14 +29,9 @@
|
|||||||
%%% API
|
%%% API
|
||||||
%%%===================================================================
|
%%%===================================================================
|
||||||
|
|
||||||
test(DeviceToken) ->
|
|
||||||
Title = <<"这是一个消息通知"/utf8>>,
|
|
||||||
Body = jiffy:encode(#{<<"id">> => 1234, <<"name">> => <<"英雄第二季"/utf8>>}, [force_utf8]),
|
|
||||||
gen_server:cast(?SERVER, {push, DeviceToken, Title, Body}).
|
|
||||||
|
|
||||||
-spec push(Pid :: pid(), DeviceToken :: binary(), Title :: binary(), Body :: binary()) -> no_return().
|
-spec push(Pid :: pid(), DeviceToken :: binary(), Title :: binary(), Body :: binary()) -> no_return().
|
||||||
push(Pid, DeviceToken, Title, Body) when is_pid(Pid), is_binary(DeviceToken), is_binary(Title), is_binary(Body) ->
|
push(Pid, DeviceToken, Title, Body) when is_pid(Pid), is_binary(DeviceToken), is_binary(Title), is_binary(Body) ->
|
||||||
gen_server:cast(Pid, {push, DeviceToken, Title, Body}).
|
gen_server:call(Pid, {push, DeviceToken, Title, Body}).
|
||||||
|
|
||||||
%% @doc Spawns the server and registers the local name (unique)
|
%% @doc Spawns the server and registers the local name (unique)
|
||||||
-spec(start_link(Opts :: list()) ->
|
-spec(start_link(Opts :: list()) ->
|
||||||
@ -69,6 +63,73 @@ init([Props]) ->
|
|||||||
|
|
||||||
{ok, #state{apns_pid = ApnsPid, headers = Headers}}.
|
{ok, #state{apns_pid = ApnsPid, headers = Headers}}.
|
||||||
|
|
||||||
|
%% @private
|
||||||
|
%% @doc Handling call messages
|
||||||
|
-spec(handle_call(Request :: term(), From :: {pid(), Tag :: term()},
|
||||||
|
State :: #state{}) ->
|
||||||
|
{reply, Reply :: term(), NewState :: #state{}} |
|
||||||
|
{reply, Reply :: term(), NewState :: #state{}, timeout() | hibernate} |
|
||||||
|
{noreply, NewState :: #state{}} |
|
||||||
|
{noreply, NewState :: #state{}, timeout() | hibernate} |
|
||||||
|
{stop, Reason :: term(), Reply :: term(), NewState :: #state{}} |
|
||||||
|
{stop, Reason :: term(), NewState :: #state{}}).
|
||||||
|
handle_call({push, DeviceToken, Title, Body}, _From, State = #state{apns_pid = ApnsPid, headers = Headers}) ->
|
||||||
|
Notification = #{
|
||||||
|
aps => #{
|
||||||
|
alert => #{
|
||||||
|
title => Title,
|
||||||
|
body => Body
|
||||||
|
},
|
||||||
|
% 播放默认声音
|
||||||
|
sound => <<"default">>,
|
||||||
|
% App 图标角标
|
||||||
|
badge => 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
PushResult = apns:push_notification(ApnsPid, DeviceToken, Notification, Headers),
|
||||||
|
lager:debug("[dimension_apn_pusher] push result is: ~p", [PushResult]),
|
||||||
|
{reply, ok, State}.
|
||||||
|
|
||||||
|
%% @private
|
||||||
|
%% @doc Handling cast messages
|
||||||
|
-spec(handle_cast(Request :: term(), State :: #state{}) ->
|
||||||
|
{noreply, NewState :: #state{}} |
|
||||||
|
{noreply, NewState :: #state{}, timeout() | hibernate} |
|
||||||
|
{stop, Reason :: term(), NewState :: #state{}}).
|
||||||
|
handle_cast(_Request, State) ->
|
||||||
|
{noreply, State}.
|
||||||
|
|
||||||
|
%% @private
|
||||||
|
%% @doc Handling all non call/cast messages
|
||||||
|
-spec(handle_info(Info :: timeout() | term(), State :: #state{}) ->
|
||||||
|
{noreply, NewState :: #state{}} |
|
||||||
|
{noreply, NewState :: #state{}, timeout() | hibernate} |
|
||||||
|
{stop, Reason :: term(), NewState :: #state{}}).
|
||||||
|
handle_info(_Info, State = #state{}) ->
|
||||||
|
{noreply, State}.
|
||||||
|
|
||||||
|
%% @private
|
||||||
|
%% @doc This function is called by a gen_server when it is about to
|
||||||
|
%% terminate. It should be the opposite of Module:init/1 and do any
|
||||||
|
%% necessary cleaning up. When it returns, the gen_server terminates
|
||||||
|
%% with Reason. The return value is ignored.
|
||||||
|
-spec(terminate(Reason :: (normal | shutdown | {shutdown, term()} | term()),
|
||||||
|
State :: #state{}) -> term()).
|
||||||
|
terminate(_Reason, _State = #state{}) ->
|
||||||
|
ok.
|
||||||
|
|
||||||
|
%% @private
|
||||||
|
%% @doc Convert process state when code is changed
|
||||||
|
-spec(code_change(OldVsn :: term() | {down, term()}, State :: #state{},
|
||||||
|
Extra :: term()) ->
|
||||||
|
{ok, NewState :: #state{}} | {error, Reason :: term()}).
|
||||||
|
code_change(_OldVsn, State = #state{}, _Extra) ->
|
||||||
|
{ok, State}.
|
||||||
|
|
||||||
|
%%%===================================================================
|
||||||
|
%%% Internal functions
|
||||||
|
%%%===================================================================
|
||||||
|
|
||||||
-spec parse_headers(Headers :: list()) -> map().
|
-spec parse_headers(Headers :: list()) -> map().
|
||||||
parse_headers(Headers) ->
|
parse_headers(Headers) ->
|
||||||
parse_headers(Headers, #{}).
|
parse_headers(Headers, #{}).
|
||||||
@ -112,72 +173,4 @@ connection_opts([{type, Type}|ConnectionOpts], Acc) ->
|
|||||||
connection_opts([{timeout, Timeout}|ConnectionOpts], Acc) ->
|
connection_opts([{timeout, Timeout}|ConnectionOpts], Acc) ->
|
||||||
connection_opts(ConnectionOpts, Acc#{timeout => Timeout});
|
connection_opts(ConnectionOpts, Acc#{timeout => Timeout});
|
||||||
connection_opts([_|ConnectionOpts], Acc) ->
|
connection_opts([_|ConnectionOpts], Acc) ->
|
||||||
connection_opts(ConnectionOpts, Acc).
|
connection_opts(ConnectionOpts, Acc).
|
||||||
|
|
||||||
%% @private
|
|
||||||
%% @doc Handling call messages
|
|
||||||
-spec(handle_call(Request :: term(), From :: {pid(), Tag :: term()},
|
|
||||||
State :: #state{}) ->
|
|
||||||
{reply, Reply :: term(), NewState :: #state{}} |
|
|
||||||
{reply, Reply :: term(), NewState :: #state{}, timeout() | hibernate} |
|
|
||||||
{noreply, NewState :: #state{}} |
|
|
||||||
{noreply, NewState :: #state{}, timeout() | hibernate} |
|
|
||||||
{stop, Reason :: term(), Reply :: term(), NewState :: #state{}} |
|
|
||||||
{stop, Reason :: term(), NewState :: #state{}}).
|
|
||||||
handle_call(_Request, _From, State = #state{}) ->
|
|
||||||
{reply, ok, State}.
|
|
||||||
|
|
||||||
%% @private
|
|
||||||
%% @doc Handling cast messages
|
|
||||||
-spec(handle_cast(Request :: term(), State :: #state{}) ->
|
|
||||||
{noreply, NewState :: #state{}} |
|
|
||||||
{noreply, NewState :: #state{}, timeout() | hibernate} |
|
|
||||||
{stop, Reason :: term(), NewState :: #state{}}).
|
|
||||||
handle_cast({push, DeviceToken, Title, Body}, State = #state{apns_pid = ApnsPid, headers = Headers}) ->
|
|
||||||
Notification = #{
|
|
||||||
aps => #{
|
|
||||||
alert => #{
|
|
||||||
title => Title,
|
|
||||||
body => Body
|
|
||||||
},
|
|
||||||
% 播放默认声音
|
|
||||||
sound => <<"default">>,
|
|
||||||
% App 图标角标
|
|
||||||
badge => 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
PushResult = apns:push_notification(ApnsPid, DeviceToken, Notification, Headers),
|
|
||||||
lager:debug("[dimension_apn_pusher] push result is: ~p", [PushResult]),
|
|
||||||
|
|
||||||
{noreply, State}.
|
|
||||||
|
|
||||||
%% @private
|
|
||||||
%% @doc Handling all non call/cast messages
|
|
||||||
-spec(handle_info(Info :: timeout() | term(), State :: #state{}) ->
|
|
||||||
{noreply, NewState :: #state{}} |
|
|
||||||
{noreply, NewState :: #state{}, timeout() | hibernate} |
|
|
||||||
{stop, Reason :: term(), NewState :: #state{}}).
|
|
||||||
handle_info(_Info, State = #state{}) ->
|
|
||||||
{noreply, State}.
|
|
||||||
|
|
||||||
%% @private
|
|
||||||
%% @doc This function is called by a gen_server when it is about to
|
|
||||||
%% terminate. It should be the opposite of Module:init/1 and do any
|
|
||||||
%% necessary cleaning up. When it returns, the gen_server terminates
|
|
||||||
%% with Reason. The return value is ignored.
|
|
||||||
-spec(terminate(Reason :: (normal | shutdown | {shutdown, term()} | term()),
|
|
||||||
State :: #state{}) -> term()).
|
|
||||||
terminate(_Reason, _State = #state{}) ->
|
|
||||||
ok.
|
|
||||||
|
|
||||||
%% @private
|
|
||||||
%% @doc Convert process state when code is changed
|
|
||||||
-spec(code_change(OldVsn :: term() | {down, term()}, State :: #state{},
|
|
||||||
Extra :: term()) ->
|
|
||||||
{ok, NewState :: #state{}} | {error, Reason :: term()}).
|
|
||||||
code_change(_OldVsn, State = #state{}, _Extra) ->
|
|
||||||
{ok, State}.
|
|
||||||
|
|
||||||
%%%===================================================================
|
|
||||||
%%% Internal functions
|
|
||||||
%%%===================================================================
|
|
||||||
25
apps/dimension_apn/src/dimension_spn_pusher.erl
Normal file
25
apps/dimension_apn/src/dimension_spn_pusher.erl
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
%%%-------------------------------------------------------------------
|
||||||
|
%%% @author anlicheng
|
||||||
|
%%% @copyright (C) 2025, <COMPANY>
|
||||||
|
%%% @doc
|
||||||
|
%%%
|
||||||
|
%%% @end
|
||||||
|
%%% Created : 03. 4月 2025 15:41
|
||||||
|
%%%-------------------------------------------------------------------
|
||||||
|
-module(dimension_spn_pusher).
|
||||||
|
-author("anlicheng").
|
||||||
|
|
||||||
|
%% API
|
||||||
|
-export([push/3]).
|
||||||
|
-export([test/1]).
|
||||||
|
|
||||||
|
test(DeviceToken) ->
|
||||||
|
Title = <<"这是一个消息通知"/utf8>>,
|
||||||
|
Body = jiffy:encode(#{<<"id">> => 1234, <<"name">> => <<"英雄第二季"/utf8>>}, [force_utf8]),
|
||||||
|
push(DeviceToken, Title, Body).
|
||||||
|
|
||||||
|
-spec push(DeviceToken :: binary(), Title :: binary(), Body :: binary()) -> no_return().
|
||||||
|
push(DeviceToken, Title, Body) when is_binary(DeviceToken), is_binary(Title), is_binary(Body) ->
|
||||||
|
poolboy:transaction(apns_pool, fun(WorkerPid) ->
|
||||||
|
dimension_apn_worker:push(WorkerPid, DeviceToken, Title, Body)
|
||||||
|
end).
|
||||||
@ -12,7 +12,7 @@
|
|||||||
{pools, [
|
{pools, [
|
||||||
%% 推送设置
|
%% 推送设置
|
||||||
{apns_pool,
|
{apns_pool,
|
||||||
[{size, 1}, {max_overflow, 1}, {worker_module, dimension_apn_pusher}],
|
[{size, 1}, {max_overflow, 1}, {worker_module, dimension_apn_worker}],
|
||||||
[
|
[
|
||||||
{connection_opts, [
|
{connection_opts, [
|
||||||
{apple_host, "api.sandbox.push.apple.com"},
|
{apple_host, "api.sandbox.push.apple.com"},
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user