keep CLI units current during rebuilds

This commit is contained in:
udo 2026-07-13 14:20:29 +00:00
parent 97ecc6edd6
commit cd2fa163e6
4 changed files with 19 additions and 7 deletions

View File

@ -358,8 +358,9 @@ header free-functions are `inline`. The wasm backend exposes only declarations
cold component that exceeds the development epoch window and proves the cold component that exceeds the development epoch window and proves the
parent request still renders it. The dependency-invalidation gate also holds parent request still renders it. The dependency-invalidation gate also holds
parent and child compile locks across a transitive source edit, proves a parent and child compile locks across a transitive source edit, proves a
warmed request returns the last atomically published result without waiting, warmed HTTP request returns the last atomically published result without
and then proves the new dependency result appears after rebuild completion. waiting, while a CLI request waits and returns only the current dependency
result after rebuild completion.
- **WebSocket end-to-end**: a headless client performs a raw WS handshake to - **WebSocket end-to-end**: a headless client performs a raw WS handshake to
`:HTTP_PORT` with path `/site/tests/websockets.ws.uce` (self-resolving `:HTTP_PORT` with path `/site/tests/websockets.ws.uce` (self-resolving

View File

@ -84,14 +84,24 @@ rebuild_lock_pid=$!
sleep 0.2 sleep 0.2
sed -i 's/dependency-marker-b/dependency-marker-d/' "$source_dir/child.uce" sed -i 's/dependency-marker-b/dependency-marker-d/' "$source_dir/child.uce"
started_at=$(date +%s%N) started_at=$(date +%s%N)
assert_marker parent dependency-marker-b http_during_lock=$(http_marker)
elapsed_ms=$(( ($(date +%s%N) - started_at) / 1000000 )) elapsed_ms=$(( ($(date +%s%N) - started_at) / 1000000 ))
if [[ "$http_during_lock" != *"dependency-marker-b"* ]]; then
echo "HTTP request did not serve the last complete artifact during rebuild: $http_during_lock" >&2
exit 1
fi
if (( elapsed_ms >= 2000 )); then if (( elapsed_ms >= 2000 )); then
echo "request waited ${elapsed_ms}ms for an active transitive rebuild" >&2 echo "HTTP request waited ${elapsed_ms}ms for an active transitive rebuild" >&2
exit 1
fi
started_at=$(date +%s%N)
assert_marker parent dependency-marker-d
elapsed_ms=$(( ($(date +%s%N) - started_at) / 1000000 ))
if (( elapsed_ms < 2000 )); then
echo "CLI request returned before the locked rebuild published the current artifact (${elapsed_ms}ms)" >&2
exit 1 exit 1
fi fi
wait "$rebuild_lock_pid" wait "$rebuild_lock_pid"
assert_marker parent dependency-marker-d
# Warm every configured worker, then replace the artifact while retaining its # Warm every configured worker, then replace the artifact while retaining its
# whole-second mtime. The worker cache must notice the nanosecond/ctime change. # whole-second mtime. The worker cache must notice the nanosecond/ctime change.

View File

@ -850,7 +850,8 @@ SharedUnit* compiler_get_shared_unit_internal(Request* context, String file_name
SharedUnit* su = new SharedUnit(); SharedUnit* su = new SharedUnit();
setup_unit_paths(context, su, file_name); setup_unit_paths(context, su, file_name);
int fdlock = compiler_open_lock_file(su->wasm_name + ".lock", "shared-unit:" + file_name, !force_recompile); bool can_serve_stale = !force_recompile && compiler_request_can_serve_stale_artifact(context);
int fdlock = compiler_open_lock_file(su->wasm_name + ".lock", "shared-unit:" + file_name, can_serve_stale);
if(fdlock == -2 && file_exists(su->wasm_name)) if(fdlock == -2 && file_exists(su->wasm_name))
{ {
auto state = inspect_shared_unit_filesystem(context, su); auto state = inspect_shared_unit_filesystem(context, su);

View File

@ -100,7 +100,7 @@ static bool wasm_artifact_exists(Request* context, const String& entry_unit)
// metadata mismatches, which can leave stale wasm with old imports. // metadata mismatches, which can leave stale wasm with old imports.
bool source_missing = false; bool source_missing = false;
if(compiler_unit_needs_recompile(context, entry_unit, &source_missing)) if(compiler_unit_needs_recompile(context, entry_unit, &source_missing))
return(compiler_request_can_serve_stale_artifact(context) || compiler_unit_compile_in_progress(context, entry_unit)); return(compiler_request_can_serve_stale_artifact(context));
if(source_missing) if(source_missing)
return(false); return(false);
return(true); return(true);