Flush scoped() container bindings between requests in LaravelHttpServer - #234
Open
onlime wants to merge 1 commit into
Open
Flush scoped() container bindings between requests in LaravelHttpServer#234onlime wants to merge 1 commit into
scoped() container bindings between requests in LaravelHttpServer#234onlime wants to merge 1 commit into
Conversation
LaravelHttpServer reuses one long-lived container for every request of a browser test, but never calls Application::forgetScopedInstances() — the only thing that releases scoped() bindings. So a scoped() service resolved in one request leaks into the next and behaves like a singleton, unlike every real runtime: FPM builds a fresh container per request, Octane flushes scoped instances between requests, and even the queue worker does so between jobs. Symptoms look like flaky, order-dependent tests (stale user/team context, wrong locale) and bite hardest right after an auth change mid-test such as an impersonation. Flush scoped instances at the start of each request, before Kernel::handle(), mirroring Octane.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
LaravelHttpServerserves every request of a browser test from one long-lived container — it calls$kernel->handle()/$kernel->terminate()per request, but never$app->forgetScopedInstances(). Sincescoped()bindings are only released by that call, ascoped()service resolved in one request survives into the next and behaves like asingleton().Every other Laravel runtime releases them per unit of work:
Illuminate\Queue\QueueServiceProvidercalls$app->forgetScopedInstances()).The in-process test server is the only place where a
scoped()service leaks — so browser tests exercise a lifetime that exists in no production runtime.Impact
Symptoms look like flaky, order-dependent tests rather than a container issue, and bite hardest right after an auth change mid-test (login, logout, impersonation): the request after taking an impersonation can resolve the previous user's cached, request-scoped context service and act on the wrong user/team. The failure is silent and only surfaces once an app registers a
scoped()binding.Change
Flush scoped instances at the start of each request, before
$kernel->handle(), mirroring Octane:One line, no API change, and a no-op for apps without
scoped()bindings.Test
Added to
tests/Unit/Drivers/Laravel/LaravelHttpServerTest.php: register ascoped()binding,visit()a route that renders the resolved object's hash twice, assert the two differ. Fails on4.xwithout the change (same instance returned), passes with it.Targeted at
4.x; if5.xalready flushes here, this is only needed for the 4.x line.