bundled: wipe Symfony cache on every launch — mount path bakes into cache
Reproduces with the v0.1.1 AppImage on the second launch (same user
data dir, fresh AppImage mount):
phpqml.bridge.bundled: symfony: "/tmp/.mount_Todo-xllnOHH/..."
Cannot load migrations from "/tmp/.mount_Todo-xDBkOfG/.../migrations"
^^^^^^^
stale path from PREVIOUS launch's cache
Symfony compiles `kernel.project_dir` (an absolute path) into its
cached container under var/cache/. We redirect var/cache into the
user data dir for read-only-mount survival (v0.1.0 fix), but the
*content* of that cache references the mount path that was active
when the cache was built. Next launch gets a different
/tmp/.mount_<random>; the cached refs are stale; first
project_dir-sensitive lookup blows up (doctrine migrations was the
canary; would also surface as misrouted assets, broken Twig template
paths, etc.).
Fix: BackendConnection::initBundledMode does
QDir(cacheDir).removeRecursively() right after creating the dirs but
before runMigrations spawns the doctrine subprocess. Symfony rebuilds
the cache against the current mount on every launch. Cost: ~1-2s of
warmup per cold start.
Permanent fix is build-time cache warmup (ship the prod cache inside
the AppImage, copy to user data dir on first launch, no per-launch
warmup) — already tracked as a v0.2.0 item in PLAN.md §13. v0.1.1
takes the simpler always-wipe approach since it's bugfix-class.
Regression guard: examples/todo/tests/bundled-supervisor.sh gains a
"2nd launch from fresh staging" step that tears down the first host,
re-stages a fresh fake AppImage layout (different /tmp dir = different
"mount path" from BackendConnection's perspective), and asserts
/healthz comes back up. Without the cache wipe, that step would fail
exactly the way doctrine did in the user's report.
Verified locally:
- bundled-supervisor.sh passes (incl. 2nd-launch step)
- Real AppImage: two consecutive launches both reach
"phpqml.bridge.bundled: migrations OK" + frankenphp spawn
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -138,4 +138,52 @@ if [ -d "$ROOT/usr/share/$APP_NAME/symfony/var/cache/prod" ] && \
|
||||
fail "Symfony wrote into the read-only staging tree — Kernel::getCacheDir override broken"
|
||||
fi
|
||||
|
||||
step "All bundled-supervisor assertions passed."
|
||||
# ── Second launch: same XDG_DATA_HOME, fresh staging mount ─────────────
|
||||
# Real AppImages get a fresh /tmp/.mount_<random> per launch but reuse the
|
||||
# user data dir, so any cached absolute path from launch N is stale by N+1.
|
||||
# Tear down the running host, re-run from a NEW staging dir (mimicking the
|
||||
# fresh-mount situation), assert /healthz comes back up.
|
||||
step "tear down + relaunch from fresh staging (regression: cache-baked-mount-path)"
|
||||
kill -TERM "$PID" 2>/dev/null || true
|
||||
for _ in 1 2 3 4 5 6 7 8 9 10; do
|
||||
kill -0 "$PID" 2>/dev/null || break
|
||||
sleep 0.2
|
||||
done
|
||||
kill -KILL "$PID" 2>/dev/null || true
|
||||
PID=""
|
||||
chmod -R u+w "$ROOT/usr/share/$APP_NAME/symfony" 2>/dev/null
|
||||
rm -rf "$ROOT"
|
||||
ROOT="$(mktemp -d)"
|
||||
mkdir -p "$ROOT/usr/bin" "$ROOT/usr/share/$APP_NAME"
|
||||
cp "$HOST_BIN" "$ROOT/usr/bin/$APP_NAME"
|
||||
ln -s "$(command -v frankenphp)" "$ROOT/usr/bin/frankenphp"
|
||||
cp -a "$STAGING/." "$ROOT/usr/share/$APP_NAME/symfony/"
|
||||
cp "$CADDYFILE" "$ROOT/usr/share/$APP_NAME/Caddyfile"
|
||||
chmod -R a-w "$ROOT/usr/share/$APP_NAME/symfony"
|
||||
|
||||
LOG2="$DATA_DIR/host2.log"
|
||||
env -u BRIDGE_URL \
|
||||
XDG_DATA_HOME="$DATA_DIR/share" \
|
||||
XDG_CACHE_HOME="$DATA_DIR/cache" \
|
||||
XDG_CONFIG_HOME="$DATA_DIR/config" \
|
||||
QT_QPA_PLATFORM=offscreen \
|
||||
"$ROOT/usr/bin/$APP_NAME" > "$LOG2" 2>&1 &
|
||||
PID=$!
|
||||
|
||||
DEADLINE=$(( $(date +%s) + 30 ))
|
||||
HEALTHZ2_BODY=""
|
||||
while [ "$(date +%s)" -lt "$DEADLINE" ]; do
|
||||
if ! kill -0 "$PID" 2>/dev/null; then
|
||||
sed 's/^/ /' "$LOG2" >&2 || true
|
||||
fail "host died during 2nd boot"
|
||||
fi
|
||||
if HEALTHZ2_BODY="$(curl -fsS -m 1 "http://127.0.0.1:$PORT/healthz" 2>/dev/null)"; then
|
||||
break
|
||||
fi
|
||||
sleep 0.2
|
||||
done
|
||||
[ -n "$HEALTHZ2_BODY" ] || { sed 's/^/ /' "$LOG2" >&2 || true; fail "/healthz never responded on 2nd launch — stale cache?"; }
|
||||
echo "$HEALTHZ2_BODY" | grep -q '"status":"ok"' \
|
||||
|| fail "2nd-launch /healthz didn't return status:ok"
|
||||
|
||||
step "All bundled-supervisor assertions passed (incl. 2nd-launch cache wipe)."
|
||||
|
||||
Reference in New Issue
Block a user