summaryrefslogtreecommitdiff
path: root/src/ejabberd_redis.erl
diff options
context:
space:
mode:
authorEvgeniy Khramtsov <ekhramtsov@process-one.net>2017-02-24 12:05:47 +0300
committerEvgeniy Khramtsov <ekhramtsov@process-one.net>2017-02-24 12:05:47 +0300
commit67d6ca9f101ef5577468e32c730fa8341df2e080 (patch)
treec89c3d21058a25a5d6313ccc759a2200d8245088 /src/ejabberd_redis.erl
parentFix a case clause and run c2s_filter_send on send_error/3 (diff)
Improve startup procedure
Diffstat (limited to 'src/ejabberd_redis.erl')
-rw-r--r--src/ejabberd_redis.erl77
1 files changed, 42 insertions, 35 deletions
diff --git a/src/ejabberd_redis.erl b/src/ejabberd_redis.erl
index 6a853737..f349baac 100644
--- a/src/ejabberd_redis.erl
+++ b/src/ejabberd_redis.erl
@@ -28,7 +28,7 @@
-behaviour(ejabberd_config).
%% API
--export([start/0, stop/0, start_link/0, q/1, qp/1, host_up/1, opt_type/1]).
+-export([start_link/0, q/1, qp/1, config_reloaded/0, opt_type/1]).
%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
@@ -40,7 +40,7 @@
-include("logger.hrl").
-include("ejabberd.hrl").
--record(state, {}).
+-record(state, {connection :: {pid(), reference()} | undefined}).
%%%===================================================================
%%% API
@@ -48,19 +48,6 @@
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
-start() ->
- ejabberd_hooks:add(config_reloaded, ?MODULE, start, 20),
- ejabberd_hooks:add(host_up, ?MODULE, host_up, 20),
- case lists:any(
- fun(Host) ->
- is_redis_configured(Host)
- end, ?MYHOSTS) of
- true ->
- do_start();
- false ->
- stop()
- end.
-
q(Command) ->
try eredis:q(?PROCNAME, Command)
catch _:Reason -> {error, Reason}
@@ -71,22 +58,21 @@ qp(Pipeline) ->
catch _:Reason -> {error, Reason}
end.
-stop() ->
- supervisor:terminate_child(ejabberd_sup, ?MODULE),
- supervisor:delete_child(ejabberd_sup, ?MODULE).
-
-host_up(Host) ->
- case is_redis_configured(Host) of
- true -> do_start();
- false -> ok
+config_reloaded() ->
+ case is_redis_configured() of
+ true ->
+ ?MODULE ! connect;
+ false ->
+ ?MODULE ! disconnect
end.
%%%===================================================================
%%% gen_server callbacks
%%%===================================================================
init([]) ->
+ ejabberd_hooks:add(config_reloaded, ?MODULE, config_reloaded, 20),
process_flag(trap_exit, true),
- connect(),
+ self() ! connect,
{ok, #state{}}.
handle_call(_Request, _From, State) ->
@@ -96,13 +82,35 @@ handle_call(_Request, _From, State) ->
handle_cast(_Msg, State) ->
{noreply, State}.
+handle_info(connect, #state{connection = undefined} = State) ->
+ NewState = case is_redis_configured() of
+ true ->
+ case connect() of
+ {ok, Connection} ->
+ State#state{connection = Connection};
+ {error, _} ->
+ State
+ end;
+ false ->
+ State
+ end,
+ {noreply, NewState};
handle_info(connect, State) ->
- connect(),
+ %% Already connected
{noreply, State};
-handle_info({'DOWN', _MRef, _Type, _Pid, Reason}, State) ->
+handle_info(disconnect, #state{connection = {Pid, MRef}} = State) ->
+ ?INFO_MSG("Disconnecting from Redis server", []),
+ erlang:demonitor(MRef, [flush]),
+ eredis:stop(Pid),
+ {noreply, State#state{connection = undefined}};
+handle_info(disconnect, State) ->
+ %% Not connected
+ {noreply, State};
+handle_info({'DOWN', MRef, _Type, Pid, Reason},
+ #state{connection = {Pid, MRef}} = State) ->
?INFO_MSG("Redis connection has failed: ~p", [Reason]),
connect(),
- {noreply, State};
+ {noreply, State#state{connection = undefined}};
handle_info({'EXIT', _, _}, State) ->
{noreply, State};
handle_info(Info, State) ->
@@ -110,7 +118,7 @@ handle_info(Info, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
- ok.
+ ejabberd_hooks:delete(config_reloaded, ?MODULE, config_reloaded, 20).
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
@@ -118,10 +126,8 @@ code_change(_OldVsn, State, _Extra) ->
%%%===================================================================
%%% Internal functions
%%%===================================================================
-do_start() ->
- Spec = {?MODULE, {?MODULE, start_link, []},
- permanent, 5000, worker, [?MODULE]},
- supervisor:start_child(ejabberd_sup, Spec).
+is_redis_configured() ->
+ lists:any(fun is_redis_configured/1, ?MYHOSTS).
is_redis_configured(Host) ->
ServerConfigured = ejabberd_config:has_option({redis_server, Host}),
@@ -181,9 +187,9 @@ connect() ->
{ok, Client} ->
?INFO_MSG("Connected to Redis at ~s:~p", [Server, Port]),
unlink(Client),
- erlang:monitor(process, Client),
+ MRef = erlang:monitor(process, Client),
register(?PROCNAME, Client),
- {ok, Client};
+ {ok, {Client, MRef}};
{error, Why} ->
erlang:error(Why)
end
@@ -192,7 +198,8 @@ connect() ->
?ERROR_MSG("Redis connection at ~s:~p has failed: ~p; "
"reconnecting in ~p seconds",
[Server, Port, Reason, Timeout]),
- erlang:send_after(timer:seconds(Timeout), self(), connect)
+ erlang:send_after(timer:seconds(Timeout), self(), connect),
+ {error, Reason}
end.
opt_type(redis_connect_timeout) ->