Add OnServerHeartbeat to Redbean (#522)

This commit is contained in:
Paul Kulchenko 2022-08-02 20:41:44 -07:00 committed by GitHub
parent 066ed2b2b2
commit 42bd79a461
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 30 additions and 5 deletions

View file

@ -554,6 +554,12 @@ HOOKS
each time redbean reaps a child connection process using wait4(). each time redbean reaps a child connection process using wait4().
This won't be called in uniprocess mode. This won't be called in uniprocess mode.
OnServerHeartbeat()
If this function is defined it'll be called from the main process
on each server heartbeat. The heartbeat interval is configurable
with ProgramHeartbeatInterval. If this hook is defined, then
`/.heartbeat.lua` is not called.
OnServerListen(socketdescriptor:int,serverip:int,serverport:int) → bool OnServerListen(socketdescriptor:int,serverip:int,serverport:int) → bool
If this function is defined it'll be called from the main process If this function is defined it'll be called from the main process
before redbean starts listening on a port. This hook can be used before redbean starts listening on a port. This hook can be used
@ -1368,6 +1374,10 @@ FUNCTIONS
as Content-Range and Date, which are abstracted by the transport as Content-Range and Date, which are abstracted by the transport
layer. layer.
ProgramHeartbeatInterval(milliseconds:int)
Sets the heartbeat interval (in milliseconds). 5000ms is the default
and 100ms is the minimum.
ProgramTimeout(milliseconds:int|seconds:int) ProgramTimeout(milliseconds:int|seconds:int)
Default timeout is 60000ms. Minimal value of timeout is 10(ms). Default timeout is 60000ms. Minimal value of timeout is 10(ms).
Negative values (<0) sets the keepalive in seconds. Negative values (<0) sets the keepalive in seconds.

View file

@ -150,7 +150,6 @@ STATIC_YOINK("ShowCrashReportsEarly");
#endif #endif
#define VERSION 0x02000f #define VERSION 0x02000f
#define HEARTBEAT 5000 /*ms*/
#define HASH_LOAD_FACTOR /* 1. / */ 4 #define HASH_LOAD_FACTOR /* 1. / */ 4
#define MONITOR_MICROS 150000 #define MONITOR_MICROS 150000
#define READ(F, P, N) readv(F, &(struct iovec){P, N}, 1) #define READ(F, P, N) readv(F, &(struct iovec){P, N}, 1)
@ -418,6 +417,7 @@ static int sslpskindex;
static int oldloglevel; static int oldloglevel;
static int messageshandled; static int messageshandled;
static int sslticketlifetime; static int sslticketlifetime;
static int heartbeatint = 5000; // ms
static uint32_t clientaddrsize; static uint32_t clientaddrsize;
static size_t zsize; static size_t zsize;
@ -4737,6 +4737,16 @@ static int LuaProgramUniprocess(lua_State *L) {
return 1; return 1;
} }
static int LuaProgramHeartbeatInterval(lua_State *L) {
OnlyCallFromMainProcess(L, "ProgramHeartbeatInterval");
if (!lua_isinteger(L, 1) && !lua_isnoneornil(L, 1)) {
return luaL_argerror(L, 1, "invalid heartbeat interval; integer expected");
}
lua_pushinteger(L, heartbeatint);
if (lua_isinteger(L, 1)) heartbeatint = MAX(100, lua_tointeger(L, 1));
return 1;
}
static int LuaProgramAddr(lua_State *L) { static int LuaProgramAddr(lua_State *L) {
uint32_t ip; uint32_t ip;
OnlyCallFromInitLua(L, "ProgramAddr"); OnlyCallFromInitLua(L, "ProgramAddr");
@ -5218,6 +5228,7 @@ static const luaL_Reg kLuaFuncs[] = {
{"ProgramDirectory", LuaProgramDirectory}, // {"ProgramDirectory", LuaProgramDirectory}, //
{"ProgramGid", LuaProgramGid}, // {"ProgramGid", LuaProgramGid}, //
{"ProgramHeader", LuaProgramHeader}, // {"ProgramHeader", LuaProgramHeader}, //
{"ProgramHeartbeatInterval", LuaProgramHeartbeatInterval}, //
{"ProgramLogBodies", LuaProgramLogBodies}, // {"ProgramLogBodies", LuaProgramLogBodies}, //
{"ProgramLogMessages", LuaProgramLogMessages}, // {"ProgramLogMessages", LuaProgramLogMessages}, //
{"ProgramLogPath", LuaProgramLogPath}, // {"ProgramLogPath", LuaProgramLogPath}, //
@ -5734,7 +5745,11 @@ static void HandleHeartbeat(void) {
Reindex(); Reindex();
getrusage(RUSAGE_SELF, &shared->server); getrusage(RUSAGE_SELF, &shared->server);
#ifndef STATIC #ifndef STATIC
LuaRunAsset("/.heartbeat.lua", false); if (IsHookDefined("OnServerHeartbeat")) {
CallSimpleHook("OnServerHeartbeat");
} else {
LuaRunAsset("/.heartbeat.lua", false);
}
CollectGarbage(); CollectGarbage();
#endif #endif
for (i = 1; i < servers.n; ++i) { for (i = 1; i < servers.n; ++i) {
@ -7066,7 +7081,7 @@ static int EventLoop(int ms) {
EnterMeltdownMode(); EnterMeltdownMode();
lua_repl_unlock(); lua_repl_unlock();
meltdown = false; meltdown = false;
} else if ((t = nowl()) - lastheartbeat > HEARTBEAT / 1000.) { } else if ((t = nowl()) - lastheartbeat > heartbeatint / 1000.) {
lastheartbeat = t; lastheartbeat = t;
HandleHeartbeat(); HandleHeartbeat();
} else if (HandlePoll(ms) == -1) { } else if (HandlePoll(ms) == -1) {
@ -7366,12 +7381,12 @@ void RedBean(int argc, char *argv[]) {
} }
} }
#ifdef STATIC #ifdef STATIC
EventLoop(HEARTBEAT); EventLoop(heartbeatint);
#else #else
GetHostsTxt(); // for effect GetHostsTxt(); // for effect
GetResolvConf(); // for effect GetResolvConf(); // for effect
if (daemonize || uniprocess || !linenoiseIsTerminal()) { if (daemonize || uniprocess || !linenoiseIsTerminal()) {
EventLoop(HEARTBEAT); EventLoop(heartbeatint);
} else if (IsWindows()) { } else if (IsWindows()) {
CHECK_NE(-1, _spawn(WindowsReplThread, 0, &replth)); CHECK_NE(-1, _spawn(WindowsReplThread, 0, &replth));
EventLoop(100); EventLoop(100);