Skip to content

Commit e679c06

Browse files
authored
[1.x] Flushes controller on route (#589)
* Flushes controller on route * Adds test * Adds memory leak tests * Updates framework versions
1 parent 7ba4282 commit e679c06

File tree

3 files changed

+69
-1
lines changed

3 files changed

+69
-1
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
],
1616
"require": {
1717
"php": "^8.0",
18-
"laravel/framework": "^8.81|^9.0",
18+
"laravel/framework": "^8.83.25|^9.33",
1919
"laminas/laminas-diactoros": "^2.5",
2020
"laravel/serializable-closure": "^1.0",
2121
"nesbot/carbon": "^2.60",

src/ApplicationGateway.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Illuminate\Contracts\Http\Kernel;
66
use Illuminate\Foundation\Application;
77
use Illuminate\Http\Request;
8+
use Illuminate\Routing\Route;
89
use Laravel\Octane\Events\RequestHandled;
910
use Laravel\Octane\Events\RequestReceived;
1011
use Laravel\Octane\Events\RequestTerminated;
@@ -50,5 +51,11 @@ public function terminate(Request $request, Response $response): void
5051
$this->sandbox->make(Kernel::class)->terminate($request, $response);
5152

5253
$this->dispatchEvent($this->sandbox, new RequestTerminated($this->app, $this->sandbox, $request, $response));
54+
55+
$route = $request->route();
56+
57+
if ($route instanceof Route && method_exists($route, 'flushController')) {
58+
$route->flushController();
59+
}
5360
}
5461
}

tests/RequestStateTest.php

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,67 @@ public function test_form_requests_contain_the_correct_state_across_subsequent_r
4949
$this->assertEquals('Abigail', $client->responses[1]->original['name']);
5050
$this->assertNotEquals($client->responses[0]->original['container'], $client->responses[1]->original['container']);
5151
}
52+
53+
public function test_request_routes_flush_controller_state()
54+
{
55+
[$app, $worker, $client] = $this->createOctaneContext([
56+
Request::create('/users', 'GET'),
57+
Request::create('/users', 'GET'),
58+
]);
59+
60+
$app['router']->get('/users', UserControllerStub::class);
61+
62+
$worker->run();
63+
64+
$this->assertEquals(1, $client->responses[0]->original);
65+
$this->assertEquals(1, $client->responses[1]->original);
66+
67+
$worker->run();
68+
69+
$this->assertEquals(1, $client->responses[0]->original);
70+
$this->assertEquals(1, $client->responses[1]->original);
71+
}
72+
73+
public function test_request_routes_controller_does_not_leak()
74+
{
75+
UserControllerStub::$destroyedCount = 0;
76+
77+
[$app, $worker, $client] = $this->createOctaneContext([
78+
Request::create('/users', 'GET'),
79+
Request::create('/users', 'GET'),
80+
]);
81+
82+
$app['router']->get('/users', UserControllerStub::class);
83+
84+
$worker->run();
85+
86+
gc_collect_cycles();
87+
$this->assertEquals(2, UserControllerStub::$destroyedCount);
88+
89+
$worker->run();
90+
91+
gc_collect_cycles();
92+
$this->assertEquals(4, UserControllerStub::$destroyedCount);
93+
}
94+
}
95+
96+
class UserControllerStub
97+
{
98+
protected $invokedCount = 0;
99+
100+
public static $destroyedCount = 0;
101+
102+
public function __invoke()
103+
{
104+
$this->invokedCount++;
105+
106+
return $this->invokedCount;
107+
}
108+
109+
public function __destruct()
110+
{
111+
static::$destroyedCount++;
112+
}
52113
}
53114

54115
class RequestStateTestFormRequest extends FormRequest

0 commit comments

Comments
 (0)