Ensure nested CLI components are fresh
This commit is contained in:
@@ -146,9 +146,10 @@ a stale entry artifact: they return `503 Service Unavailable` with
|
|||||||
`Retry-After: 1`, allowing the client to retry after the priority rebuild.
|
`Retry-After: 1`, allowing the client to retry after the priority rebuild.
|
||||||
CLI and explicit compile paths remain synchronous. A failed rebuild removes
|
CLI and explicit compile paths remain synchronous. A failed rebuild removes
|
||||||
availability and surfaces the compiler error rather than serving the old unit
|
availability and surfaces the compiler error rather than serving the old unit
|
||||||
indefinitely. The per-unit lock also keeps concurrent synchronous compilers
|
indefinitely. This freshness contract includes components resolved lazily from
|
||||||
from waiting across a transitive graph when a last complete artifact is
|
an otherwise-current CLI entry unit: if the proactive compiler already owns a
|
||||||
available.
|
stale child's lock, the CLI request joins that compile and waits for the fresh
|
||||||
|
artifact. Read-only HTTP may use the child's last complete artifact instead.
|
||||||
|
|
||||||
Before preprocessing, the compiler verifies that the worker can actually read
|
Before preprocessing, the compiler verifies that the worker can actually read
|
||||||
the source. An unreadable path is reported as a source-read failure with a
|
the source. An unreadable path is reported as a source-read failure with a
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ mutation_file="/tmp/uce-dependency-mutation-$$"
|
|||||||
post_body="/tmp/uce-dependency-post-body-$$"
|
post_body="/tmp/uce-dependency-post-body-$$"
|
||||||
post_headers="/tmp/uce-dependency-post-headers-$$"
|
post_headers="/tmp/uce-dependency-post-headers-$$"
|
||||||
lock_ready_file="/tmp/uce-dependency-lock-ready-$$"
|
lock_ready_file="/tmp/uce-dependency-lock-ready-$$"
|
||||||
|
nested_lock_ready_file="/tmp/uce-nested-lock-ready-$$"
|
||||||
race_output="/tmp/uce-source-race-output-$$"
|
race_output="/tmp/uce-source-race-output-$$"
|
||||||
race_error="/tmp/uce-source-race-error-$$"
|
race_error="/tmp/uce-source-race-error-$$"
|
||||||
race_status="/tmp/uce-source-race-status-$$"
|
race_status="/tmp/uce-source-race-status-$$"
|
||||||
@@ -31,7 +32,7 @@ cleanup() {
|
|||||||
if [[ -n "$cache_dir" ]]; then
|
if [[ -n "$cache_dir" ]]; then
|
||||||
rm -rf "$cache_dir"
|
rm -rf "$cache_dir"
|
||||||
fi
|
fi
|
||||||
rm -f "$mutation_file" "$post_body" "$post_headers" "$lock_ready_file" "$race_output" "$race_error" "$race_status"
|
rm -f "$mutation_file" "$post_body" "$post_headers" "$lock_ready_file" "$nested_lock_ready_file" "$race_output" "$race_error" "$race_status"
|
||||||
}
|
}
|
||||||
trap cleanup EXIT
|
trap cleanup EXIT
|
||||||
mkdir -p "$source_dir"
|
mkdir -p "$source_dir"
|
||||||
@@ -175,6 +176,47 @@ if (( elapsed_ms < 2000 )); then
|
|||||||
fi
|
fi
|
||||||
wait "$rebuild_lock_pid"
|
wait "$rebuild_lock_pid"
|
||||||
|
|
||||||
|
# CLI freshness applies to every nested component, not only the request entry
|
||||||
|
# unit. Hold the changed child's compile lock as a proactive rebuild would: the
|
||||||
|
# parent CLI request must wait and render the new child, never its stale wasm.
|
||||||
|
printf '%s\n' 'COMPONENT(Request& context) { print("nested-component-marker-a"); }' >"$source_dir/nested-child.uce"
|
||||||
|
printf '%s\n' \
|
||||||
|
'CLI(Request& context) { DValue props; print(component("nested-child", props, context)); }' >"$source_dir/nested-parent.uce"
|
||||||
|
assert_marker nested-parent nested-component-marker-a
|
||||||
|
nested_child_wasm="$cache_dir/nested-child.uce.wasm"
|
||||||
|
(
|
||||||
|
exec 8>"$nested_child_wasm.lock"
|
||||||
|
flock 8
|
||||||
|
: >"$nested_lock_ready_file"
|
||||||
|
sleep 3
|
||||||
|
) &
|
||||||
|
nested_lock_pid=$!
|
||||||
|
deadline=$((SECONDS + 5))
|
||||||
|
while [[ ! -e "$nested_lock_ready_file" && $SECONDS -lt $deadline ]]; do
|
||||||
|
if ! kill -0 "$nested_lock_pid" 2>/dev/null; then
|
||||||
|
echo "nested component lock exited before acquisition" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
sleep 0.05
|
||||||
|
done
|
||||||
|
if [[ ! -e "$nested_lock_ready_file" ]]; then
|
||||||
|
echo "nested component lock was not acquired before deadline" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
sed -i 's/nested-component-marker-a/nested-component-marker-b/' "$source_dir/nested-child.uce"
|
||||||
|
started_at=$(date +%s%N)
|
||||||
|
nested_output=$(scripts/uce-cli "/$test_name/nested-parent.uce")
|
||||||
|
elapsed_ms=$(( ($(date +%s%N) - started_at) / 1000000 ))
|
||||||
|
wait "$nested_lock_pid"
|
||||||
|
if [[ "$nested_output" != *"nested-component-marker-b"* ]]; then
|
||||||
|
echo "CLI nested component returned stale wasm: $nested_output" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if (( elapsed_ms < 2000 )); then
|
||||||
|
echo "CLI nested component did not wait for the active rebuild (${elapsed_ms}ms)" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# 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.
|
||||||
for _ in {1..16}; do assert_marker parent dependency-marker-d; done
|
for _ in {1..16}; do assert_marker parent dependency-marker-d; done
|
||||||
|
|||||||
+3
-2
@@ -1612,9 +1612,10 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool stale = compiler_unit_needs_recompile(context, resolved, 0);
|
bool stale = compiler_unit_needs_recompile(context, resolved, 0);
|
||||||
if(stale && compiler_request_can_serve_stale_artifact(context))
|
bool can_serve_stale = compiler_request_can_serve_stale_artifact(context);
|
||||||
|
if(stale && can_serve_stale)
|
||||||
compiler_prioritize_unit(context, resolved);
|
compiler_prioritize_unit(context, resolved);
|
||||||
if(!file_exists_host(worker.unit_wasm_path(resolved)) || (stale && !compiler_request_can_serve_stale_artifact(context) && !compiler_unit_compile_in_progress(context, resolved)))
|
if(!file_exists_host(worker.unit_wasm_path(resolved)) || (stale && !can_serve_stale))
|
||||||
get_shared_unit(context, resolved);
|
get_shared_unit(context, resolved);
|
||||||
|
|
||||||
size_t unit_index = 0;
|
size_t unit_index = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user