-
-
Notifications
You must be signed in to change notification settings - Fork 156
feat(core): support frankenphp worker mode #1996
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 3.x
Are you sure you want to change the base?
Changes from all commits
1b0c6da
c6ea676
cf6b270
9fe220f
2565c4f
db99c50
ae7a69d
c7b17f8
093b5da
c87866e
2124266
c3ff106
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace Tempest\Core; | ||
|
|
||
| use Tempest\Container\Container; | ||
|
|
||
| final readonly class GenericResetHandler implements ResetHandler | ||
| { | ||
| public function __construct( | ||
| private ResetableContainer $resetableContainer, | ||
| ) {} | ||
|
|
||
| public function reset(Container $container): void | ||
| { | ||
| foreach ($this->resetableContainer->resetableClasses as $class) { | ||
| if (! $container->has($class)) { | ||
| continue; | ||
| } | ||
|
|
||
| $container->get($class)->reset(); | ||
| } | ||
|
|
||
| foreach ($this->resetableContainer->resetableStaticClasses as $class) { | ||
| $class::resetStatic(); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace Tempest\Core; | ||
|
|
||
| use Tempest\Container\Container; | ||
|
|
||
| interface ResetHandler | ||
| { | ||
| public function reset(Container $container): void; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace Tempest\Core; | ||
|
|
||
| use Tempest\Container\Container; | ||
| use Tempest\Container\Initializer; | ||
|
|
||
| final readonly class ResetHandlerInitializer implements Initializer | ||
| { | ||
| public function initialize(Container $container): ResetHandler | ||
| { | ||
| return $container->get(GenericResetHandler::class); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace Tempest\Core; | ||
|
|
||
| interface Resetable | ||
| { | ||
| public function reset(): void; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace Tempest\Core; | ||
|
|
||
| use Tempest\Container\Singleton; | ||
|
|
||
| #[Singleton] | ||
| class ResetableContainer | ||
| { | ||
| /** | ||
| * @param class-string<Resetable>[] $resetableClasses | ||
| * @param class-string<ResetableStatic>[] $resetableStaticClasses | ||
| */ | ||
| public function __construct( | ||
| private(set) array $resetableClasses = [], | ||
| private(set) array $resetableStaticClasses = [], | ||
| ) {} | ||
|
|
||
| /** @param class-string<Resetable> $class */ | ||
| public function add(string $class): void | ||
| { | ||
| $this->resetableClasses[] = $class; | ||
| } | ||
|
|
||
| /** @param class-string<ResetableStatic> $class */ | ||
| public function addStatic(string $class): void | ||
| { | ||
| $this->resetableStaticClasses[] = $class; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace Tempest\Core; | ||
|
|
||
| use Tempest\Discovery\Discovery; | ||
| use Tempest\Discovery\DiscoveryLocation; | ||
| use Tempest\Discovery\IsDiscovery; | ||
| use Tempest\Reflection\ClassReflector; | ||
|
|
||
| final class ResetableDiscovery implements Discovery | ||
| { | ||
| use IsDiscovery; | ||
|
|
||
| private const int IS_RESETABLE = 1; | ||
| private const int IS_RESETABLE_STATIC = 2; | ||
|
|
||
| public function __construct( | ||
| private readonly ResetableContainer $resetableContainer, | ||
| ) {} | ||
|
|
||
| public function discover(DiscoveryLocation $location, ClassReflector $class): void | ||
| { | ||
| if ($class->implements(Resetable::class)) { | ||
| $this->discoveryItems->add($location, [self::IS_RESETABLE, $class->getName()]); | ||
| } | ||
|
|
||
| if ($class->implements(ResetableStatic::class)) { | ||
| $this->discoveryItems->add($location, [self::IS_RESETABLE_STATIC, $class->getName()]); | ||
| } | ||
| } | ||
|
|
||
| public function apply(): void | ||
| { | ||
| foreach ($this->discoveryItems as [$type, $className]) { | ||
| if ($type === self::IS_RESETABLE) { | ||
| $this->resetableContainer->add($className); | ||
| } else { | ||
| $this->resetableContainer->addStatic($className); | ||
| } | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace Tempest\Core; | ||
|
|
||
| interface ResetableStatic | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm wondering why we need a separate class for resetting static stuff? |
||
| { | ||
| public static function resetStatic(): void; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,104 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace Tempest\Http; | ||
|
|
||
| use Tempest\Container\Singleton; | ||
| use Tempest\Http\Cookie\Cookie; | ||
|
|
||
| #[Singleton] | ||
| final class OpaqueRequest implements Request | ||
| { | ||
| public function __construct( | ||
| private RequestHolder $requestHolder, | ||
| ) {} | ||
|
|
||
| public array $cookies { | ||
| get { | ||
| return $this->requestHolder->request->cookies; | ||
| } | ||
| } | ||
|
|
||
| public array $files { | ||
| get { | ||
| return $this->requestHolder->request->files; | ||
| } | ||
| } | ||
|
|
||
| public array $query { | ||
| get { | ||
| return $this->requestHolder->request->query; | ||
| } | ||
| } | ||
|
|
||
| public string $path { | ||
| get { | ||
| return $this->requestHolder->request->path; | ||
| } | ||
| } | ||
| public RequestHeaders $headers { | ||
| get { | ||
| return $this->requestHolder->request->headers; | ||
| } | ||
| } | ||
|
|
||
| public array $body { | ||
| get { | ||
| return $this->requestHolder->request->body; | ||
| } | ||
| } | ||
|
|
||
| public ?string $raw { | ||
| get { | ||
| return $this->requestHolder->request->raw; | ||
| } | ||
| } | ||
|
|
||
| public string $uri { | ||
| get { | ||
| return $this->requestHolder->request->uri; | ||
| } | ||
| } | ||
|
|
||
| public Method $method { | ||
| get { | ||
| return $this->requestHolder->request->method; | ||
| } | ||
| } | ||
|
|
||
| public function has(string $key): bool | ||
| { | ||
| return $this->requestHolder->request->has($key); | ||
| } | ||
|
|
||
| public function hasBody(?string $key = null): bool | ||
| { | ||
| return $this->requestHolder->request->hasBody($key); | ||
| } | ||
|
|
||
| public function hasQuery(string $key): bool | ||
| { | ||
| return $this->requestHolder->request->hasQuery($key); | ||
| } | ||
|
|
||
| public function get(string $key, mixed $default = null): mixed | ||
| { | ||
| return $this->requestHolder->request->get($key, $default); | ||
| } | ||
|
|
||
| public function getSessionValue(string $name): mixed | ||
| { | ||
| return $this->requestHolder->request->getSessionValue($name); | ||
| } | ||
|
|
||
| public function getCookie(string $name): ?Cookie | ||
| { | ||
| return $this->requestHolder->request->getCookie($name); | ||
| } | ||
|
|
||
| public function accepts(ContentType ...$contentType): bool | ||
| { | ||
| return $this->requestHolder->request->accepts(...$contentType); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace Tempest\Http; | ||
|
|
||
| use Tempest\Container\Singleton; | ||
| use Tempest\Core\Resetable; | ||
|
|
||
| #[Singleton] | ||
| final class RequestHolder implements Resetable | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the reason why we can't reset request and session directly and need these opaque objects in between? |
||
| { | ||
| private(set) Request $request; | ||
|
|
||
| public function setRequest(Request $request): void | ||
| { | ||
| $this->request = $request; | ||
| } | ||
|
|
||
| public function reset(): void | ||
| { | ||
| unset($this->request); | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find
ResetableContainera bit of a confusing name, because I assumed it was a new container implementation, which it is not. Maybe something likeResetableConfigto keep in line with the rest of the framework would work better?