|
|
@@ -233,7 +233,7 @@ on_get_status(InstanceId, State) ->
|
|
|
{ok, pos_integer(), [term()], term()}
|
|
|
| {ok, pos_integer(), [term()]}
|
|
|
| {error, term()}.
|
|
|
-on_query(InstanceId, {ChannelId, Msg} = Req, #{channels := Channels} = State) ->
|
|
|
+on_query(InstanceId, {ChannelId, Msg} = Req, State) ->
|
|
|
?tp(elasticsearch_bridge_on_query, #{instance_id => InstanceId}),
|
|
|
?SLOG(debug, #{
|
|
|
msg => "elasticsearch_bridge_on_query_called",
|
|
|
@@ -241,21 +241,16 @@ on_query(InstanceId, {ChannelId, Msg} = Req, #{channels := Channels} = State) ->
|
|
|
send_message => Req,
|
|
|
state => emqx_utils:redact(State)
|
|
|
}),
|
|
|
- case try_render_message(Req, Channels) of
|
|
|
- {ok, Body} ->
|
|
|
- handle_response(
|
|
|
- emqx_bridge_http_connector:on_query(
|
|
|
- InstanceId, {ChannelId, {Msg, Body}}, State
|
|
|
- )
|
|
|
- );
|
|
|
- Error ->
|
|
|
- Error
|
|
|
- end.
|
|
|
+ handle_response(
|
|
|
+ emqx_bridge_http_connector:on_query(
|
|
|
+ InstanceId, {ChannelId, Msg}, State
|
|
|
+ )
|
|
|
+ ).
|
|
|
|
|
|
-spec on_query_async(manager_id(), tuple(), {function(), [term()]}, state()) ->
|
|
|
{ok, pid()} | {error, empty_request}.
|
|
|
on_query_async(
|
|
|
- InstanceId, {ChannelId, Msg} = Req, ReplyFunAndArgs0, #{channels := Channels} = State
|
|
|
+ InstanceId, {ChannelId, Msg} = Req, ReplyFunAndArgs0, State
|
|
|
) ->
|
|
|
?tp(elasticsearch_bridge_on_query_async, #{instance_id => InstanceId}),
|
|
|
?SLOG(debug, #{
|
|
|
@@ -264,22 +259,17 @@ on_query_async(
|
|
|
send_message => Req,
|
|
|
state => emqx_utils:redact(State)
|
|
|
}),
|
|
|
- case try_render_message(Req, Channels) of
|
|
|
- {ok, Payload} ->
|
|
|
- ReplyFunAndArgs =
|
|
|
- {
|
|
|
- fun(Result) ->
|
|
|
- Response = handle_response(Result),
|
|
|
- emqx_resource:apply_reply_fun(ReplyFunAndArgs0, Response)
|
|
|
- end,
|
|
|
- []
|
|
|
- },
|
|
|
- emqx_bridge_http_connector:on_query_async(
|
|
|
- InstanceId, {ChannelId, {Msg, Payload}}, ReplyFunAndArgs, State
|
|
|
- );
|
|
|
- Error ->
|
|
|
- Error
|
|
|
- end.
|
|
|
+ ReplyFunAndArgs =
|
|
|
+ {
|
|
|
+ fun(Result) ->
|
|
|
+ Response = handle_response(Result),
|
|
|
+ emqx_resource:apply_reply_fun(ReplyFunAndArgs0, Response)
|
|
|
+ end,
|
|
|
+ []
|
|
|
+ },
|
|
|
+ emqx_bridge_http_connector:on_query_async(
|
|
|
+ InstanceId, {ChannelId, Msg}, ReplyFunAndArgs, State
|
|
|
+ ).
|
|
|
|
|
|
on_add_channel(
|
|
|
InstanceId,
|
|
|
@@ -291,19 +281,17 @@ on_add_channel(
|
|
|
true ->
|
|
|
{error, already_exists};
|
|
|
_ ->
|
|
|
- #{data := Data} = Parameter,
|
|
|
- Parameter1 = Parameter#{path => path(Parameter), method => <<"post">>},
|
|
|
+ Parameter1 = Parameter#{
|
|
|
+ path => path(Parameter),
|
|
|
+ method => method(Parameter),
|
|
|
+ body => get_body_template(Parameter)
|
|
|
+ },
|
|
|
{ok, State} = emqx_bridge_http_connector:on_add_channel(
|
|
|
InstanceId, State0, ChannelId, #{parameters => Parameter1}
|
|
|
),
|
|
|
- case preproc_data_template(Data) of
|
|
|
- [] ->
|
|
|
- {error, invalid_data};
|
|
|
- DataTemplate ->
|
|
|
- Channel = Parameter1#{data => DataTemplate},
|
|
|
- Channels2 = Channels#{ChannelId => Channel},
|
|
|
- {ok, State#{channels => Channels2}}
|
|
|
- end
|
|
|
+ Channel = Parameter1,
|
|
|
+ Channels2 = Channels#{ChannelId => Channel},
|
|
|
+ {ok, State#{channels => Channels2}}
|
|
|
end.
|
|
|
|
|
|
on_remove_channel(InstanceId, #{channels := Channels} = OldState0, ChannelId) ->
|
|
|
@@ -325,124 +313,55 @@ on_get_channel_status(_InstanceId, ChannelId, #{channels := Channels}) ->
|
|
|
%%--------------------------------------------------------------------
|
|
|
%% Internal Functions
|
|
|
%%--------------------------------------------------------------------
|
|
|
-path(Param) ->
|
|
|
- Target = maps:get(target, Param, undefined),
|
|
|
- QString0 = maps:fold(
|
|
|
- fun(K, V, Acc) ->
|
|
|
- [[atom_to_list(K), "=", to_str(V)] | Acc]
|
|
|
+%% delete DELETE /<index>/_doc/<_id>
|
|
|
+path(#{action := delete, id := Id, index := Index} = Action) ->
|
|
|
+ BasePath = ["/", Index, "/_doc/", Id],
|
|
|
+ Qs = add_query_string([routing], Action),
|
|
|
+ BasePath ++ Qs;
|
|
|
+%% update POST /<index>/_update/<_id>
|
|
|
+path(#{action := update, id := Id, index := Index} = Action) ->
|
|
|
+ BasePath = ["/", Index, "/_update/", Id],
|
|
|
+ Qs = add_query_string([routing, require_alias], Action),
|
|
|
+ BasePath ++ Qs;
|
|
|
+%% create with id /<index>/_doc/_id
|
|
|
+path(#{action := create, index := Index, id := Id} = Action) ->
|
|
|
+ BasePath = ["/", Index, "/_doc/", Id],
|
|
|
+ Qs =
|
|
|
+ case maps:get(overwrite, Action, true) of
|
|
|
+ true ->
|
|
|
+ add_query_string([routing, require_alias], Action);
|
|
|
+ false ->
|
|
|
+ Action1 = Action#{op_type => "create"},
|
|
|
+ add_query_string([routing, require_alias, op_type], Action1)
|
|
|
end,
|
|
|
- [["_source=false"], ["filter_path=items.*.error"]],
|
|
|
- maps:with([require_alias, routing, wait_for_active_shards], Param)
|
|
|
- ),
|
|
|
- QString = "?" ++ lists:join("&", QString0),
|
|
|
- target(Target) ++ QString.
|
|
|
-
|
|
|
-target(undefined) -> "/_bulk";
|
|
|
-target(Str) -> "/" ++ binary_to_list(Str) ++ "/_bulk".
|
|
|
+ BasePath ++ Qs;
|
|
|
+%% create without id POST /<index>/_doc/
|
|
|
+path(#{action := create, index := Index} = Action) ->
|
|
|
+ BasePath = ["/", Index, "/_doc/"],
|
|
|
+ Qs = add_query_string([routing, require_alias], Action),
|
|
|
+ BasePath ++ Qs.
|
|
|
+
|
|
|
+method(#{action := create}) -> <<"POST">>;
|
|
|
+method(#{action := delete}) -> <<"DELETE">>;
|
|
|
+method(#{action := update}) -> <<"POST">>.
|
|
|
+
|
|
|
+add_query_string(Keys, Param0) ->
|
|
|
+ Param1 = maps:with(Keys, Param0),
|
|
|
+ FoldFun = fun(K, V, Acc) -> [[atom_to_list(K), "=", to_str(V)] | Acc] end,
|
|
|
+ case maps:fold(FoldFun, [], Param1) of
|
|
|
+ "" -> "";
|
|
|
+ QString -> "?" ++ lists:join("&", QString)
|
|
|
+ end.
|
|
|
|
|
|
to_str(List) when is_list(List) -> List;
|
|
|
to_str(false) -> "false";
|
|
|
to_str(true) -> "true";
|
|
|
to_str(Atom) when is_atom(Atom) -> atom_to_list(Atom).
|
|
|
|
|
|
-proc_data(DataList, Msg) when is_list(DataList) ->
|
|
|
- [
|
|
|
- begin
|
|
|
- proc_data(Data, Msg)
|
|
|
- end
|
|
|
- || Data <- DataList
|
|
|
- ];
|
|
|
-proc_data(
|
|
|
- #{
|
|
|
- action := Action,
|
|
|
- '_index' := IndexT,
|
|
|
- '_id' := IdT,
|
|
|
- require_alias := RequiredAliasT,
|
|
|
- fields := FieldsT
|
|
|
- },
|
|
|
- Msg
|
|
|
-) when Action =:= create; Action =:= index ->
|
|
|
- [
|
|
|
- emqx_utils_json:encode(
|
|
|
- #{
|
|
|
- Action => filter([
|
|
|
- {'_index', emqx_placeholder:proc_tmpl(IndexT, Msg)},
|
|
|
- {'_id', emqx_placeholder:proc_tmpl(IdT, Msg)},
|
|
|
- {required_alias, emqx_placeholder:proc_tmpl(RequiredAliasT, Msg)}
|
|
|
- ])
|
|
|
- }
|
|
|
- ),
|
|
|
- "\n",
|
|
|
- emqx_placeholder:proc_tmpl(FieldsT, Msg),
|
|
|
- "\n"
|
|
|
- ];
|
|
|
-proc_data(
|
|
|
- #{
|
|
|
- action := delete,
|
|
|
- '_index' := IndexT,
|
|
|
- '_id' := IdT,
|
|
|
- require_alias := RequiredAliasT
|
|
|
- },
|
|
|
- Msg
|
|
|
-) ->
|
|
|
- [
|
|
|
- emqx_utils_json:encode(
|
|
|
- #{
|
|
|
- delete => filter([
|
|
|
- {'_index', emqx_placeholder:proc_tmpl(IndexT, Msg)},
|
|
|
- {'_id', emqx_placeholder:proc_tmpl(IdT, Msg)},
|
|
|
- {required_alias, emqx_placeholder:proc_tmpl(RequiredAliasT, Msg)}
|
|
|
- ])
|
|
|
- }
|
|
|
- ),
|
|
|
- "\n"
|
|
|
- ];
|
|
|
-proc_data(
|
|
|
- #{
|
|
|
- action := update,
|
|
|
- '_index' := IndexT,
|
|
|
- '_id' := IdT,
|
|
|
- require_alias := RequiredAliasT,
|
|
|
- doc_as_upsert := DocAsUpsert,
|
|
|
- upsert := Upsert,
|
|
|
- fields := FieldsT
|
|
|
- },
|
|
|
- Msg
|
|
|
-) ->
|
|
|
- [
|
|
|
- emqx_utils_json:encode(
|
|
|
- #{
|
|
|
- update => filter([
|
|
|
- {'_index', emqx_placeholder:proc_tmpl(IndexT, Msg)},
|
|
|
- {'_id', emqx_placeholder:proc_tmpl(IdT, Msg)},
|
|
|
- {required_alias, emqx_placeholder:proc_tmpl(RequiredAliasT, Msg)},
|
|
|
- {doc_as_upsert, emqx_placeholder:proc_tmpl(DocAsUpsert, Msg)},
|
|
|
- {upsert, emqx_placeholder:proc_tmpl(Upsert, Msg)}
|
|
|
- ])
|
|
|
- }
|
|
|
- ),
|
|
|
- "\n{\"doc\":",
|
|
|
- emqx_placeholder:proc_tmpl(FieldsT, Msg),
|
|
|
- "}\n"
|
|
|
- ].
|
|
|
-
|
|
|
-filter(List) ->
|
|
|
- Fun = fun
|
|
|
- ({_K, V}) when V =:= undefined; V =:= <<"undefined">>; V =:= "undefined" ->
|
|
|
- false;
|
|
|
- ({_K, V}) when V =:= ""; V =:= <<>> ->
|
|
|
- false;
|
|
|
- ({_K, V}) when V =:= "false" -> {true, false};
|
|
|
- ({_K, V}) when V =:= "true" -> {true, true};
|
|
|
- ({_K, _V}) ->
|
|
|
- true
|
|
|
- end,
|
|
|
- maps:from_list(lists:filtermap(Fun, List)).
|
|
|
-
|
|
|
-handle_response({ok, 200, _Headers, Body} = Resp) ->
|
|
|
- eval_response_body(Body, Resp);
|
|
|
-handle_response({ok, 200, Body} = Resp) ->
|
|
|
- eval_response_body(Body, Resp);
|
|
|
+handle_response({ok, Code, _Headers, _Body} = Resp) when Code =:= 200; Code =:= 201 ->
|
|
|
+ Resp;
|
|
|
+handle_response({ok, Code, _Body} = Resp) when Code =:= 200; Code =:= 201 ->
|
|
|
+ Resp;
|
|
|
handle_response({ok, Code, _Headers, Body}) ->
|
|
|
{error, #{code => Code, body => Body}};
|
|
|
handle_response({ok, Code, Body}) ->
|
|
|
@@ -450,49 +369,5 @@ handle_response({ok, Code, Body}) ->
|
|
|
handle_response({error, _} = Error) ->
|
|
|
Error.
|
|
|
|
|
|
-eval_response_body(<<"{}">>, Resp) -> Resp;
|
|
|
-eval_response_body(Body, _Resp) -> {error, emqx_utils_json:decode(Body)}.
|
|
|
-
|
|
|
-preproc_data_template(DataList) when is_list(DataList) ->
|
|
|
- [
|
|
|
- begin
|
|
|
- preproc_data_template(Data)
|
|
|
- end
|
|
|
- || Data <- DataList
|
|
|
- ];
|
|
|
-preproc_data_template(#{action := create} = Data) ->
|
|
|
- Index = maps:get('_index', Data, ""),
|
|
|
- Id = maps:get('_id', Data, ""),
|
|
|
- RequiredAlias = maps:get(require_alias, Data, ""),
|
|
|
- Fields = maps:get(fields, Data, ""),
|
|
|
- #{
|
|
|
- action => create,
|
|
|
- '_index' => emqx_placeholder:preproc_tmpl(Index),
|
|
|
- '_id' => emqx_placeholder:preproc_tmpl(Id),
|
|
|
- require_alias => emqx_placeholder:preproc_tmpl(RequiredAlias),
|
|
|
- fields => emqx_placeholder:preproc_tmpl(Fields)
|
|
|
- };
|
|
|
-preproc_data_template(#{action := index} = Data) ->
|
|
|
- Data1 = preproc_data_template(Data#{action => create}),
|
|
|
- Data1#{action => index};
|
|
|
-preproc_data_template(#{action := delete} = Data) ->
|
|
|
- Data1 = preproc_data_template(Data#{action => create}),
|
|
|
- Data2 = Data1#{action => delete},
|
|
|
- maps:remove(fields, Data2);
|
|
|
-preproc_data_template(#{action := update} = Data) ->
|
|
|
- Data1 = preproc_data_template(Data#{action => index}),
|
|
|
- DocAsUpsert = maps:get(doc_as_upsert, Data, ""),
|
|
|
- Upsert = maps:get(upsert, Data, ""),
|
|
|
- Data1#{
|
|
|
- action => update,
|
|
|
- doc_as_upsert => emqx_placeholder:preproc_tmpl(DocAsUpsert),
|
|
|
- upsert => emqx_placeholder:preproc_tmpl(Upsert)
|
|
|
- }.
|
|
|
-
|
|
|
-try_render_message({ChannelId, Msg}, Channels) ->
|
|
|
- case maps:find(ChannelId, Channels) of
|
|
|
- {ok, #{data := Data}} ->
|
|
|
- {ok, proc_data(Data, Msg)};
|
|
|
- _ ->
|
|
|
- {error, {unrecoverable_error, {invalid_channel_id, ChannelId}}}
|
|
|
- end.
|
|
|
+get_body_template(#{doc := Doc}) -> Doc;
|
|
|
+get_body_template(_) -> undefined.
|