Skip to content

[Bugfix][CachedRouting] Make route caching best-effort so boot never fails - #28

Merged
agissept merged 2 commits into
masterfrom
bugfix/route-cache-corrupt-rebuild
Aug 28, 2026
Merged

[Bugfix][CachedRouting] Make route caching best-effort so boot never fails#28
agissept merged 2 commits into
masterfrom
bugfix/route-cache-corrupt-rebuild

Conversation

@agissept

@agissept agissept commented Aug 27, 2026

Copy link
Copy Markdown
Member

Summary

Fixes the deploy-time 500 on /ready (and the opcache_clear post-deploy task) that appeared after route cache moved to the local file store (4.2.89). The production stack trace showed the failure is a cache write, not a corrupt read:

ErrorException: file_put_contents(.../app_storage/cache/8b/8c/8b8c...): Failed to open stream: No such file or directory
  Filesystem::put -> FileStore::put -> Router::cache (uploaders.php:3) -> Application::boot

The cache directory (app_storage/cache/) is not creatable/writable by the php-fpm user on the nodes, so FileStore::createCacheDirectory() swallows the makeDirectory() failure and file_put_contents() then throws — and that exception propagates out of Router::cache() during boot, surfacing as a 500.

Route caching is only an optimization, so no cache I/O failure should ever break boot. This wraps both the read and the write in Router::cache() so failures degrade gracefully instead of crashing.

Changes

  • CachedRouting\Router::cache() — best-effort caching:
    • read failure (corrupt/unreadable entry) → treated as a miss → rebuild from the callback;
    • write failure (unwritable dir, disk full, …) → ignored; routes stay defined in memory, just uncached.
  • RoutingIntegrationTest — adds testBootStillWorksWhenCacheIsUnwritable (unwritable cache path still boots with routes defined) and testRebuildsWhenCachedFileIsCorrupt (corrupt entry rebuilds instead of erroring).

Context

This makes the app resilient, but the underlying root cause is operational: the app_storage/cache/ directory must exist and be writable by php-fpm on every node (previously nothing wrote there because the route cache lived in Redis). That should be fixed in provisioning/deploy in parallel; with this change a missing/unwritable cache dir degrades to "routes rebuilt per request" instead of a 500.

References

Source/Label Link
L42x PR #27 #27

🤖 Generated with Claude Code

agissept and others added 2 commits August 27, 2026 15:39
A partially-written or corrupt cache file (e.g. a torn write from
concurrent processes booting right after a deploy) made
`FileStore::getPayload()` call `unserialize()` on garbage. The emitted
warning is promoted to an ErrorException by the framework error handler,
so the read threw before the caller could react — surfacing as a 500
during boot when the route cache file was being built concurrently.

Wrap the unserialize in try/catch: on failure, forget the entry and
return a miss so the caller rebuilds. Adds a CachedRouting test that a
corrupt cache file triggers a rebuild rather than an error.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The production stack trace showed the real failure is a cache WRITE, not
a corrupt read: `file_put_contents(.../app_storage/cache/..): No such
file or directory` — the cache directory is not creatable/writable by
php-fpm, so `FileStore::put()` throws and the exception propagates out of
`Router::cache()` during boot, returning a 500.

Route caching is only an optimization, so no cache I/O failure should
break boot. Wrap both the read and the write in `Router::cache()`:
- read failure (corrupt/unreadable entry) -> treat as a miss and rebuild
- write failure (unwritable dir, disk full) -> ignore; routes stay
  defined in memory, just uncached

Reverts the earlier FileStore-level read guard (superseded by the
read try/catch here). Adds a test that an unwritable cache path still
boots with routes defined, alongside the corrupt-cache rebuild test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@agissept agissept changed the title [Bugfix][Cache] Tolerate corrupt file cache entries instead of failing [Bugfix][CachedRouting] Make route caching best-effort so boot never fails Aug 27, 2026
@agissept agissept self-assigned this Aug 28, 2026
@agissept
agissept merged commit 31f7867 into master Aug 28, 2026
2 checks passed
@agissept
agissept deleted the bugfix/route-cache-corrupt-rebuild branch August 28, 2026 07:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant