diff options
author | Vsevolod Stakhov <vsevolod@rspamd.com> | 2025-03-01 13:52:16 +0000 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@rspamd.com> | 2025-03-01 13:52:16 +0000 |
commit | b6b8875def92584623854ab2aac35cbf281a7eb2 (patch) | |
tree | 4c36b7f20406060ee74c6eee2b635745a1683b1f /src | |
parent | 2b8e4398ae7148cd98f624a1d6ef10cdfbef413e (diff) | |
download | rspamd-b6b8875def92584623854ab2aac35cbf281a7eb2.tar.gz rspamd-b6b8875def92584623854ab2aac35cbf281a7eb2.zip |
[Feature] Allow to add periodic functions in Lua API
Diffstat (limited to 'src')
-rw-r--r-- | src/lua/lua_util.c | 113 |
1 files changed, 112 insertions, 1 deletions
diff --git a/src/lua/lua_util.c b/src/lua/lua_util.c index ce4d9f67c..0999729ce 100644 --- a/src/lua/lua_util.c +++ b/src/lua/lua_util.c @@ -1,5 +1,5 @@ /* - * Copyright 2024 Vsevolod Stakhov + * Copyright 2025 Vsevolod Stakhov * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -755,9 +755,17 @@ static const struct luaL_reg int64lib_m[] = { {NULL, NULL}}; LUA_FUNCTION_DEF(ev_base, loop); +LUA_FUNCTION_DEF(ev_base, update_time); +LUA_FUNCTION_DEF(ev_base, timestamp); +LUA_FUNCTION_DEF(ev_base, pending_events); +LUA_FUNCTION_DEF(ev_base, add_periodic); static const struct luaL_reg ev_baselib_m[] = { LUA_INTERFACE_DEF(ev_base, loop), + LUA_INTERFACE_DEF(ev_base, update_time), + LUA_INTERFACE_DEF(ev_base, timestamp), + LUA_INTERFACE_DEF(ev_base, pending_events), + LUA_INTERFACE_DEF(ev_base, add_periodic), {"__tostring", rspamd_lua_class_tostring}, {NULL, NULL}}; @@ -3611,3 +3619,106 @@ lua_ev_base_loop(lua_State *L) return 1; } + +static int +lua_ev_base_update_time(lua_State *L) +{ + struct ev_loop *ev_base; + + ev_base = lua_check_ev_base(L, 1); + ev_now_update_if_cheap(ev_base); + + lua_pushnumber(L, ev_time()); + + return 1; +} + +static int +lua_ev_base_timestamp(lua_State *L) +{ + struct ev_loop *ev_base; + + ev_base = lua_check_ev_base(L, 1); + lua_pushnumber(L, ev_now(ev_base)); + + return 1; +} + +static int +lua_ev_base_pending_events(lua_State *L) +{ + struct ev_loop *ev_base; + + ev_base = lua_check_ev_base(L, 1); + lua_pushnumber(L, ev_pending_count(ev_base)); + + return 1; +} + +struct rspamd_ev_base_cbdata { + lua_State *L; + int cbref; + ev_timer ev; +}; + +static void +lua_ev_base_cb(struct ev_loop *loop, struct ev_timer *t, int events) +{ + struct rspamd_ev_base_cbdata *cbdata = (struct rspamd_ev_base_cbdata *) t->data; + lua_State *L; + bool schedule_more = false; + + L = cbdata->L; + + lua_pushcfunction(L, &rspamd_lua_traceback); + int err_idx = lua_gettop(L); + lua_rawgeti(L, LUA_REGISTRYINDEX, cbdata->cbref); + + if (lua_pcall(L, 0, 1, err_idx) != 0) { + msg_err("call to periodic " + "script failed: %s", + lua_tostring(L, -1)); + } + else { + if (lua_isnumber(L, -1)) { + schedule_more = true; + ev_timer_set(&cbdata->ev, lua_tonumber(L, -1), 0.0); + } + } + + if (schedule_more) { + ev_timer_again(loop, t); + } + else { + /* Cleanup */ + ev_timer_stop(loop, t); + luaL_unref(L, LUA_REGISTRYINDEX, cbdata->cbref); + g_free(cbdata); + } +} + +static int +lua_ev_base_add_periodic(lua_State *L) +{ + struct ev_loop *ev_base; + + ev_base = lua_check_ev_base(L, 1); + if (!lua_isfunction(L, 3)) { + return luaL_error(L, "invalid arguments: callback expected"); + } + + if (!lua_isnumber(L, 2)) { + return luaL_error(L, "invalid arguments: timeout expected"); + } + + struct rspamd_ev_base_cbdata *cbdata = g_malloc(sizeof(*cbdata)); + cbdata->L = L; + lua_pushvalue(L, 3); + cbdata->ev.data = cbdata; + cbdata->cbref = luaL_ref(L, LUA_REGISTRYINDEX); + + ev_timer_init(&cbdata->ev, lua_ev_base_cb, lua_tonumber(L, 2), 0.0); + ev_timer_start(ev_base, &cbdata->ev); + + return 0; +}
\ No newline at end of file |