This commit is contained in:
root
2026-06-15 21:42:50 +00:00
parent 34a97e2577
commit 99cd92fb4a
126 changed files with 1615 additions and 1057 deletions
+29 -14
View File
@@ -20,10 +20,16 @@ pid_t proactive_compiler_pid = 0;
// The central WS broker process: owns the WS port + every connection, forwards
// renders to the worker pool over uce.sock, and applies ws_* commands flushed
// back from workers. ws_broker_outbound holds in-flight async render
// connections (fd -> bytes still to write; empty value means draining the reply).
// connections and their enqueue timestamps.
struct WsBrokerOutbound
{
String pending;
f64 started_at;
};
FastCGIServer ws_broker;
pid_t ws_broker_pid = 0;
std::map<int, String> ws_broker_outbound;
std::map<int, WsBrokerOutbound> ws_broker_outbound;
static sigjmp_buf request_fault_jmp;
static volatile sig_atomic_t request_fault_active = 0;
static volatile sig_atomic_t request_fault_signal = 0;
@@ -768,11 +774,11 @@ int custom_server_bind_http(FastCGIServer& dispatcher, String bind)
if(custom_server_is_numeric_port(bind))
{
u64 port = int_val(bind);
u64 min_port = config_map_u64(server_state.config, "CUSTOM_SERVER_MIN_PORT", 1024);
u64 max_port = config_map_u64(server_state.config, "CUSTOM_SERVER_MAX_PORT", 65535);
u64 min_port = to_u64(server_state.config["CUSTOM_SERVER_MIN_PORT"], 1024);
u64 max_port = to_u64(server_state.config["CUSTOM_SERVER_MAX_PORT"], 65535);
if(port < min_port || port > max_port)
throw std::runtime_error("server_start_http(): TCP port is outside configured custom server range");
String bind_address = config_map_bool(server_state.config, "CUSTOM_SERVER_ALLOW_PUBLIC_BIND", false) ? "0.0.0.0" : "127.0.0.1";
String bind_address = to_bool(server_state.config["CUSTOM_SERVER_ALLOW_PUBLIC_BIND"], false) ? "0.0.0.0" : "127.0.0.1";
return(dispatcher.listen_http((unsigned)port, bind_address));
}
String socket_prefix = first(server_state.config["CUSTOM_SERVER_UNIX_SOCKET_PREFIX"], "/tmp/uce/custom-servers/");
@@ -836,7 +842,7 @@ int custom_server_http_complete(FastCGIRequest& request)
request.params["UCE_SERVE_HTTP_BIND"] = cfg["bind"];
request.params["UCE_SERVE_HTTP_FUNCTION"] = cfg["function"];
request.params["SCRIPT_FILENAME"] = cfg["file"];
u64 timeout = config_map_u64(server_state.config, "CUSTOM_SERVER_HANDLER_TIMEOUT_SECONDS", 30);
u64 timeout = to_u64(server_state.config["CUSTOM_SERVER_HANDLER_TIMEOUT_SECONDS"], 30);
return(forward_request_to_worker(request, timeout > 0 ? (u32)timeout : 30));
}
@@ -942,20 +948,28 @@ int ws_broker_ws_message(FastCGIRequest& request, const String& message, u8 opco
int fd = ws_broker_connect_unix(first(server_state.config["FCGI_SOCKET_PATH"], "/run/uce.sock"));
if(fd < 0)
return(0);
ws_broker_outbound[fd] = fcgi_build_request(params, "");
ws_broker_outbound[fd] = {fcgi_build_request(params, ""), time_precise()};
return(0);
}
// Drive in-flight render forwards non-blocking: finish writing the request, then
// drain/discard the reply (the unit's ws_* came back via the command socket).
void ws_broker_drain_outbound()
void ws_broker_drain_outbound(u64 timeout_seconds)
{
f64 now = time_precise();
for(auto it = ws_broker_outbound.begin(); it != ws_broker_outbound.end(); )
{
int fd = it->first;
String& pending = it->second;
WsBrokerOutbound& outbound = it->second;
String& pending = outbound.pending;
bool done = false;
if(!pending.empty())
bool timed_out = timeout_seconds > 0 && now - outbound.started_at > (f64)timeout_seconds;
if(timed_out)
{
fprintf(stderr, "ws broker dropping stale outbound forward fd=%i after %.1fs\n", fd, now - outbound.started_at);
done = true;
}
if(!done && !pending.empty())
{
ssize_t n = ::send(fd, pending.data(), pending.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
if(n > 0)
@@ -997,6 +1011,7 @@ void run_ws_broker()
ws_broker.on_websocket_message = &ws_broker_ws_message;
if(server_state.config["HTTP_PORT"] != "")
ws_broker.listen_http(int_val(server_state.config["HTTP_PORT"]));
u64 ws_broker_outbound_timeout_seconds = to_u64(server_state.config["WS_BROKER_OUTBOUND_TIMEOUT_SECONDS"], 30);
if(server_state.config["WS_BROKER_SOCKET_PATH"] != "")
{
ws_broker.listen(server_state.config["WS_BROKER_SOCKET_PATH"]);
@@ -1005,7 +1020,7 @@ void run_ws_broker()
for(;;)
{
ws_broker.process(50);
ws_broker_drain_outbound();
ws_broker_drain_outbound(ws_broker_outbound_timeout_seconds);
}
}
@@ -1094,7 +1109,7 @@ pid_t server_start_http(String key, String socket_fn_or_port, String call_uce_fi
previous_config = custom_server_config_decode(file_get_contents(config_file));
String new_config = custom_server_config_encode(key, "http", socket_fn_or_port, call_uce_filename, call_function);
String task_key = custom_server_task_key(key);
u64 max_servers = config_map_u64(server_state.config, "CUSTOM_SERVER_MAX_SERVERS", 16);
u64 max_servers = to_u64(server_state.config["CUSTOM_SERVER_MAX_SERVERS"], 16);
if(!file_exists(config_file) && max_servers > 0 && custom_server_registry_count() >= max_servers)
throw std::runtime_error("server_start_http(): custom server quota exceeded");
pid_t existing_pid = task_pid(task_key);
@@ -1146,7 +1161,7 @@ void run_proactive_compiler()
StringList compile_queue;
background_context.server = &server_state;
set_active_request(background_context);
if(!config_map_bool(server_state.config, "PROACTIVE_COMPILE_ENABLED", true))
if(!to_bool(server_state.config["PROACTIVE_COMPILE_ENABLED"], true))
return;
f64 check_interval = float_val(server_state.config["PROACTIVE_COMPILE_CHECK_INTERVAL"]);
f64 failure_retry_interval = 0;
@@ -1276,7 +1291,7 @@ bool proactive_compiler_alive()
void ensure_proactive_compiler()
{
if(!config_map_bool(server_state.config, "PROACTIVE_COMPILE_ENABLED", true))
if(!to_bool(server_state.config["PROACTIVE_COMPILE_ENABLED"], true))
return;
if(float_val(server_state.config["PROACTIVE_COMPILE_CHECK_INTERVAL"]) <= 0)
return;