Skip to content

Commit a597988

Browse files
authored
Merge pull request #518 from hypervel/revert/server-reloader
Revert provider-based server reloading
2 parents d67dc9d + 93dc049 commit a597988

129 files changed

Lines changed: 725 additions & 3779 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/plans/2026-08-08-1956-server-reloader-and-worker-configuration-refresh.md

Lines changed: 0 additions & 424 deletions
This file was deleted.

docs/plans/2026-08-20-1310-revert-provider-based-server-reloader.md

Lines changed: 245 additions & 0 deletions
Large diffs are not rendered by default.

docs/todo.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
- Convert the remaining tests that extend `PHPUnit\Framework\TestCase` to `Hypervel\Tests\TestCase` as required by `AGENTS.md`, verifying each file individually under coroutine execution and opting out only when the test explicitly exercises coroutine transitions.
2424
- Design a connection-owned service identity and capability API for external backends that packages can query without repeated hot-path probes. Redis/Valkey and database connections already expose fragments of this information in different forms; prefer lazy detection cached for the current connection or pool generation, with invalidation on reconnect and purge, over an eager process-global startup registry that performs unused I/O or survives a backend change. Start with concrete consumers and capability checks rather than a universal version-comparison abstraction.
25+
- Find a clean, simple framework-wide solution for configuration-dependent services resolved before worker configuration reload. `server:reload` refreshes the existing configuration repository, but objects that have already copied configuration into their own state remain stale. For example, `SentryServiceProvider` eagerly resolves a worker-lifetime Hub and client during boot, so DSN, environment, and sampling changes are not applied until a full restart; resolving `Cache::store('some-store')` from a service provider populates `CacheManager`'s store cache before reload, so changes to that store's driver, connection, prefix, or other captured configuration are likewise not applied. Define the reload contract, audit framework-owned eager resolutions and manager caches, and solve the lifecycle at their shared owning boundary instead of adding package-specific refresh hooks or application workarounds.
2526
- Investigate where requiring and directly using a PHP extension would make framework code significantly faster than its current pure-PHP implementation. The framework already declares bundled extensions it depends on, so the question is which hot paths are doing in PHP what a C extension does natively. The worked example is `ext-gmp` for identifier encoding: UUID and ULID string conversion and any base32/base58/base62 short-id work exceed 64 bits, so `ramsey/uuid` and `symfony/uid` convert them digit by digit in PHP, while `gmp_init()`/`gmp_strval()` do arbitrary-base conversion natively — a hand-rolled base-36 UUID conversion measured 14.6 µs against 0.5 µs for the GMP equivalent with byte-identical output. Anything that fits in a 64-bit int (snowflakes, timestamps, counters) needs no extension, and hashing, encryption, and signatures are already C. Measure `Str::uuid()`/`Str::ulid()` and the other candidates before adding a requirement, and weigh each new extension against installation cost.
2627
- Convert untyped `$config->get()` calls across `src/` to the typed getters (`string()`, `integer()`, `float()`, `boolean()`, `array()`) without call-site defaults, for every key that isn't genuinely nullable. Defaults live in the merged config files — declare any key currently defaulted only at a call site in its package's config file as part of the conversion. Typed getters throw `InvalidArgumentException` naming the key on misconfiguration instead of letting a wrong type propagate silently, and give phpstan real return types. Bootstrap code that runs before config merging keeps its call-site defaults. Approved modernization per the Porting Packages policy in `AGENTS.md`; new code already follows the rule.
2728
- Audit unmatched PHPStan inline ignores and global patterns with `reportUnmatchedIgnoredErrors` enabled — currently 196 unmatched inline ignores across 99 files plus 5 unmatched global patterns. Remove only suppressions that no longer match after tracing the underlying code; do not replace correct source with runtime branches or wider types merely to keep static analysis green. Decide as part of the work whether `phpstan.neon.dist` should then set `reportUnmatchedIgnoredErrors: true` permanently, since leaving it `false` lets the suppressions rot again.

src/auth/src/AuthServiceProvider.php

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
use Hypervel\Contracts\Auth\Access\Gate as GateContract;
1212
use Hypervel\Contracts\Auth\Authenticatable as AuthenticatableContract;
1313
use Hypervel\Contracts\Config\Repository as ConfigRepository;
14-
use Hypervel\Contracts\Foundation\ReloadsConfiguration;
1514
use Hypervel\Core\Events\AfterWorkerStart;
1615
use Hypervel\Database\Eloquent\Builder as EloquentBuilder;
1716
use Hypervel\Database\Eloquent\Collection as EloquentCollection;
@@ -26,7 +25,7 @@
2625

2726
use function Hypervel\Support\enum_value;
2827

29-
class AuthServiceProvider extends ServiceProvider implements ReloadsConfiguration
28+
class AuthServiceProvider extends ServiceProvider
3029
{
3130
private const int MAX_QUERY_ATTRIBUTE_LENGTH = 63;
3231

@@ -43,19 +42,6 @@ public function register(): void
4342
$this->commands([ClearResetsCommand::class]);
4443
}
4544

46-
/**
47-
* Reload configuration-derived worker state.
48-
*
49-
* Boot-only. Request-time use clears shared resolved guards while
50-
* concurrent coroutines may still be using them.
51-
*/
52-
public function reloadConfiguration(): void
53-
{
54-
if ($this->app->resolved('auth')) {
55-
$this->app->make('auth')->forgetGuards();
56-
}
57-
}
58-
5945
/**
6046
* Bootstrap the service provider.
6147
*/

src/auth/src/Passwords/PasswordBrokerManager.php

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -188,19 +188,6 @@ public function setDefaultDriver(UnitEnum|string $name): void
188188
CoroutineContext::set(self::DEFAULT_BROKER_CONTEXT_KEY, $name);
189189
}
190190

191-
/**
192-
* Forget all resolved password brokers.
193-
*
194-
* Boot or tests only. Mutates the singleton's broker cache; concurrent
195-
* coroutines may already hold a broker that next resolution will replace.
196-
*/
197-
public function forgetBrokers(): static
198-
{
199-
$this->brokers = [];
200-
201-
return $this;
202-
}
203-
204191
/**
205192
* Refresh the event dispatcher on resolved brokers.
206193
*

src/auth/src/Passwords/PasswordResetServiceProvider.php

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@
44

55
namespace Hypervel\Auth\Passwords;
66

7-
use Hypervel\Contracts\Foundation\ReloadsConfiguration;
87
use Hypervel\Support\ServiceProvider;
98

10-
class PasswordResetServiceProvider extends ServiceProvider implements ReloadsConfiguration
9+
class PasswordResetServiceProvider extends ServiceProvider
1110
{
1211
/**
1312
* Register the service provider.
@@ -18,19 +17,6 @@ public function register(): void
1817
$this->registerEventRebindHandler();
1918
}
2019

21-
/**
22-
* Reload configuration-derived worker state.
23-
*
24-
* Boot-only. Request-time use clears shared resolved brokers while
25-
* concurrent coroutines may still be using them.
26-
*/
27-
public function reloadConfiguration(): void
28-
{
29-
if ($this->app->resolved('auth.password')) {
30-
$this->app->make('auth.password')->forgetBrokers();
31-
}
32-
}
33-
3420
/**
3521
* Register the password broker instance.
3622
*/

src/broadcasting/src/BroadcastServiceProvider.php

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,9 @@
66

77
use Hypervel\Contracts\Broadcasting\Broadcaster as BroadcasterContract;
88
use Hypervel\Contracts\Broadcasting\Factory as BroadcastingFactory;
9-
use Hypervel\Contracts\Foundation\ReloadsConfiguration;
109
use Hypervel\Support\ServiceProvider;
1110

12-
class BroadcastServiceProvider extends ServiceProvider implements ReloadsConfiguration
11+
class BroadcastServiceProvider extends ServiceProvider
1312
{
1413
/**
1514
* Register the service provider.
@@ -25,19 +24,4 @@ public function register(): void
2524
BroadcastingFactory::class
2625
);
2726
}
28-
29-
/**
30-
* Reload configuration-derived worker state.
31-
*
32-
* Boot-only. Request-time use clears shared broadcast connections while
33-
* concurrent coroutines may still be using them.
34-
*/
35-
public function reloadConfiguration(): void
36-
{
37-
if ($this->app->resolved(BroadcastManager::class)) {
38-
$this->app->make(BroadcastManager::class)->forgetDrivers();
39-
}
40-
41-
$this->app->forgetInstance(BroadcasterContract::class);
42-
}
4327
}

src/bus/src/BusServiceProvider.php

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,10 @@
77
use Hypervel\Container\Container;
88
use Hypervel\Contracts\Bus\Dispatcher as DispatcherContract;
99
use Hypervel\Contracts\Bus\QueueingDispatcher as QueueingDispatcherContract;
10-
use Hypervel\Contracts\Foundation\ReloadsConfiguration;
1110
use Hypervel\Contracts\Queue\Factory as QueueFactoryContract;
1211
use Hypervel\Support\ServiceProvider;
1312

14-
class BusServiceProvider extends ServiceProvider implements ReloadsConfiguration
13+
class BusServiceProvider extends ServiceProvider
1514
{
1615
/**
1716
* Register the service provider.
@@ -37,18 +36,6 @@ public function register(): void
3736
);
3837
}
3938

40-
/**
41-
* Reload configuration-derived worker state.
42-
*
43-
* Boot-only. Request-time use replaces shared batch repositories while
44-
* concurrent coroutines may still hold the previous instances.
45-
*/
46-
public function reloadConfiguration(): void
47-
{
48-
$this->app->forgetInstance(BatchRepository::class);
49-
$this->app->forgetInstance(DatabaseBatchRepository::class);
50-
}
51-
5239
/**
5340
* Register the batch handling services.
5441
*/

src/cache/src/CacheManager.php

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -471,19 +471,6 @@ public function forgetDriver(array|UnitEnum|string|null $name = null): static
471471
return $this;
472472
}
473473

474-
/**
475-
* Forget all resolved cache drivers.
476-
*
477-
* Boot or tests only. Mutates the singleton's store cache; concurrent
478-
* coroutines may already hold stores that next resolution will replace.
479-
*/
480-
public function forgetDrivers(): static
481-
{
482-
$this->stores = [];
483-
484-
return $this;
485-
}
486-
487474
/**
488475
* Disconnect the given driver and remove from local cache.
489476
*
@@ -540,10 +527,9 @@ public function setApplication(Container $app): static
540527
* Register classes that cache stores may unserialize.
541528
*
542529
* Boot-only. The resolver contributes to the worker-lifetime cache policy
543-
* and is evaluated after every provider has booted: at application boot
544-
* completion in console processes or after configuration reload in each
545-
* Swoole worker. An earlier cache read evaluates the current contributions
546-
* without memoizing them.
530+
* and is evaluated at application boot completion in console processes or
531+
* after the worker configuration is rebuilt in Swoole workers. An earlier
532+
* cache read evaluates the current contributions without memoizing them.
547533
*
548534
* @param Closure(): array<array-key, class-string> $resolver
549535
*

src/cache/src/CacheServiceProvider.php

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,11 @@
1313
use Hypervel\Cache\Listeners\RegisterSwooleMaintenanceTimers;
1414
use Hypervel\Cache\Redis\Console\BenchmarkCommand;
1515
use Hypervel\Cache\Redis\Console\DoctorCommand;
16-
use Hypervel\Contracts\Foundation\ReloadsConfiguration;
1716
use Hypervel\Core\Events\AfterWorkerStart;
1817
use Hypervel\Core\Events\BeforeServerStart;
1918
use Hypervel\Support\ServiceProvider;
2019

21-
class CacheServiceProvider extends ServiceProvider implements ReloadsConfiguration
20+
class CacheServiceProvider extends ServiceProvider
2221
{
2322
/**
2423
* Register the service provider.
@@ -40,21 +39,6 @@ public function register(): void
4039
]);
4140
}
4241

43-
/**
44-
* Reload configuration-derived worker state.
45-
*
46-
* Boot-only. Request-time use clears shared cache stores while concurrent
47-
* coroutines may still be using them.
48-
*/
49-
public function reloadConfiguration(): void
50-
{
51-
if ($this->app->resolved('cache')) {
52-
$this->app->make('cache')->forgetDrivers();
53-
}
54-
55-
$this->app->forgetInstance('cache.store');
56-
}
57-
5842
/**
5943
* Bootstrap the service provider.
6044
*/
@@ -80,7 +64,7 @@ public function boot(): void
8064
return;
8165
}
8266

83-
// Worker configuration is reloaded during BeforeWorkerStart.
67+
// Finalize after BeforeWorkerStart rebuilds the worker configuration.
8468
$events->listen(AfterWorkerStart::class, function (AfterWorkerStart $event): void {
8569
$this->app->make(CacheManager::class)->finalizeSerializableClasses();
8670
});

0 commit comments

Comments
 (0)