bundled: wipe Symfony cache on every launch — mount path bakes into cache
All checks were successful
CI / Quality (push) Successful in 5m43s
Release / Linux AppImage (push) Successful in 6m13s

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:
2026-05-03 15:23:30 +02:00
parent 1c231b1bac
commit 597e74edcf
3 changed files with 53 additions and 1 deletions

View File

@@ -16,6 +16,7 @@ Bugfix release closing the four follow-ups identified during the v0.1.0 shakedow
### Fixed
- **Wipe Symfony cache on bundled-mode launch.** Symfony's compiled container bakes `kernel.project_dir` as an absolute path. In bundled mode that path lives inside the AppImage's FUSE mount (`/tmp/.mount_<random>`), which is regenerated every launch. So the cache from launch N referenced mount-N's path; launch N+1 (different mount) hit `InvalidDirectory` from doctrine-migrations on the first launch-2 (and similar at any kernel.project_dir-sensitive lookup). `BackendConnection::initBundledMode` now `rmdir`s the cache before each spawn. Costs ~1-2s of warmup per launch; build-time cache warmup is the permanent fix (PLAN.md §13 v0.2.0). The bundled-supervisor integration test gained a 2nd-launch-from-fresh-staging step so this regresses if forgotten.
- **`HealthController` deep-loads the bundle.** Constructor-injects `Publisher` so `/healthz` returns 200 only when `BridgeBundle` is fully container-resolvable. v0.1.0's `/healthz` returned 200 against half-loaded bundles — both the path-repo symlink dangling at runtime and the read-only-cache failure shipped green through perfsmoke as a result. Response body now includes `bundle: "PhpQml\\Bridge\\Publisher"` as the canary value.
- **Caddyfile formatting.** `framework/skeleton/Caddyfile` and `examples/todo/Caddyfile` reformatted with `caddy fmt`. The "Caddyfile input is not formatted; run 'caddy fmt --overwrite'" warning that fired on every FrankenPHP boot is gone.