docs
This commit is contained in:
+23
-20
@@ -1,7 +1,7 @@
|
||||
// W4 — FastCGI backend glue for the W3 wasm workspace runtime.
|
||||
//
|
||||
// Included into the native server TU (src/linux_fastcgi.cpp) after uce_lib.cpp,
|
||||
// so it shares String/DValue/config and the UCEB1 codec. Provides a
|
||||
// so it shares String/DValue/config and the UCEB2 codec. Provides a
|
||||
// Always-on wasm backend: every unit request is served through a per-request
|
||||
// wasm workspace. The legacy native dlopen execution path has been removed.
|
||||
|
||||
@@ -50,9 +50,9 @@ static String wasm_backend_ensure_started(Request* context)
|
||||
for(const char* key : { "BIN_DIRECTORY", "SESSION_PATH", "TMP_UPLOAD_PATH" })
|
||||
if(cfg[key] != "")
|
||||
wc.write_roots.push_back(cfg[key]);
|
||||
wc.memory_limit = (int64_t)config_u64("WASM_MEMORY_LIMIT_BYTES", 512ull * 1024 * 1024);
|
||||
wc.epoch_deadline_ticks = config_u64("WASM_EPOCH_DEADLINE_TICKS", 200);
|
||||
wc.verbose = config_bool("WASM_BACKEND_VERBOSE", false);
|
||||
wc.memory_limit = (int64_t)to_u64(cfg["WASM_MEMORY_LIMIT_BYTES"], 512ull * 1024 * 1024);
|
||||
wc.epoch_deadline_ticks = to_u64(cfg["WASM_EPOCH_DEADLINE_TICKS"], 200);
|
||||
wc.verbose = to_bool(cfg["WASM_BACKEND_VERBOSE"], false);
|
||||
|
||||
g_wasm_worker = new WasmWorker(wc);
|
||||
g_wasm_init_error = g_wasm_worker->init();
|
||||
@@ -65,7 +65,7 @@ static String wasm_backend_ensure_started(Request* context)
|
||||
|
||||
g_wasm_epoch_running.store(true);
|
||||
WasmWorker* worker = g_wasm_worker;
|
||||
u64 period_ms = config_u64("WASM_EPOCH_PERIOD_MS", 50);
|
||||
u64 period_ms = to_u64(cfg["WASM_EPOCH_PERIOD_MS"], 50);
|
||||
g_wasm_epoch_ticker = new std::thread([worker, period_ms] {
|
||||
while(g_wasm_epoch_running.load())
|
||||
{
|
||||
@@ -84,12 +84,13 @@ static bool wasm_artifact_exists(Request* context, const String& entry_unit)
|
||||
struct stat wasm_st;
|
||||
if(stat(wasm_path.c_str(), &wasm_st) != 0 || !S_ISREG(wasm_st.st_mode))
|
||||
return(false);
|
||||
// Require the artifact to be newer than the source. If it is stale,
|
||||
// dispatch compiles the unit on demand and then rechecks this predicate.
|
||||
struct stat src_st;
|
||||
if(stat(entry_unit.c_str(), &src_st) != 0 || !S_ISREG(src_st.st_mode))
|
||||
// Require the artifact to satisfy the full compiler freshness check. Source
|
||||
// mtime alone misses runtime/unit ABI changes, setup-template changes, and
|
||||
// metadata mismatches, which can leave stale wasm with old imports.
|
||||
bool source_missing = false;
|
||||
if(compiler_unit_needs_recompile(context, entry_unit, &source_missing))
|
||||
return(false);
|
||||
if(wasm_st.st_mtime < src_st.st_mtime)
|
||||
if(source_missing)
|
||||
return(false);
|
||||
return(true);
|
||||
}
|
||||
@@ -151,23 +152,25 @@ String wasm_backend_serve(Request& request, const String& entry_unit, const Stri
|
||||
if(!response.ok)
|
||||
return(response.error == "" ? String("wasm workspace failed") : response.error);
|
||||
|
||||
// Any handler may have called ws_send/ws_close (not just WS handlers). If it
|
||||
// left dispatch commands, flush the batch to the central WS broker, which owns
|
||||
// all connections and resolves each command's target (id/scope/broadcast)
|
||||
// against the full registry. This is the only path WS data takes out — the
|
||||
// workspace owns no connections.
|
||||
if(DValue* cmds = response.meta.key("ws_commands"))
|
||||
// Any handler may have called ws_send/ws_close (not just WS handlers). Flush the
|
||||
// websocket batch whenever either command frames or an updated per-connection
|
||||
// state are present. This is the only path WS data takes out; the workspace
|
||||
// owns no connections.
|
||||
DValue* cmds = response.meta.key("ws_commands");
|
||||
DValue* cstate = response.meta.key("ws_connection_state");
|
||||
if(cmds || cstate)
|
||||
{
|
||||
DValue batch;
|
||||
batch["commands"] = *cmds;
|
||||
if(DValue* cstate = response.meta.key("ws_connection_state"))
|
||||
if(cmds)
|
||||
batch["commands"] = *cmds;
|
||||
if(cstate)
|
||||
{
|
||||
batch["connection_id"] = request.resources.websocket_connection_id;
|
||||
batch["connection_state"] = *cstate;
|
||||
}
|
||||
StringMap dispatch_params;
|
||||
dispatch_params["UCE_WS_DISPATCH"] = "1";
|
||||
String broker_socket = first(request.server ? request.server->config["WS_BROKER_SOCKET_PATH"] : String(),
|
||||
String broker_socket = first(request.server->config["WS_BROKER_SOCKET_PATH"],
|
||||
"/run/uce/ws-broker.sock");
|
||||
fcgi_forward_request(broker_socket, dispatch_params, ucb_encode(batch), 5);
|
||||
}
|
||||
@@ -182,7 +185,7 @@ String wasm_backend_serve(Request& request, const String& entry_unit, const Stri
|
||||
|
||||
// Diagnostic timing headers are opt-in: they leak workspace internals and
|
||||
// belong to the W5 benchmark harness, not public responses.
|
||||
if(config_bool("WASM_BACKEND_VERBOSE", false))
|
||||
if(to_bool(request.server->config["WASM_BACKEND_VERBOSE"], false))
|
||||
{
|
||||
request.header["X-UCE-Backend"] = "wasm";
|
||||
request.header["X-UCE-Wasm-Workspace-Birth-Us"] = std::to_string(response.workspace_birth_us);
|
||||
|
||||
Reference in New Issue
Block a user