MINOR: hlua/event_hdl: per-server event subscription

Now that event_hdl api is properly implemented in hlua, we may add the
per-server event subscription in addition to the global event
subscription.

Per-server subscription allows to be notified for events related to
single server. It is useful to track a server UP/DOWN and DEL events.

It works exactly like core.event_sub() except that the subscription
will be performed within the server dedicated subscription list instead
of the global one.
The callback function will only be called for server events affecting
the server from which the subscription was performed.

Regarding the implementation, it is pretty trivial at this point, we add
more doc than code this time.

Usage examples have been added to the (lua) documentation.
This commit is contained in:
Aurelien DARRAGON 2023-03-10 15:34:35 +01:00 committed by Christopher Faulet
parent c84899c636
commit 223770ddca
2 changed files with 86 additions and 0 deletions

View File

@ -924,6 +924,7 @@ Core class
:param array event_types: array of string containing the event types you want to subscribe to
:param function func: is the Lua function called when one of the subscribed events occur.
:returns: A :ref:`event_sub_class` object.
:see: :js:func:`Server.event_sub()`.
List of available event types :
@ -1298,6 +1299,69 @@ Server class
:param class_server sv: A :ref:`server_class` which indicates the manipulated
server.
.. js:function:: Server.event_sub(sv, event_types, func)
Register a function that will be called on specific server events.
It works exactly like :js:func:`core.event_sub()` except that the subscription
will be performed within the server dedicated subscription list instead of the
global one.
(Your callback function will only be called for server events affecting sv)
See :js:func:`core.event_sub()` for function usage.
A key advantage to using :js:func:`Server.event_sub()` over
:js:func:`core.event_sub()` for servers is that :js:func:`Server.event_sub()`
allows you to be notified for servers events of a single server only.
It removes the needs for extra filtering in your callback function if you only
care about a single server, and also prevents useless wakeups.
For instance, if you want to be notified for UP/DOWN events on a given set of
servers, it is recommended to peform multiple per-server subscriptions since
it will be more efficient that doing a single global subscription that will
filter the received events.
Unless you really want to be notified for servers events of ALL servers of
course, which could make sense given you setup but should be avoided if you
have an important number of servers as it will add a significant load on your
haproxy process in case of multiple servers state change in a short amount of
time.
.. Note::
You may also combine :js:func:`core.event_sub()` with
:js:func:`Server.event_sub()`.
Also, don't forget that you can use :js:func:`core.register_task()` from
your callback function if needed. (ie: parallel work)
Here is a working example combining :js:func:`core.event_sub()` with
:js:func:`Server.event_sub()` and :js:func:`core.register_task()`
(This only serves as a demo, this is not necessarily useful to do so)
.. code-block:: lua
core.event_sub({"SERVER_ADD"}, function(event, data, sub)
-- in the global event handler
if data["reference"] ~= nil then
print("Tracking new server: ", data["name"])
data["reference"]:event_sub({"SERVER_UP", "SERVER_DOWN"}, function(event, data, sub)
-- in the per-server event handler
if data["reference"] ~= nil then
core.register_task(function(server)
-- subtask to perform some async work (e.g.: HTTP API calls, sending emails...)
print("ASYNC: SERVER ", server:get_name(), " is ", event == "SERVER_UP" and "UP" or "DOWN")
end, data["reference"])
end
end)
end
end)
..
In this example, we will first track global server addition events.
For each newly added server ("add server" on the cli), we will register a
UP/DOWN server subscription.
Then, the callback function will schedule the event handling in an async
subtask which will receive the server reference as an argument.
.. _listener_class:
Listener class

View File

@ -1374,6 +1374,27 @@ int hlua_server_agent_force_down(lua_State *L)
return 0;
}
/* hlua_event_sub wrapper for per-server subscription:
*
* hlua_event_sub() is called with sv->e_subs subscription list and
* lua arguments are passed as-is (skipping the first argument which
* is the server ctx)
*/
int hlua_server_event_sub(lua_State *L)
{
struct server *sv;
sv = hlua_check_server(L, 1);
if (sv == NULL) {
return 0;
}
/* remove first argument from the stack (server) */
lua_remove(L, 1);
/* try to subscribe within server's subscription list */
return hlua_event_sub(L, &sv->e_subs);
}
int hlua_fcn_new_server(lua_State *L, struct server *srv)
{
lua_newtable(L);
@ -1413,6 +1434,7 @@ int hlua_fcn_new_server(lua_State *L, struct server *srv)
hlua_class_function(L, "agent_disable", hlua_server_agent_disable);
hlua_class_function(L, "agent_force_up", hlua_server_agent_force_up);
hlua_class_function(L, "agent_force_down", hlua_server_agent_force_down);
hlua_class_function(L, "event_sub", hlua_server_event_sub);
return 1;
}