Skip to content

Commit

Permalink
Added function to wait for site startup. (#1466)
Browse files Browse the repository at this point in the history
Use z_sites_manager:await_startup/1 and/or z_module_manager:await_upgrade/1
  • Loading branch information
mworrell authored and ddeboer committed Oct 6, 2016
1 parent 823e660 commit d76d54a
Show file tree
Hide file tree
Showing 9 changed files with 78 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,6 @@ context() ->

start_modules(Context) ->
ok = z_module_manager:activate_await(mod_content_groups, Context),
ok = z_module_manager:activate_await(mod_acl_user_groups, Context).
ok = z_module_manager:activate_await(mod_acl_user_groups, Context),
ok = z_module_manager:await_upgrade(Context).

2 changes: 2 additions & 0 deletions modules/mod_search/tests/mod_search_db_tests.erl
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ wait_for(QueryId, ItemId) ->


query_hooks_test() ->
ok = z_sites_manager:await_startup(testsandboxdb),
C = z_acl:sudo(z_context:new(testsandboxdb)),

z_notifier:observe(rsc_query_item, self(), C),
Expand Down Expand Up @@ -50,6 +51,7 @@ query_hooks_test() ->


search_query_notify_test() ->
ok = z_sites_manager:await_startup(testsandboxdb),
C = z_acl:sudo(z_context:new(testsandboxdb)),

Q = <<"cat=keyword\nis_featured">>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ event(#submit{message=addsite, form=Form}, Context) ->
progress(Sitename, ?__("Starting the new site ...", Context), Context),
ok = z_sites_manager:upgrade(),
ok = z_sites_manager:start(Site),
ok = z_sites_manager:await_startup(Site),
lager:info("[zotonic_status] Success creating site ~s", [Site]),
case await(Site) of
ok ->
Expand Down
5 changes: 4 additions & 1 deletion src/models/tests/m_identity_tests.erl
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ hash_is_equal_old_hash_test() ->
ok.

check_password_no_user_test() ->
ok = z_sites_manager:await_startup(testsandboxdb),
C = z_context:new(testsandboxdb),
AdminC = z_acl:logon(?ACL_ADMIN_USER_ID, C),
ok = delete_user("mr_z", AdminC),
Expand All @@ -46,6 +47,7 @@ check_username_password_test_() ->
{timeout, 20, fun() -> check_username_password() end}.

check_username_password() ->
ok = z_sites_manager:await_startup(testsandboxdb),
C = z_context:new(testsandboxdb),
start_modules(C),

Expand Down Expand Up @@ -87,7 +89,8 @@ start_modules(Context) ->
ok = z_module_manager:activate_await(mod_acl_mock, Context),
ok = z_module_manager:activate_await(mod_authentication, Context),
ok = z_module_manager:activate_await(mod_admin, Context),
ok = z_module_manager:activate_await(mod_admin_identity, Context).
ok = z_module_manager:activate_await(mod_admin_identity, Context),
ok = z_module_manager:await_upgrade(Context).


%% Old hash algorithm copied from m_identity before the change to bcrypt.
Expand Down
3 changes: 3 additions & 0 deletions src/models/tests/m_rsc_db_tests.erl
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
-include_lib("zotonic.hrl").

modify_rsc_test() ->
ok = z_sites_manager:await_startup(testsandboxdb),
C = z_context:new(testsandboxdb),
AdminC = z_acl:logon(?ACL_ADMIN_USER_ID, C),
CatId = m_rsc:rid(text, C),
Expand Down Expand Up @@ -53,6 +54,7 @@ modify_rsc_test() ->


page_path_test() ->
ok = z_sites_manager:await_startup(testsandboxdb),
C = z_context:new(testsandboxdb),
AdminC = z_acl:logon(?ACL_ADMIN_USER_ID, C),

Expand All @@ -62,6 +64,7 @@ page_path_test() ->

%% @doc Resource name instead of id as argument.
name_rid_test() ->
ok = z_sites_manager:await_startup(testsandboxdb),
C = z_context:new(testsandboxdb),
AdminC = z_acl:logon(?ACL_ADMIN_USER_ID, C),
{ok, Id} = m_rsc:insert([{title, <<"What’s in a name?"/utf8>>}, {category_id, text}, {name, rose}], AdminC),
Expand Down
1 change: 1 addition & 0 deletions src/models/tests/m_rsc_import_db_tests.erl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

modify_rsc_test() ->
C = z_context:new(testsandboxdb),
ok = z_module_manager:await_upgrade(C),
AdminC = z_acl:logon(?ACL_ADMIN_USER_ID, C),
SudoC = z_acl:sudo(C),

Expand Down
36 changes: 36 additions & 0 deletions src/support/z_module_manager.erl
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
deactivate/2,
activate/2,
activate_await/2,
await_upgrade/1,
restart/2,
module_reloaded/2,
active/1,
Expand All @@ -42,6 +43,7 @@
get_provided/1,
get_modules/1,
get_modules_status/1,
get_upgrade_status/1,
whereis/2,
all/1,
scan/1,
Expand Down Expand Up @@ -160,6 +162,21 @@ activate(Module, IsSync, Context) ->
{error, not_found}
end.

%% @doc Wait till all modules are started, used when starting up a new or test site.
-spec await_upgrade(#context{}) -> ok | {error, timeout}.
await_upgrade(Context) ->
await_upgrade(Context, 20).

await_upgrade(_Context, 0) ->
{error, timeout};
await_upgrade(Context, RetryCt) ->
case erlang:whereis(name(Context)) of
undefined ->
timer:sleep(500),
await_upgrade(Context, RetryCt-1);
Pid ->
gen_server:call(Pid, await_upgrade, infinity)
end.

%% @doc Restart a module, activates the module if it was not activated.
-spec restart(Module::atom(), #context{}) -> ok | {error, not_found}.
Expand Down Expand Up @@ -236,6 +253,11 @@ get_modules_status(Context) ->
gen_server:call(name(Context), get_modules_status).


%% @doc Return the status of any ongoing upgrade
get_upgrade_status(Context) ->
gen_server:call(name(Context), get_upgrade_status).


%% @doc Return the pid of a running module
-spec whereis(atom(), #context{}) -> {ok, pid()} | {error, not_running}.
whereis(Module, Context) ->
Expand Down Expand Up @@ -467,6 +489,20 @@ handle_call(upgrade, From, State) ->
State2 = handle_upgrade(State1),
{noreply, State2};

handle_call(get_upgrade_status, _From, State) ->
Reply = [
{start_wait, State#state.start_wait},
{start_queue, State#state.start_queue},
{start_error, State#state.start_error},
{upgrade_waiters, State#state.upgrade_waiters}
],
{reply, {ok, Reply}, State};

handle_call(await_upgrade, _From, #state{start_wait=none, start_queue=[]} = State) ->
{reply, ok, State};
handle_call(await_upgrade, From, State) ->
{noreply, State#state{upgrade_waiters=[From|State#state.upgrade_waiters]}};

%% @doc Trap unknown calls
handle_call(Message, _From, State) ->
{stop, {unknown_call, Message}, State}.
Expand Down
41 changes: 27 additions & 14 deletions src/support/z_sites_manager.erl
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,9 @@ get_sites_all() ->
gen_server:call(?MODULE, get_sites_all).

%% @doc Get the status of a particular site
get_site_status(Site) when is_atom(Site) ->
gen_server:call(?MODULE, {site_status, Site});
get_site_status(#context{site=Site}) ->
get_site_status(Site);
get_site_status(Site) when is_atom(Site) ->
gen_server:call(?MODULE, {site_status, Site}).

%% @doc Return a list of all sites and their status.
Expand Down Expand Up @@ -190,6 +190,31 @@ module_loaded(Module) ->
gen_server:cast(?MODULE, {module_loaded, Module}).


%% @doc Wait for a site to complete its startup sequence. Note - due
%% to the way the site startup works currently, we cannot know whether
%% the site has already started or not. Therefore, this function
%% should only be called when you are certain the site has not
%% completed starting up, otherwise it will block infinitely.
await_startup(Context = #context{}) ->
await_startup(z_context:site(Context));
await_startup(Site) when is_atom(Site) ->
case get_site_status(Site) of
{ok, running} ->
% Now wait for the sites modules to be started
Context = z_context:new(Site),
z_module_manager:await_upgrade(Context);
{ok, failed} ->
{error, failed};
{ok, stopped} ->
{error, stopped};
{ok, retrying} ->
timer:sleep(1000),
await_startup(Site);
{error, _} = Error ->
Error
end.


%%====================================================================
%% gen_server callbacks
%%====================================================================
Expand Down Expand Up @@ -536,18 +561,6 @@ is_module(Module) ->
_ -> false
end.

%% @doc Wait for a site to complete its startup sequence. Note - due
%% to the way the site startup works currently, we cannot know whether
%% the site has already started or not. Therefore, this function
%% should only be called when you are certain the site has not
%% completed starting up, otherwise it will block infinitely.
await_startup(Context = #context{}) ->
case z_notifier:await(module_ready, 30*1000, Context) of
{ok, _} ->
ok;
E -> E
end.

get_site_config_overrides(Site) when is_atom(Site) ->
Key = z_convert:to_atom(z_convert:to_list(Site) ++ "_config_overrides"),
application:get_env(zotonic, Key, []).
Expand Down
4 changes: 1 addition & 3 deletions src/support/z_sitetest.erl
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,7 @@ close_connection(Connection) ->
%% @doc Start the site, and wait for it to be fully booted.
start_site(Site) ->
ok = z_sites_manager:start(Site),
timer:sleep(100), %% Sleep is needed to ensure the translation server has started
Context = z_context:new(Site),
ok = z_sites_manager:await_startup(Context).
z_sites_manager:await_startup(Site).


%% @doc Filter the list of beam files to find all sitetest modules
Expand Down

0 comments on commit d76d54a

Please sign in to comment.