test: reuse browser sync probe session
This commit is contained in:
parent
ba2514021c
commit
ed63827ae0
16
AGENTS.md
16
AGENTS.md
@ -344,3 +344,19 @@ Context: 0.17.14 can keep one Lesavka session alive across multiple measured seg
|
|||||||
- [x] Update manual probe contract tests for the adaptive artifacts and controls.
|
- [x] Update manual probe contract tests for the adaptive artifacts and controls.
|
||||||
- [x] Run focused script checks and package checks.
|
- [x] Run focused script checks and package checks.
|
||||||
- [x] Push clean semver `0.17.15` for installed client/server testing.
|
- [x] Push clean semver `0.17.15` for installed client/server testing.
|
||||||
|
|
||||||
|
## 0.17.16 Continuous Browser Evidence Checklist
|
||||||
|
|
||||||
|
Context: 0.17.15 proved the adaptive/live-edit loop is structurally useful, but each segment restarted the Tethys browser/getUserMedia receiver. That contaminates calibration segments with receiver startup noise and keeps usable coded pairs too low (`3-5` pairs instead of the `8+` needed for safe calibration). 0.17.16 is scoped to making the probe evidence continuous and attributable before any more media playout changes.
|
||||||
|
|
||||||
|
- [x] Keep 0.17.16 scoped to probe/tooling reliability; do not change server media playout policy, freshness ceilings, queue policy, or UAC smoothness.
|
||||||
|
- [x] Make adaptive mirrored runs keep one Tethys browser/getUserMedia session alive after the first segment.
|
||||||
|
- [x] Preserve single-segment/manual probe behavior by default.
|
||||||
|
- [x] Add an explicit `BROWSER_CONSUMER_REUSE_SESSION` control to the browser probe runner.
|
||||||
|
- [x] Verify browser uploads by start token so the fetched WebM belongs to the segment just triggered.
|
||||||
|
- [x] Track browser upload counts/tokens in `browser_consumer_probe.py` status JSON for post-run debugging.
|
||||||
|
- [x] Wire adaptive mirrored mode to reuse the existing Tethys receiver for segments 2+.
|
||||||
|
- [x] Keep calibration mutation behind the existing analyzer `calibration.ready=true` gate.
|
||||||
|
- [x] Update manual probe contract tests for continuous browser session behavior.
|
||||||
|
- [x] Run shell syntax checks, focused contract tests, and package checks.
|
||||||
|
- [ ] Push clean semver `0.17.16` for installed client/server testing.
|
||||||
|
|||||||
6
Cargo.lock
generated
6
Cargo.lock
generated
@ -1652,7 +1652,7 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lesavka_client"
|
name = "lesavka_client"
|
||||||
version = "0.17.15"
|
version = "0.17.16"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-stream",
|
"async-stream",
|
||||||
@ -1686,7 +1686,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lesavka_common"
|
name = "lesavka_common"
|
||||||
version = "0.17.15"
|
version = "0.17.16"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"base64",
|
"base64",
|
||||||
@ -1698,7 +1698,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lesavka_server"
|
name = "lesavka_server"
|
||||||
version = "0.17.15"
|
version = "0.17.16"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"base64",
|
"base64",
|
||||||
|
|||||||
@ -4,7 +4,7 @@ path = "src/main.rs"
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "lesavka_client"
|
name = "lesavka_client"
|
||||||
version = "0.17.15"
|
version = "0.17.16"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "lesavka_common"
|
name = "lesavka_common"
|
||||||
version = "0.17.15"
|
version = "0.17.16"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import json
|
|||||||
import socketserver
|
import socketserver
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
|
import urllib.parse
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
@ -36,6 +37,9 @@ class ProbeState:
|
|||||||
"devices": [],
|
"devices": [],
|
||||||
"page_message": "booting",
|
"page_message": "booting",
|
||||||
"last_update": time.time(),
|
"last_update": time.time(),
|
||||||
|
"active_start_token": 0,
|
||||||
|
"uploaded_start_token": None,
|
||||||
|
"upload_count": 0,
|
||||||
}
|
}
|
||||||
self.write_status()
|
self.write_status()
|
||||||
|
|
||||||
@ -62,6 +66,8 @@ class ProbeState:
|
|||||||
with self.lock:
|
with self.lock:
|
||||||
self.start_token += 1
|
self.start_token += 1
|
||||||
self.status.update({
|
self.status.update({
|
||||||
|
"active_start_token": self.start_token,
|
||||||
|
"uploaded_start_token": None,
|
||||||
"recording": False,
|
"recording": False,
|
||||||
"uploaded": False,
|
"uploaded": False,
|
||||||
"last_error": None,
|
"last_error": None,
|
||||||
@ -71,12 +77,15 @@ class ProbeState:
|
|||||||
self.write_status()
|
self.write_status()
|
||||||
return self.snapshot()
|
return self.snapshot()
|
||||||
|
|
||||||
def store_upload(self, blob: bytes) -> dict:
|
def store_upload(self, blob: bytes, start_token: int | None) -> dict:
|
||||||
with self.lock:
|
with self.lock:
|
||||||
self.output_path.parent.mkdir(parents=True, exist_ok=True)
|
self.output_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
self.output_path.write_bytes(blob)
|
self.output_path.write_bytes(blob)
|
||||||
|
upload_count = int(self.status.get("upload_count") or 0) + 1
|
||||||
self.status.update({
|
self.status.update({
|
||||||
"uploaded": True,
|
"uploaded": True,
|
||||||
|
"uploaded_start_token": start_token,
|
||||||
|
"upload_count": upload_count,
|
||||||
"recording": False,
|
"recording": False,
|
||||||
"page_message": f"capture uploaded to {self.output_path}",
|
"page_message": f"capture uploaded to {self.output_path}",
|
||||||
"upload_size": len(blob),
|
"upload_size": len(blob),
|
||||||
@ -224,7 +233,7 @@ async function maybeStartRecording() {{
|
|||||||
recorder.ondataavailable = event => {{ if (event.data && event.data.size > 0) chunks.push(event.data); }};
|
recorder.ondataavailable = event => {{ if (event.data && event.data.size > 0) chunks.push(event.data); }};
|
||||||
recorder.onstop = async () => {{
|
recorder.onstop = async () => {{
|
||||||
const blob = new Blob(chunks, {{ type: recorder.mimeType || 'video/webm' }});
|
const blob = new Blob(chunks, {{ type: recorder.mimeType || 'video/webm' }});
|
||||||
await postBlob('/upload', blob);
|
await postBlob('/upload?start_token=' + encodeURIComponent(startToken), blob);
|
||||||
recording = false;
|
recording = false;
|
||||||
}};
|
}};
|
||||||
recorder.start(250);
|
recorder.start(250);
|
||||||
@ -257,7 +266,8 @@ class ProbeHandler(http.server.BaseHTTPRequestHandler):
|
|||||||
self.wfile.write(body)
|
self.wfile.write(body)
|
||||||
|
|
||||||
def do_GET(self) -> None:
|
def do_GET(self) -> None:
|
||||||
if self.path in ("/", "/index.html"):
|
parsed = urllib.parse.urlparse(self.path)
|
||||||
|
if parsed.path in ("/", "/index.html"):
|
||||||
snap = self.state.snapshot()
|
snap = self.state.snapshot()
|
||||||
self.state.update({
|
self.state.update({
|
||||||
"page_message": "html served",
|
"page_message": "html served",
|
||||||
@ -265,27 +275,35 @@ class ProbeHandler(http.server.BaseHTTPRequestHandler):
|
|||||||
})
|
})
|
||||||
self._send(200, page_html(self.state.duration_seconds).encode("utf-8"), "text/html; charset=utf-8")
|
self._send(200, page_html(self.state.duration_seconds).encode("utf-8"), "text/html; charset=utf-8")
|
||||||
return
|
return
|
||||||
if self.path == "/command":
|
if parsed.path == "/command":
|
||||||
self._send(200, json.dumps(self.state.snapshot()).encode("utf-8"))
|
self._send(200, json.dumps(self.state.snapshot()).encode("utf-8"))
|
||||||
return
|
return
|
||||||
if self.path == "/status":
|
if parsed.path == "/status":
|
||||||
self._send(200, json.dumps(self.state.snapshot()).encode("utf-8"))
|
self._send(200, json.dumps(self.state.snapshot()).encode("utf-8"))
|
||||||
return
|
return
|
||||||
self._send(404, b"not found", "text/plain; charset=utf-8")
|
self._send(404, b"not found", "text/plain; charset=utf-8")
|
||||||
|
|
||||||
def do_POST(self) -> None:
|
def do_POST(self) -> None:
|
||||||
|
parsed = urllib.parse.urlparse(self.path)
|
||||||
length = int(self.headers.get("Content-Length", "0"))
|
length = int(self.headers.get("Content-Length", "0"))
|
||||||
body = self.rfile.read(length)
|
body = self.rfile.read(length)
|
||||||
if self.path == "/status":
|
if parsed.path == "/status":
|
||||||
payload = json.loads(body.decode("utf-8"))
|
payload = json.loads(body.decode("utf-8"))
|
||||||
self.state.update(payload)
|
self.state.update(payload)
|
||||||
self._send(200, json.dumps(self.state.snapshot()).encode("utf-8"))
|
self._send(200, json.dumps(self.state.snapshot()).encode("utf-8"))
|
||||||
return
|
return
|
||||||
if self.path == "/start":
|
if parsed.path == "/start":
|
||||||
self._send(200, json.dumps(self.state.request_start()).encode("utf-8"))
|
self._send(200, json.dumps(self.state.request_start()).encode("utf-8"))
|
||||||
return
|
return
|
||||||
if self.path == "/upload":
|
if parsed.path == "/upload":
|
||||||
self._send(200, json.dumps(self.state.store_upload(body)).encode("utf-8"))
|
query = urllib.parse.parse_qs(parsed.query)
|
||||||
|
start_token = None
|
||||||
|
if query.get("start_token"):
|
||||||
|
try:
|
||||||
|
start_token = int(query["start_token"][0])
|
||||||
|
except ValueError:
|
||||||
|
start_token = None
|
||||||
|
self._send(200, json.dumps(self.state.store_upload(body, start_token)).encode("utf-8"))
|
||||||
return
|
return
|
||||||
self._send(404, b"not found", "text/plain; charset=utf-8")
|
self._send(404, b"not found", "text/plain; charset=utf-8")
|
||||||
|
|
||||||
|
|||||||
@ -15,6 +15,7 @@ LESAVKA_SERVER_ADDR=${LESAVKA_SERVER_ADDR:-https://38.28.125.112:50051}
|
|||||||
PROBE_DURATION_SECONDS=${PROBE_DURATION_SECONDS:-15}
|
PROBE_DURATION_SECONDS=${PROBE_DURATION_SECONDS:-15}
|
||||||
BROWSER_RECORD_SECONDS=${BROWSER_RECORD_SECONDS:-${PROBE_DURATION_SECONDS}}
|
BROWSER_RECORD_SECONDS=${BROWSER_RECORD_SECONDS:-${PROBE_DURATION_SECONDS}}
|
||||||
BROWSER_SYNC_DRIVER_COMMAND=${BROWSER_SYNC_DRIVER_COMMAND:-}
|
BROWSER_SYNC_DRIVER_COMMAND=${BROWSER_SYNC_DRIVER_COMMAND:-}
|
||||||
|
BROWSER_CONSUMER_REUSE_SESSION=${BROWSER_CONSUMER_REUSE_SESSION:-0}
|
||||||
SYNC_ANALYZE_EVENT_WIDTH_CODES=${SYNC_ANALYZE_EVENT_WIDTH_CODES:-}
|
SYNC_ANALYZE_EVENT_WIDTH_CODES=${SYNC_ANALYZE_EVENT_WIDTH_CODES:-}
|
||||||
BROWSER_PORT=${BROWSER_PORT:-18443}
|
BROWSER_PORT=${BROWSER_PORT:-18443}
|
||||||
REMOTE_SCRIPT=${REMOTE_SCRIPT:-/tmp/lesavka-browser-consumer-probe.py}
|
REMOTE_SCRIPT=${REMOTE_SCRIPT:-/tmp/lesavka-browser-consumer-probe.py}
|
||||||
@ -44,7 +45,8 @@ ssh ${SSH_OPTS} "${TETHYS_HOST}" bash -s -- \
|
|||||||
"${BROWSER_RECORD_SECONDS}" \
|
"${BROWSER_RECORD_SECONDS}" \
|
||||||
"${BROWSER_PORT}" \
|
"${BROWSER_PORT}" \
|
||||||
"${DISPLAY_ENV}" \
|
"${DISPLAY_ENV}" \
|
||||||
"${REMOTE_RUNTIME_DIR}" <<'REMOTE_SETUP'
|
"${REMOTE_RUNTIME_DIR}" \
|
||||||
|
"${BROWSER_CONSUMER_REUSE_SESSION}" <<'REMOTE_SETUP'
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
remote_script=$1
|
remote_script=$1
|
||||||
remote_capture=$2
|
remote_capture=$2
|
||||||
@ -54,8 +56,22 @@ duration=$5
|
|||||||
port=$6
|
port=$6
|
||||||
display_env=$7
|
display_env=$7
|
||||||
runtime_dir=$8
|
runtime_dir=$8
|
||||||
|
reuse_session=$9
|
||||||
dbus_address=""
|
dbus_address=""
|
||||||
xauthority_path=""
|
xauthority_path=""
|
||||||
|
if [[ "${reuse_session}" == "1" ]] && status_json="$(curl --max-time 2 -fsS "http://127.0.0.1:${port}/status" 2>/dev/null)"; then
|
||||||
|
if STATUS_JSON="${status_json}" python3 - <<'PY'
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
status = json.loads(os.environ["STATUS_JSON"])
|
||||||
|
sys.exit(0 if status.get("ready") else 1)
|
||||||
|
PY
|
||||||
|
then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
firefox_pid="$(pgrep -n -x firefox-esr || true)"
|
firefox_pid="$(pgrep -n -x firefox-esr || true)"
|
||||||
if [[ -n "${firefox_pid}" && -r "/proc/${firefox_pid}/environ" ]]; then
|
if [[ -n "${firefox_pid}" && -r "/proc/${firefox_pid}/environ" ]]; then
|
||||||
while IFS='=' read -r key value; do
|
while IFS='=' read -r key value; do
|
||||||
@ -128,12 +144,22 @@ while true; do
|
|||||||
done
|
done
|
||||||
|
|
||||||
echo "==> triggering browser recording"
|
echo "==> triggering browser recording"
|
||||||
if ! ssh ${SSH_OPTS} "${TETHYS_HOST}" "curl --max-time 10 -fsS -X POST http://127.0.0.1:${BROWSER_PORT}/start >/dev/null"; then
|
start_json=""
|
||||||
|
if ! start_json="$(ssh ${SSH_OPTS} "${TETHYS_HOST}" "curl --max-time 10 -fsS -X POST http://127.0.0.1:${BROWSER_PORT}/start")"; then
|
||||||
status_json=$(ssh ${SSH_OPTS} "${TETHYS_HOST}" "test -f '${REMOTE_STATUS}' && cat '${REMOTE_STATUS}'" || true)
|
status_json=$(ssh ${SSH_OPTS} "${TETHYS_HOST}" "test -f '${REMOTE_STATUS}' && cat '${REMOTE_STATUS}'" || true)
|
||||||
echo "browser consumer start request failed or timed out" >&2
|
echo "browser consumer start request failed or timed out" >&2
|
||||||
[[ -n "${status_json:-}" ]] && echo "last status: ${status_json}" >&2
|
[[ -n "${status_json:-}" ]] && echo "last status: ${status_json}" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
browser_start_token="$(START_JSON="${start_json}" python3 - <<'PY'
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
|
||||||
|
status = json.loads(os.environ["START_JSON"])
|
||||||
|
print(int(status.get("start_token") or 0))
|
||||||
|
PY
|
||||||
|
)"
|
||||||
|
echo " ↪ browser_start_token=${browser_start_token}"
|
||||||
|
|
||||||
sleep 1
|
sleep 1
|
||||||
|
|
||||||
@ -155,7 +181,17 @@ deadline_upload=$(( $(date +%s) + PROBE_DURATION_SECONDS + 60 ))
|
|||||||
while true; do
|
while true; do
|
||||||
status_json=$(ssh ${SSH_OPTS} "${TETHYS_HOST}" "test -f '${REMOTE_STATUS}' && cat '${REMOTE_STATUS}'" || true)
|
status_json=$(ssh ${SSH_OPTS} "${TETHYS_HOST}" "test -f '${REMOTE_STATUS}' && cat '${REMOTE_STATUS}'" || true)
|
||||||
if [[ -n "${status_json}" ]]; then
|
if [[ -n "${status_json}" ]]; then
|
||||||
if STATUS_JSON="${status_json}" python3 -c 'import json, os, sys; status = json.loads(os.environ["STATUS_JSON"]); sys.exit(0 if status.get("uploaded") else 1)'
|
if STATUS_JSON="${status_json}" BROWSER_START_TOKEN="${browser_start_token}" python3 - <<'PY'
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
status = json.loads(os.environ["STATUS_JSON"])
|
||||||
|
expected = int(os.environ["BROWSER_START_TOKEN"])
|
||||||
|
uploaded = bool(status.get("uploaded"))
|
||||||
|
uploaded_token = status.get("uploaded_start_token")
|
||||||
|
sys.exit(0 if uploaded and uploaded_token == expected else 1)
|
||||||
|
PY
|
||||||
then
|
then
|
||||||
echo "==> browser recording uploaded"
|
echo "==> browser recording uploaded"
|
||||||
break
|
break
|
||||||
|
|||||||
@ -29,6 +29,7 @@ LESAVKA_SYNC_APPLY_CALIBRATION=${LESAVKA_SYNC_APPLY_CALIBRATION:-0}
|
|||||||
LESAVKA_SYNC_SAVE_CALIBRATION=${LESAVKA_SYNC_SAVE_CALIBRATION:-0}
|
LESAVKA_SYNC_SAVE_CALIBRATION=${LESAVKA_SYNC_SAVE_CALIBRATION:-0}
|
||||||
LESAVKA_SYNC_CALIBRATION_TARGET=${LESAVKA_SYNC_CALIBRATION_TARGET:-video}
|
LESAVKA_SYNC_CALIBRATION_TARGET=${LESAVKA_SYNC_CALIBRATION_TARGET:-video}
|
||||||
LESAVKA_SYNC_CALIBRATION_SEGMENTS=${LESAVKA_SYNC_CALIBRATION_SEGMENTS:-1}
|
LESAVKA_SYNC_CALIBRATION_SEGMENTS=${LESAVKA_SYNC_CALIBRATION_SEGMENTS:-1}
|
||||||
|
LESAVKA_SYNC_CONTINUOUS_BROWSER=${LESAVKA_SYNC_CONTINUOUS_BROWSER:-${LESAVKA_SYNC_ADAPTIVE_CALIBRATION}}
|
||||||
LESAVKA_SYNC_SEGMENT_SETTLE_SECONDS=${LESAVKA_SYNC_SEGMENT_SETTLE_SECONDS:-3}
|
LESAVKA_SYNC_SEGMENT_SETTLE_SECONDS=${LESAVKA_SYNC_SEGMENT_SETTLE_SECONDS:-3}
|
||||||
STIMULUS_PORT=${STIMULUS_PORT:-18444}
|
STIMULUS_PORT=${STIMULUS_PORT:-18444}
|
||||||
STIMULUS_SETTLE_SECONDS=${STIMULUS_SETTLE_SECONDS:-10}
|
STIMULUS_SETTLE_SECONDS=${STIMULUS_SETTLE_SECONDS:-10}
|
||||||
@ -438,14 +439,21 @@ start_real_lesavka_client() {
|
|||||||
run_browser_capture_with_real_driver() {
|
run_browser_capture_with_real_driver() {
|
||||||
local segment_label="$1"
|
local segment_label="$1"
|
||||||
local segment_output_dir="$2"
|
local segment_output_dir="$2"
|
||||||
|
local segment_index="${3:-1}"
|
||||||
local record_seconds=$((PROBE_DURATION_SECONDS + 3))
|
local record_seconds=$((PROBE_DURATION_SECONDS + 3))
|
||||||
local wait_seconds=$((PROBE_DURATION_SECONDS + 2))
|
local wait_seconds=$((PROBE_DURATION_SECONDS + 2))
|
||||||
local driver_command="curl -fsS -X POST http://127.0.0.1:${STIMULUS_PORT}/start >/dev/null; sleep ${wait_seconds}"
|
local driver_command="curl -fsS -X POST http://127.0.0.1:${STIMULUS_PORT}/start >/dev/null; sleep ${wait_seconds}"
|
||||||
|
local reuse_browser_session=0
|
||||||
|
if [[ "${LESAVKA_SYNC_CONTINUOUS_BROWSER}" == "1" && "${segment_index}" != "1" ]]; then
|
||||||
|
reuse_browser_session=1
|
||||||
|
fi
|
||||||
mkdir -p "${segment_output_dir}"
|
mkdir -p "${segment_output_dir}"
|
||||||
echo "==> starting Tethys browser consumer and mirrored driver (${segment_label})"
|
echo "==> starting Tethys browser consumer and mirrored driver (${segment_label})"
|
||||||
|
echo " ↪ browser_consumer_reuse_session=${reuse_browser_session}"
|
||||||
BROWSER_RECORD_SECONDS="${record_seconds}" \
|
BROWSER_RECORD_SECONDS="${record_seconds}" \
|
||||||
PROBE_DURATION_SECONDS="${PROBE_DURATION_SECONDS}" \
|
PROBE_DURATION_SECONDS="${PROBE_DURATION_SECONDS}" \
|
||||||
BROWSER_SYNC_DRIVER_COMMAND="${driver_command}" \
|
BROWSER_SYNC_DRIVER_COMMAND="${driver_command}" \
|
||||||
|
BROWSER_CONSUMER_REUSE_SESSION="${reuse_browser_session}" \
|
||||||
SYNC_ANALYZE_EVENT_WIDTH_CODES="${PROBE_EVENT_WIDTH_CODES}" \
|
SYNC_ANALYZE_EVENT_WIDTH_CODES="${PROBE_EVENT_WIDTH_CODES}" \
|
||||||
LOCAL_OUTPUT_DIR="${segment_output_dir}" \
|
LOCAL_OUTPUT_DIR="${segment_output_dir}" \
|
||||||
LESAVKA_SERVER_ADDR="${RESOLVED_LESAVKA_SERVER_ADDR}" \
|
LESAVKA_SERVER_ADDR="${RESOLVED_LESAVKA_SERVER_ADDR}" \
|
||||||
@ -462,7 +470,7 @@ run_mirrored_segments() {
|
|||||||
echo "==> mirrored calibration ${segment_label}"
|
echo "==> mirrored calibration ${segment_label}"
|
||||||
print_upstream_calibration_state "before ${segment_label}" "${segment_dir}/calibration-before.env"
|
print_upstream_calibration_state "before ${segment_label}" "${segment_dir}/calibration-before.env"
|
||||||
print_upstream_sync_state "before ${segment_label}" "${segment_dir}/planner-before.env"
|
print_upstream_sync_state "before ${segment_label}" "${segment_dir}/planner-before.env"
|
||||||
if run_browser_capture_with_real_driver "${segment_label}" "${segment_dir}"; then
|
if run_browser_capture_with_real_driver "${segment_label}" "${segment_dir}" "${segment}"; then
|
||||||
maybe_apply_probe_calibration "${segment_dir}" "${segment_label}"
|
maybe_apply_probe_calibration "${segment_dir}" "${segment_label}"
|
||||||
print_upstream_sync_state "after ${segment_label}" "${segment_dir}/planner-after.env"
|
print_upstream_sync_state "after ${segment_label}" "${segment_dir}/planner-after.env"
|
||||||
print_upstream_calibration_state "after ${segment_label}" "${segment_dir}/calibration-after.env"
|
print_upstream_calibration_state "after ${segment_label}" "${segment_dir}/calibration-after.env"
|
||||||
|
|||||||
@ -10,7 +10,7 @@ bench = false
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "lesavka_server"
|
name = "lesavka_server"
|
||||||
version = "0.17.15"
|
version = "0.17.16"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
autobins = false
|
autobins = false
|
||||||
|
|
||||||
|
|||||||
@ -73,9 +73,13 @@ fn browser_sync_script_can_delegate_to_a_real_path_driver() {
|
|||||||
for expected in [
|
for expected in [
|
||||||
"BROWSER_RECORD_SECONDS=${BROWSER_RECORD_SECONDS:-${PROBE_DURATION_SECONDS}}",
|
"BROWSER_RECORD_SECONDS=${BROWSER_RECORD_SECONDS:-${PROBE_DURATION_SECONDS}}",
|
||||||
"BROWSER_SYNC_DRIVER_COMMAND=${BROWSER_SYNC_DRIVER_COMMAND:-}",
|
"BROWSER_SYNC_DRIVER_COMMAND=${BROWSER_SYNC_DRIVER_COMMAND:-}",
|
||||||
|
"BROWSER_CONSUMER_REUSE_SESSION=${BROWSER_CONSUMER_REUSE_SESSION:-0}",
|
||||||
"SYNC_ANALYZE_EVENT_WIDTH_CODES=${SYNC_ANALYZE_EVENT_WIDTH_CODES:-}",
|
"SYNC_ANALYZE_EVENT_WIDTH_CODES=${SYNC_ANALYZE_EVENT_WIDTH_CODES:-}",
|
||||||
"==> running custom browser sync driver",
|
"==> running custom browser sync driver",
|
||||||
"bash -lc \"${BROWSER_SYNC_DRIVER_COMMAND}\"",
|
"bash -lc \"${BROWSER_SYNC_DRIVER_COMMAND}\"",
|
||||||
|
"browser_start_token=${browser_start_token}",
|
||||||
|
"uploaded_start_token",
|
||||||
|
"BROWSER_START_TOKEN",
|
||||||
"--event-width-codes",
|
"--event-width-codes",
|
||||||
"--report-dir \"${LOCAL_REPORT_DIR}\"",
|
"--report-dir \"${LOCAL_REPORT_DIR}\"",
|
||||||
"for attempt in 1 2 3 4 5",
|
"for attempt in 1 2 3 4 5",
|
||||||
@ -116,9 +120,12 @@ fn mirrored_sync_script_uses_real_client_capture_path() {
|
|||||||
"LESAVKA_SYNC_CALIBRATION_TARGET=${LESAVKA_SYNC_CALIBRATION_TARGET:-video}",
|
"LESAVKA_SYNC_CALIBRATION_TARGET=${LESAVKA_SYNC_CALIBRATION_TARGET:-video}",
|
||||||
"LESAVKA_SYNC_ADAPTIVE_CALIBRATION=${LESAVKA_SYNC_ADAPTIVE_CALIBRATION:-0}",
|
"LESAVKA_SYNC_ADAPTIVE_CALIBRATION=${LESAVKA_SYNC_ADAPTIVE_CALIBRATION:-0}",
|
||||||
"LESAVKA_SYNC_CALIBRATION_SEGMENTS=${LESAVKA_SYNC_CALIBRATION_SEGMENTS:-1}",
|
"LESAVKA_SYNC_CALIBRATION_SEGMENTS=${LESAVKA_SYNC_CALIBRATION_SEGMENTS:-1}",
|
||||||
|
"LESAVKA_SYNC_CONTINUOUS_BROWSER=${LESAVKA_SYNC_CONTINUOUS_BROWSER:-${LESAVKA_SYNC_ADAPTIVE_CALIBRATION}}",
|
||||||
"LESAVKA_SYNC_SEGMENT_SETTLE_SECONDS=${LESAVKA_SYNC_SEGMENT_SETTLE_SECONDS:-3}",
|
"LESAVKA_SYNC_SEGMENT_SETTLE_SECONDS=${LESAVKA_SYNC_SEGMENT_SETTLE_SECONDS:-3}",
|
||||||
"LESAVKA_SYNC_ADAPTIVE_CALIBRATION",
|
"LESAVKA_SYNC_ADAPTIVE_CALIBRATION",
|
||||||
"LESAVKA_SYNC_CALIBRATION_SEGMENTS=4",
|
"LESAVKA_SYNC_CALIBRATION_SEGMENTS=4",
|
||||||
|
"browser_consumer_reuse_session=${reuse_browser_session}",
|
||||||
|
"BROWSER_CONSUMER_REUSE_SESSION=\"${reuse_browser_session}\"",
|
||||||
"LESAVKA_SYNC_CALIBRATION_SEGMENTS must be a positive integer",
|
"LESAVKA_SYNC_CALIBRATION_SEGMENTS must be a positive integer",
|
||||||
"run_mirrored_segments",
|
"run_mirrored_segments",
|
||||||
"summarize_adaptive_probe_metrics",
|
"summarize_adaptive_probe_metrics",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user