fix micro service

This commit is contained in:
anlicheng 2025-04-30 14:51:43 +08:00
parent af2891724d
commit d713c32899

View File

@ -13,6 +13,10 @@
-behaviour(gen_server). -behaviour(gen_server).
%%
-define(STATUS_STOPPED, stopped).
-define(STATUS_RUNNING, running).
%% API %% API
-export([start_link/2]). -export([start_link/2]).
-export([get_name/1, get_pid/1, start_service/1, stop_service/1, attach_channel/2]). -export([get_name/1, get_pid/1, start_service/1, stop_service/1, attach_channel/2]).
@ -25,7 +29,9 @@
%% id信息 %% id信息
channel_pid :: pid() | undefined, channel_pid :: pid() | undefined,
%% port信息, OSPid = erlang:port_info(Port, os_pid) %% port信息, OSPid = erlang:port_info(Port, os_pid)
port :: undefined | port() port :: undefined | port(),
%%
running_status = ?STATUS_STOPPED
}). }).
%%%=================================================================== %%%===================================================================
@ -44,9 +50,11 @@ get_pid(ServiceId) when is_binary(ServiceId) ->
attach_channel(Pid, ChannelPid) when is_pid(Pid), is_pid(ChannelPid) -> attach_channel(Pid, ChannelPid) when is_pid(Pid), is_pid(ChannelPid) ->
gen_server:call(Pid, {attach_channel, ChannelPid}). gen_server:call(Pid, {attach_channel, ChannelPid}).
-spec start_service(Pid :: pid()) -> ok | {error, Reason :: binary()}.
start_service(Pid) when is_pid(Pid) -> start_service(Pid) when is_pid(Pid) ->
gen_server:call(Pid, start_service). gen_server:call(Pid, start_service).
-spec stop_service(Pid :: pid()) -> ok | {error, Reason :: binary()}.
stop_service(Pid) when is_pid(Pid) -> stop_service(Pid) when is_pid(Pid) ->
gen_server:call(Pid, stop_service). gen_server:call(Pid, stop_service).
@ -65,9 +73,11 @@ start_link(Name, Service = #micro_service{}) when is_atom(Name) ->
-spec(init(Args :: term()) -> -spec(init(Args :: term()) ->
{ok, State :: #state{}} | {ok, State :: #state{}, timeout() | hibernate} | {ok, State :: #state{}} | {ok, State :: #state{}, timeout() | hibernate} |
{stop, Reason :: term()} | ignore). {stop, Reason :: term()} | ignore).
init([Service]) -> init([Service = #micro_service{status = Status}]) ->
erlang:start_timer(0, self(), boot_service), %% 2
{ok, #state{service = Service}}. Status == 1 andalso erlang:start_timer(0, self(), boot_service),
{ok, #state{service = Service, running_status = ?STATUS_STOPPED}}.
%% @private %% @private
%% @doc Handling call messages %% @doc Handling call messages
@ -91,19 +101,32 @@ handle_call({attach_channel, ChannelPid}, _From, State = #state{channel_pid = Ol
{reply, {error, <<"serivce stopped">>}, State} {reply, {error, <<"serivce stopped">>}, State}
end; end;
%% %% :
handle_call(start_service, _From, State = #state{service = Service = #micro_service{service_id = ServiceId}}) -> handle_call(start_service, _From, State = #state{running_status = RunningStatus, port = Port, service = Service = #micro_service{service_id = ServiceId}}) ->
%%
RunningStatus == ?STATUS_RUNNING andalso stop_port(Port),
%% %%
ok = micro_service_model:start_service(ServiceId), ok = micro_service_model:start_service(ServiceId),
%% %%
erlang:start_timer(0, self(), boot_service), case boot_service(Service) of
{reply, ok, State#state{service = Service#micro_service{status = 1}}}; {ok, Port} ->
{reply, ok, State#state{running_status = ?STATUS_RUNNING, port = Port, service = Service#micro_service{status = 1}}};
{error, Reason} ->
%%
{reply, {error, Reason}, State#state{running_status = ?STATUS_STOPPED}}
end;
%% %%
handle_call(stop_service, _From, State = #state{port = Port, service = Service = #micro_service{service_id = ServiceId}}) -> handle_call(stop_service, _From, State = #state{running_status = RunningStatus, port = Port, service = Service = #micro_service{service_id = ServiceId}}) ->
case RunningStatus of
?STATUS_STOPPED ->
{reply, {error, <<"service not running">>}, State};
?STATUS_RUNNING ->
ok = micro_service_model:stop_service(ServiceId), ok = micro_service_model:stop_service(ServiceId),
stop_port(Port), stop_port(Port),
{reply, ok, State#state{port = undefined, service = Service#micro_service{status = 0}}}; {reply, ok, State#state{port = undefined, service = Service#micro_service{status = 0}}}
end;
handle_call(_Request, _From, State = #state{}) -> handle_call(_Request, _From, State = #state{}) ->
{reply, ok, State}. {reply, ok, State}.
@ -129,20 +152,25 @@ handle_info({timeout, _, boot_service}, State = #state{service = #micro_service{
handle_info({timeout, _, boot_service}, State = #state{service = Service = #micro_service{service_id = ServiceId, status = 1}}) -> handle_info({timeout, _, boot_service}, State = #state{service = Service = #micro_service{service_id = ServiceId, status = 1}}) ->
case boot_service(Service) of case boot_service(Service) of
{ok, Port} -> {ok, Port} ->
{noreply, State#state{port = Port}}; {noreply, State#state{running_status = ?STATUS_RUNNING, port = Port}};
{error, Reason} -> {error, Reason} ->
lager:debug("[efka_micro_service] service: ~p, boot_service get error: ~p", [ServiceId, Reason]), lager:debug("[efka_micro_service] service: ~p, boot_service get error: ~p", [ServiceId, Reason]),
{noreply, State} {noreply, State#state{running_status = ?STATUS_STOPPED}}
end; end;
handle_info({Port, {data, Data}}, State = #state{port = Port, service = Service}) -> handle_info({Port, {data, Data}}, State = #state{port = Port, service = Service}) ->
lager:debug("[efka_micro_service] service_id: ~p, port data: ~p", [Service#micro_service.service_id, Data]), lager:debug("[efka_micro_service] service_id: ~p, port data: ~p", [Service#micro_service.service_id, Data]),
{noreply, State}; {noreply, State};
%% port的消息 %% port的消息, Port的被动关闭会触发Port和State.port的值是相等的
handle_info({Port, {exit_status, Code}}, State = #state{port = Port, service = Service}) -> handle_info({Port, {exit_status, Code}}, State = #state{port = Port, service = Service}) ->
lager:debug("[efka_micro_service] service_id: ~p, port exit with code: ~p", [Service#micro_service.service_id, Code]), lager:debug("[efka_micro_service] service_id: ~p, port exit with code: ~p", [Service#micro_service.service_id, Code]),
erlang:start_timer(5000, self(), boot_service), erlang:start_timer(5000, self(), boot_service),
{noreply, State#state{port = undefined}};
%% port
handle_info({Port, {exit_status, Code}}, State = #state{service = Service}) when is_port(Port) ->
lager:debug("[efka_micro_service] service_id: ~p, port close with code: ~p", [Service#micro_service.service_id, Code]),
{noreply, State#state{port = undefined}}. {noreply, State#state{port = undefined}}.
%% @private %% @private