From: Aurelien DARRAGON Date: Wed, 7 Oct 2026 10:42:43 +0000 (+0200) Subject: MINOR: hlua: expose PROXY event family through Lua X-Git-Tag: v3.5-dev9~38 X-Git-Url: https://git.kaiwu.me/?a=commitdiff_plain;h=c67dbf5296b5e237239a50badea4752013f65378;p=haproxy.git MINOR: hlua: expose PROXY event family through Lua Add Proxy.event_sub() method to be able to subscribe to per proxy events, and expose PROXY event family through Lua event_hdl handler. Documentation was updated with known PROXY family events (ADD/DEL/ PUB/UNPUB). --- diff --git a/doc/lua-api/index.rst b/doc/lua-api/index.rst index 8632aaf6a..20364e79a 100644 --- a/doc/lua-api/index.rst +++ b/doc/lua-api/index.rst @@ -1056,6 +1056,13 @@ instances being inherited by the proxies using them. See the (e.g.: SERVER_STATE will always be generated for each SERVER_DOWN or SERVER_UP) + **PROXY** Family: + + * **PROXY_ADD**: when a proxy is added dynamically + * **PROXY_DEL**: when a server is removed dynamically + * **PROXY_PUB**: when a proxy is published (ready to serve connections) + * **PROXY_UNPUB**: when a server is unpublished (ineligible for trafic) + The prototype of the Lua function used as argument is: .. code-block:: lua @@ -1067,7 +1074,8 @@ instances being inherited by the proxies using them. See the when subscribing) * **event_data**: specific to each event family (For **SERVER** family, a :ref:`server_event_class` object; for **ACME** family, - a :ref:`acme_event_class` object) + a :ref:`acme_event_class` object, for **PROXY** family, + a :ref:`proxy_event_class` object) * **sub**: class to manage the subscription from within the event (a :ref:`event_sub_class` object) * **when**: timestamp corresponding to the date when the event was generated. @@ -1256,6 +1264,59 @@ Proxy class proxy. :returns: a :ref:`proxy_mailers_class` containing proxy mailers config +.. js:function:: Proxy.event_sub(px, event_types, func) + + Register a function that will be called on specific proxy events. + It works exactly like :js:func:`core.event_sub()` except that the subscription + will be performed within the proxy dedicated subscription list instead of the + global one. + (Your callback function will only be called for proxy events affecting px) + + See :js:func:`core.event_sub()` for function usage. + + A key advantage to using :js:func:`Proxy.event_sub()` over + :js:func:`core.event_sub()` for proxies is that :js:func:`Proxy.event_sub()` + allows you to be notified for proxies events of a single proxy only. + It removes the needs for extra filtering in your callback function if you only + care about a single proxy, and also prevents useless wakeups. + + .. Note:: + You may also combine :js:func:`core.event_sub()` with + :js:func:`Proxy.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:`Proxy.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({"PROXY_ADD"}, function(event, data, sub) + -- in the global event handler + if data["reference"] ~= nil then + print("Tracking new proxy: ", data["name"]) + data["reference"]:event_sub({"PROXY_PUB", "PROXY_UNPUB"}, function(event, data, sub) + -- in the per-proxy event handler + if data["reference"] ~= nil then + core.register_task(function(proxy) + -- subtask to perform some async work (e.g.: HTTP API calls, sending emails...) + print("ASYNC: PROXY ", proxy:get_name(), " is ", event == "PROXY_PUB" and "PUBLISHED" or "UNPUBLISHED") + end, data["reference"]) + end + end) + end + end) + +.. + + In this example, we will first track global proxy addition events. + For each newly added proxy ("add backend" on the cli), we will register a + PUB, UNPUB proxy subscription. + Then, the callback function will schedule the event handling in an async + subtask which will receive the server reference as an argument. + .. _proxy_mailers_class: ProxyMailers class diff --git a/src/hlua.c b/src/hlua.c index 46d7cc96e..c62b952b4 100644 --- a/src/hlua.c +++ b/src/hlua.c @@ -9576,6 +9576,39 @@ __LJMP static void hlua_event_hdl_cb_push_args(struct hlua_event_sub *hlua_sub, } } } + else if (event_hdl_sub_family_equal(EVENT_HDL_SUB_PROXY, event)) { + struct event_hdl_cb_data_proxy *e_proxy = data; + struct proxy *px; + + hlua->nargs += 1; + lua_newtable(hlua->T); + /* Add proxy name */ + lua_pushstring(hlua->T, "name"); + lua_pushstring(hlua->T, e_proxy->safe.name); + lua_settable(hlua->T, -3); + /* Add proxy uuid */ + lua_pushstring(hlua->T, "uuid"); + lua_pushinteger(hlua->T, e_proxy->safe.uuid); + lua_settable(hlua->T, -3); + /* Add proxy cap */ + lua_pushstring(hlua->T, "cap"); + lua_pushstring(hlua->T, proxy_cap_str(e_proxy->safe.cap)); + lua_settable(hlua->T, -3); + /* Add server proxy guid */ + lua_pushstring(hlua->T, "guid"); + lua_pushstring(hlua->T, e_proxy->safe.guid); + lua_settable(hlua->T, -3); + + /* attempt to provide reference proxy object + * (if it wasn't removed yet, PROXY_DEL will never succeed here) + */ + px = proxy_find_by_id(e_proxy->safe.uuid, e_proxy->safe.cap, 0); + if (px) { + lua_pushstring(hlua->T, "reference"); + hlua_fcn_new_proxy(hlua->T, px); + lua_settable(hlua->T, -3); + } + } #if defined(HAVE_ACME) else if (event_hdl_sub_family_equal(EVENT_HDL_SUB_ACME, event)) { MAY_LJMP(acme_hlua_event_push_args(hlua, event, data)); diff --git a/src/hlua_fcn.c b/src/hlua_fcn.c index 44f37b199..5a53e5212 100644 --- a/src/hlua_fcn.c +++ b/src/hlua_fcn.c @@ -2254,6 +2254,27 @@ int hlua_proxy_get_mailers(lua_State *L) return 1; } +/* hlua_event_sub wrapper for per-proxy subscription: + * + * hlua_event_sub() is called with proxy->e_subs subscription list and + * lua arguments are passed as-is (skipping the first argument which + * is the proxy ctx) + */ +int hlua_proxy_event_sub(lua_State *L) +{ + struct proxy *px; + + px = hlua_check_proxy(L, 1); + if (px == NULL) { + return 0; + } + /* remove first argument from the stack (proxy) */ + lua_remove(L, 1); + + /* try to subscribe within proxy's subscription list */ + return hlua_event_sub(L, &px->e_subs); +} + int hlua_fcn_new_proxy(lua_State *L, struct proxy *px) { struct listener *lst; @@ -2284,6 +2305,7 @@ int hlua_fcn_new_proxy(lua_State *L, struct proxy *px) hlua_class_function(L, "get_srv_bck", hlua_proxy_get_srv_bck); hlua_class_function(L, "get_stats", hlua_proxy_get_stats); hlua_class_function(L, "get_mailers", hlua_proxy_get_mailers); + hlua_class_function(L, "event_sub", hlua_proxy_event_sub); /* Browse and register servers. */ lua_pushstring(L, "servers");