From af205db5bf109bca5f36c2489e5c56605e4ac542 Mon Sep 17 00:00:00 2001 From: Matt Mullins Date: Sun, 3 Jan 2016 23:49:35 -0800 Subject: [PATCH] Release 14! This release adds rate limits and failure (gen_server timeout) tolerance to the AMQP codepaths, so that they always stay under their supervisor's restart intensity. This upgrade/downgrade path is a little racey: - It's not guaranteed that rate_limit is loaded before other modules. - The supervisors are running while the worker modules with shiny new init/1 arguments are loaded. This can cause full failure if something needs to restart while the upgrade is ongoing. Since these are just init codepaths, I'll take my chances. It's like the big sky theory, in the time domain. --- amqp/amqp.app | 2 +- amqp/amqp.appup | 12 +++++++----- bot.rel | 8 ++++---- core/core.app | 4 ++-- core/core.appup | 6 +++--- irc/irc.app | 2 +- irc/irc.appup | 16 +++++++++------- irc/irc_conn.erl | 23 +++++++++++++---------- 8 files changed, 40 insertions(+), 33 deletions(-) diff --git a/amqp/amqp.app b/amqp/amqp.app index 8c8edf9..9b42cde 100644 --- a/amqp/amqp.app +++ b/amqp/amqp.app @@ -1,6 +1,6 @@ {application, amqp, [{description, "AMQP client operations"}, - {vsn, "3"}, + {vsn, "4"}, {modules, [amqp_app, amqp_bot_sup, amqp_bot_connection, amqp_bot_listener]}, {registered, [amqp_bot_connection]}, {applications, [core]}, diff --git a/amqp/amqp.appup b/amqp/amqp.appup index 6da09d3..52d3fb1 100644 --- a/amqp/amqp.appup +++ b/amqp/amqp.appup @@ -1,8 +1,10 @@ -{"3", - [{"2", - [{update, amqp_bot_listener}] +{"4", + [{"3", + [{update, amqp_bot_connection}, + {update, amqp_bot_sup, supervisor}] }], - [{"2", - [{update, amqp_bot_listener}] + [{"3", + [{update, amqp_bot_connection}, + {update, amqp_bot_sup, supervisor}] }] }. diff --git a/bot.rel b/bot.rel index b4404e6..8e551f3 100644 --- a/bot.rel +++ b/bot.rel @@ -1,11 +1,11 @@ -{release, {"erlbot", "13"}, +{release, {"erlbot", "14"}, {erts, "5.8.3"}, [{kernel, "2.14.5"}, {stdlib, "1.17.5"}, {sasl, "2.1.10"}, {rabbit_common, "0.0.0"}, {amqp_client, "0.0.0"}, - {core, "2"}, - {amqp, "3"}, - {irc, "12"}] + {core, "3"}, + {amqp, "4"}, + {irc, "13"}] }. diff --git a/core/core.app b/core/core.app index 18e6e8f..7238e2c 100644 --- a/core/core.app +++ b/core/core.app @@ -1,7 +1,7 @@ {application, core, [{description, "IRC bot core functionality"}, - {vsn, "2"}, - {modules, [core_app, core_sup, config]}, + {vsn, "3"}, + {modules, [core_app, core_sup, config, rate_limit]}, {registered, [config]}, {applications, []}, % also depends on kernel, stdlib {mod, {core_app, none}} diff --git a/core/core.appup b/core/core.appup index cd9741d..188a26f 100644 --- a/core/core.appup +++ b/core/core.appup @@ -1,3 +1,3 @@ -{"2", - [{"1", [{load_module, config}]}], - [{"1", [{load_module, config}]}]}. +{"3", + [{"2", [{add_module, rate_limit}]}], + [{"2", [{delete_module, rate_limit}]}]}. diff --git a/irc/irc.app b/irc/irc.app index 8077632..76ac740 100644 --- a/irc/irc.app +++ b/irc/irc.app @@ -1,6 +1,6 @@ {application, irc, [{description, "IRC protocol application"}, - {vsn, "12"}, + {vsn, "13"}, {modules, [irc_util, irc_app, irc_sup, irc_net_sup, irc_conn, irc_object_sup, irc_amqp_listener, irc_command]}, {registered, [irc_sup, irc_dummy]}, diff --git a/irc/irc.appup b/irc/irc.appup index 4271b48..42b4553 100644 --- a/irc/irc.appup +++ b/irc/irc.appup @@ -1,10 +1,12 @@ -{"12", - [{"11", - [{update, irc_command}, - {update, irc_amqp_listener} +{"13", + [{"12", + [{update, irc_amqp_listener}, + {update, irc_object_sup}, + {update, irc_conn, {advanced, ok}} ]}], - [{"11", - [{update, irc_command}, - {update, irc_amqp_listener} + [{"12", + [{update, irc_amqp_listener}, + {update, irc_object_sup}, + {update, irc_conn, {advanced, ok}} ]}] }. diff --git a/irc/irc_conn.erl b/irc/irc_conn.erl index 463b975..35bf092 100644 --- a/irc/irc_conn.erl +++ b/irc/irc_conn.erl @@ -1,6 +1,6 @@ -module(irc_conn). -behavior(gen_server). --vsn(5). +-vsn(6). -define(RECONNECT_TIME, 30000). -define(PING_PERIOD, timer:seconds(30)). @@ -190,15 +190,18 @@ reset_ping_timer(#irc_state{ping_timer = Timer} = State) -> terminate(_Reason, _State) -> ok. -code_change(4, OldState, ok) -> - NewState = list_to_tuple(tuple_to_list(OldState) ++ [none]), - error_logger:info_msg("Updating irc state from ~p to ~p~n", [OldState, NewState]), - {ok, NewState}; - -code_change({down, 4}, State, ok) -> - TimerRef = State#irc_state.ping_timer, - timer:cancel(TimerRef), - {ok, list_to_tuple(lists:sublist(tuple_to_list(State), 9))}; +code_change(5, State, ok) -> + #irc_state{instance = Instance, + object_sup = ObjectSup} = State, + RoutingKey = get_routing_key(Instance), + irc_object_sup:delete_amqp_listener(ObjectSup, RoutingKey), + % TODO: test that the message is handled *after* the code change. + gen_server:cast(self(), create_object_sup), + {ok, State}; + +code_change({down, 5}, State, ok) -> + % Since there's no actual state change, the exact same instructions are fine. + code_change(5, State, ok); code_change(_OldVsn, _State, _Extra) -> {error, unsupported}. -- 2.11.0