Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make packet_to_component GD handler more robust #1763

Merged
merged 4 commits into from
Mar 12, 2018

Conversation

fenek
Copy link
Member

@fenek fenek commented Mar 8, 2018

  • mod_global_distrib:get_metadata/2,3 now may return {error, missing_gd_structure} error.
  • Fixed ETS creation in mod_global_distrib_utils - {heir, none, testing} parameter is illegal.
  • maybe_update_mapping/2 won't crash now if global_distrib structure is missing in acc.
  • New integration test is a byproduct of attempts to reproduce the issue; since it covers a new scenario, I haven't removed it.
  • Fixed component_SUITE:connect_component/2 as it was returning invalid component address.

@@ -43,15 +43,21 @@ start(Host, Opts0) ->
stop(Host) ->
mod_global_distrib_utils:stop(?MODULE, Host, fun stop/0).

-spec get_metadata(mongoose_acc:t(), Key :: term(), Default :: term()) -> Value :: term().
-spec get_metadata(mongoose_acc:t(), Key :: term(), Default :: term()) ->
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feels like it makes sense to start using {ok, Value} | {error, Reason} return format.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, it makes sense to just return Default instead.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since there's no possibility for error I'd stick with returning a single value. AFAIK that's normal for functions taking a default (proplists:get_value, map:get, application:get_env).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to keep consistent API for get_ functions... so maybe we can rename them to get_metadata/3 and find_metadata/2, so the API will be similar to map equivalents? Single value returned by /3 and tuple or error for /2.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, go ahead :)


-spec get_metadata(mongoose_acc:t(), Key :: term()) -> Value :: term().
-spec get_metadata(mongoose_acc:t(), Key :: term()) ->
Copy link
Contributor

@arcusfelis arcusfelis Mar 8, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tricky error handling is required from the caller of this function.
badkey as an exception, {error, Reason}, high chance that we would not match on {error,_} in the caller code and the tuple would "walk" around our code.

@@ -145,12 +145,12 @@ create_ets(Names, Type) when is_list(Names) ->
create_ets(Name, Type) ->
Self = self(),
Heir = case whereis(ejabberd_sup) of
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not the first time I see this pattern, usually in module start function.
Maybe we should have a dedicated process for keeping our ets tables.
Also, explicit ets:give_away is preferable, because the ets always would be owned by the same process.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mongoose_ets? :) I'll create a task for this.

Component1Config = [{port, 8888}, {component, <<"service1">>} | ComponentCommonConfig],
Component2Config = [{port, 9990}, {component, <<"service2">>} | ComponentCommonConfig],

{Comp1, Addr1, _Name1} = component_SUITE:connect_component(Component1Config),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

connect_component should into component_helper. Not in this PR.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've created a dedicated task for this.

{host, ComponentHost} = lists:keyfind(host, 1, ComponentOpts),
ComponentAddr = <<ComponentName/binary, ".", ComponentHost/binary>>,
{server, ComponentServer} = lists:keyfind(server, 1, ComponentOpts),
ComponentAddr = <<ComponentName/binary, ".", ComponentServer/binary>>,
{Component, ComponentAddr, ComponentName};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

map is preferable as a return value (maybe not in this pr).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be refactored as a part of "move to helper" PR.

@@ -833,6 +854,8 @@ get_mapping(Node, Client) ->
{ok, What} = redis_query(Node, [<<"GET">>, FullJid]),
What.

%% Warning! May not work properly with alice or any other user whose
%% stringprepped JID is different than original one
delete_mapping(Node, Client) ->
Copy link
Contributor

@arcusfelis arcusfelis Mar 8, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

escalus_utils:jid_to_lower(BinJid) can be used to work with all jids.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I tried to experiment with this function, some tests suddenly broke. :P So I'm putting a warning for now so the PR won't be blocked... but this suite should be refactored definitely.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, there is some regex inside, not sure it does normalization too

Copy link
Contributor

@arcusfelis arcusfelis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good.
I've added some comments.
Ping me if you decide to do/not to do changes, so I can review the final version of the code.

@@ -43,15 +43,21 @@ start(Host, Opts0) ->
stop(Host) ->
mod_global_distrib_utils:stop(?MODULE, Host, fun stop/0).

-spec get_metadata(mongoose_acc:t(), Key :: term(), Default :: term()) -> Value :: term().
-spec get_metadata(mongoose_acc:t(), Key :: term(), Default :: term()) ->
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since there's no possibility for error I'd stick with returning a single value. AFAIK that's normal for functions taking a default (proplists:get_value, map:get, application:get_env).

Origin = mod_global_distrib:get_metadata(Acc, origin),
mod_global_distrib_mapping:insert_for_jid(From, Origin);
case mod_global_distrib:get_metadata(Acc, origin) of
%% Lack of 'global_distrib' indicates 100% local routing...
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How did we get to maybe_update_mapping with non-GD message? 😕

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When mongoose_router_external* are moved to the beginning of router list and the message is routed locally in cluster, a packet to component will be processed by packet_to_component hook, which is handled by mod_global_distrib_mapping.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Guess I missed the change to the routing list.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change is done only in one of the deployments, it won't be a default for open source.

Copy link
Contributor

@arcusfelis arcusfelis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good

@fenek fenek merged commit 1605df3 into master Mar 12, 2018
@fenek fenek deleted the reorderable-component-routers branch March 12, 2018 07:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants