Release 14!
authorMatt Mullins <mmullins@mmlx.us>
Mon, 4 Jan 2016 07:49:35 +0000 (23:49 -0800)
committerMatt Mullins <mmullins@mmlx.us>
Mon, 4 Jan 2016 07:49:35 +0000 (23:49 -0800)
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
amqp/amqp.appup
bot.rel
core/core.app
core/core.appup
irc/irc.app
irc/irc.appup
irc/irc_conn.erl

index 8c8edf9..9b42cde 100644 (file)
@@ -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]},
index 6da09d3..52d3fb1 100644 (file)
@@ -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 (file)
--- 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"}]
 }.
index 18e6e8f..7238e2c 100644 (file)
@@ -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}}
index cd9741d..188a26f 100644 (file)
@@ -1,3 +1,3 @@
-{"2",
- [{"1", [{load_module, config}]}],
- [{"1", [{load_module, config}]}]}.
+{"3",
+ [{"2", [{add_module, rate_limit}]}],
+ [{"2", [{delete_module, rate_limit}]}]}.
index 8077632..76ac740 100644 (file)
@@ -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]},
index 4271b48..42b4553 100644 (file)
@@ -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}}
    ]}]
 }.
index 463b975..35bf092 100644 (file)
@@ -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}.