سؤال

أحتاج إلى الاحتفاظ بعملية Gen_mod أثناء حلقها كل دقيقة وتفعل بعض التنظيف. ولكن مرة واحدة كل بضعة أيام سوف تعطل وسأضطر إلى البدء مرة أخرى يدويًا مرة أخرى.

يمكنني استخدام مثال أساسي لتنفيذ المشرف في ejabberd_sup حتى يتمكن من الاستمرار. أنا أكافح لفهم الأمثلة التي تستخدم Gen_Server.

شكرا للمساعدة.

هل كانت مفيدة؟

المحلول

إليك وحدة مثال تجمع بين Ejabberd's gen_mod و OTP gen_server. التفسير مضمّن في الكود.

-module(cleaner).

-behaviour(gen_server).
-behaviour(gen_mod).

%% gen_mod requires these exports
-export([start/2, stop/1]).

%% these are exports for gen_server
-export([start_link/0]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
         terminate/2, code_change/3]).

-define(INTERVAL, timer:minutes(1)).

-record(state, {}).

%% ejabberd calls this function when this module is loaded
%% basically it adds gen_server defined by this module to 
%% ejabberd main supervisor
start(Host, Opts) ->
    Proc = gen_mod:get_module_proc(Host, ?MODULE),
    ChildSpec = {Proc,
                 {?MODULE, start_link, [Host, Opts]},
                 permanent,
                 1000,
                 worker,
                 [?MODULE]},
    supervisor:start_child(ejabberd_sup, ChildSpec).

%% this is called by ejabberd when module is unloaded, so it
%% does the opposite of start/2 :)
stop(Host) ->
    Proc = gen_mod:get_module_proc(Host, ?MODULE),
    supervisor:terminate_child(ejabberd_sup, Proc),
    supervisor:delete_child(ejabberd_sup, Proc).

%% it will be called by supervisor when it is time to start
%% this gen_server under control of supervisor
start_link(_Host, _Opts) ->
    gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).

%% it is an initialization function for gen_server
%% it starts a timer, which sends 'tick' message periodically to itself
init(_) ->
    timer:send_interval(?INTERVAL, self(), tick),
    {ok, #state{}}.

handle_call(_Request, _From, State) ->
    Reply = ok,
    {reply, Reply, State}.

handle_cast(_Msg, State) ->
    {noreply, State}.

%% this function is called whenever gen_server receives a 'tick' message
handle_info(tick, State) ->
    State2 = do_cleanup(State),
    {noreply, State2};

handle_info(_Info, State) ->
    {noreply, State}.

terminate(_Reason, _State) ->
    ok.

code_change(_OldVsn, State, _Extra) ->
    {ok, State}.


%% this function is called by handle_info/2 when tick message is received
%% so put all cleanup code here
do_cleanup(State) ->
    %% do all cleanup work here
    State.

منشور المدونة هذا يعطي شرحًا جيدًا كيف يعمل Gen_Servers. بالطبع تأكد من إعادة قراءة مبادئ تصميم OTP على gen_server و على مشرف.

يوصف تطوير وحدة Ejabberd هنا

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top