%%%------------------------------------------------------------------- %%% @author anlicheng %%% @copyright (C) 2025, %%% @doc %%% %%% @end %%% Created : 27. 8月 2025 15:22 %%%------------------------------------------------------------------- -module(gen_channel). -author("anlicheng"). -include("efka_service.hrl"). -export([register/2]). -export([push_config/4, invoke/4, channel_reply/3]). -export([next_packet_id/1]). -export([json_result/2, json_error/3]). %%%=================================================================== %%% API %%%=================================================================== -spec push_config(ChannelPid :: pid(), Ref :: reference(), ReceiverPid :: pid(), ConfigJson :: binary()) -> no_return(). push_config(ChannelPid, Ref, ReceiverPid, ConfigJson) when is_pid(ChannelPid), is_pid(ReceiverPid), is_binary(ConfigJson), is_reference(Ref) -> ChannelPid ! {push_config, Ref, ReceiverPid, ConfigJson}. -spec invoke(ChannelPid :: pid(), Ref :: reference(), ReceiverPid :: pid(), Payload :: binary()) -> no_return(). invoke(ChannelPid, Ref, ReceiverPid, Payload) when is_pid(ChannelPid), is_pid(ReceiverPid), is_binary(Payload), is_reference(Ref) -> ChannelPid ! {invoke, Ref, ReceiverPid, Payload}. %% 超时逻辑处理 channel_reply(Id, Reply, Inflight) -> case maps:take(Id, Inflight) of error -> Inflight; {{ReceiverPid, Ref}, NInflight} -> case is_pid(ReceiverPid) andalso is_process_alive(ReceiverPid) of true -> ReceiverPid ! {channel_reply, Ref, Reply}; false -> ok end, NInflight end. %% 注册 -spec register(Id :: integer(), ServiceId :: binary()) -> {error, Reply :: binary()} | {ok, Reply :: binary(), ServicePid :: pid()}. register(Id, ServiceId) when is_integer(Id), is_binary(ServiceId) -> case efka_service:get_pid(ServiceId) of undefined -> lager:warning("[gen_channel] service_id: ~p, not running", [ServiceId]), Reply = json_error(Id, -1, <<"service not running">>), {error, Reply}; ServicePid when is_pid(ServicePid) -> case efka_service:attach_channel(ServicePid, self()) of ok -> Reply = json_result(Id, <<"ok">>), erlang:monitor(process, ServicePid), {ok, Reply, ServicePid}; {error, Error} -> lager:warning("[gen_channel] service_id: ~p, attach_channel get error: ~p", [ServiceId, Error]), Reply = json_error(Id, -1, Error), {error, Reply} end end. %% 采用32位编码 -spec next_packet_id(PacketId :: integer()) -> NextPacketId :: integer(). next_packet_id(PacketId) when PacketId >= 4294967295 -> 1; next_packet_id(PacketId) -> PacketId + 1. -spec json_result(Id :: integer(), Result :: term()) -> binary(). json_result(Id, Result) when is_integer(Id) -> Response = #{ <<"id">> => Id, <<"result">> => Result }, jiffy:encode(Response, [force_utf8]). -spec json_error(Id :: integer(), Code :: integer(), Message :: binary()) -> binary(). json_error(Id, Code, Message) when is_integer(Id), is_integer(Code), is_binary(Message) -> Response = #{ <<"id">> => Id, <<"error">> => #{ <<"code">> => Code, <<"message">> => Message } }, jiffy:encode(Response, [force_utf8]).