Skip to content
This repository was archived by the owner on Feb 17, 2025. It is now read-only.

Commit e2e10e4

Browse files
authored
Merge pull request #62 from reactphp-parallel/make-public-close-method-that-will-shutdown-everything
Add close method that will shutdown the entire proxy
2 parents fde6b12 + 7ab4ea4 commit e2e10e4

File tree

5 files changed

+119
-1
lines changed

5 files changed

+119
-1
lines changed

infection.json.dist

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
"MethodCallRemoval": {
7272
"ignore": [
7373
"ReactParallel\\ObjectProxy\\Proxy::__destruct",
74+
"ReactParallel\\ObjectProxy\\Proxy::close",
7475
"ReactParallel\\ObjectProxy\\Proxy::create",
7576
"ReactParallel\\ObjectProxy\\Proxy::thread",
7677
"ReactParallel\\ObjectProxy\\Proxy\\Handler::__destruct",

phpstan.neon

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ parameters:
1414
ergebnis:
1515
classesAllowedToBeExtended:
1616
- Exception
17+
- RuntimeException
1718
- Monolog\Handler\AbstractHandler
1819
- ReactParallel\ObjectProxy\Generated\ProxyList
1920

src/ClosedException.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace ReactParallel\ObjectProxy;
6+
7+
use RuntimeException;
8+
9+
final class ClosedException extends RuntimeException
10+
{
11+
public static function create(): self
12+
{
13+
return new self('Proxy has been closed previously and cannot be used anymore');
14+
}
15+
}

src/Proxy.php

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
use function serialize;
2424
use function unserialize;
2525

26+
use const WyriHaximus\Constants\Boolean\FALSE_;
2627
use const WyriHaximus\Constants\Boolean\TRUE_;
2728

2829
final class Proxy extends ProxyList
@@ -38,6 +39,8 @@ final class Proxy extends ProxyList
3839
/** @var array<Channel> */
3940
private array $destruct = [];
4041

42+
private bool $closed = FALSE_;
43+
4144
public function __construct(Configuration $configuration)
4245
{
4346
$this->factory = $configuration->factory();
@@ -54,11 +57,19 @@ public function __construct(Configuration $configuration)
5457

5558
public function has(string $interface): bool
5659
{
60+
if ($this->closed === TRUE_) {
61+
throw ClosedException::create();
62+
}
63+
5764
return array_key_exists($interface, self::KNOWN_INTERFACE);
5865
}
5966

6067
public function share(object $object, string $interface): object
6168
{
69+
if ($this->closed === TRUE_) {
70+
throw ClosedException::create();
71+
}
72+
6273
if ($this->has($interface) === self::HASNT_PROXYABLE_INTERFACE) {
6374
throw NonExistentInterface::create($interface);
6475
}
@@ -74,6 +85,10 @@ public function share(object $object, string $interface): object
7485

7586
public function create(object $object, string $interface): object
7687
{
88+
if ($this->closed === TRUE_) {
89+
throw ClosedException::create();
90+
}
91+
7792
if ($this->has($interface) === self::HASNT_PROXYABLE_INTERFACE) {
7893
throw NonExistentInterface::create($interface);
7994
}
@@ -94,6 +109,10 @@ public function create(object $object, string $interface): object
94109

95110
public function thread(object $object, string $interface): object
96111
{
112+
if ($this->closed === TRUE_) {
113+
throw ClosedException::create();
114+
}
115+
97116
if ($this->has($interface) === self::HASNT_PROXYABLE_INTERFACE) {
98117
throw NonExistentInterface::create($interface);
99118
}
@@ -128,13 +147,24 @@ static function (string $object, string $interface, string $hash, Channel $in, C
128147
return $instance->create();
129148
}
130149

131-
public function __destruct()
150+
public function close(): void
132151
{
152+
if ($this->closed === TRUE_) {
153+
throw ClosedException::create();
154+
}
155+
156+
$this->closed = TRUE_;
157+
133158
foreach ($this->destruct as $destruct) {
134159
$destruct->send('bye');
135160
$destruct->close();
136161
}
137162

138163
$this->in->close();
139164
}
165+
166+
public function __destruct()
167+
{
168+
$this->close();
169+
}
140170
}

tests/ProxyTest.php

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use React\Promise\PromiseInterface;
1414
use React\Promise\Timer\TimeoutException;
1515
use ReactParallel\Factory;
16+
use ReactParallel\ObjectProxy\ClosedException;
1617
use ReactParallel\ObjectProxy\Configuration;
1718
use ReactParallel\ObjectProxy\Configuration\Metrics;
1819
use ReactParallel\ObjectProxy\Generated\WyriHaximus__Metrics_RegistryProxy;
@@ -306,4 +307,74 @@ public function provideBooleans(): iterable
306307
yield 'true' => [TRUE_];
307308
yield 'false' => [FALSE_];
308309
}
310+
311+
/**
312+
* @test
313+
*/
314+
public function cannotCloseProxyTwice(): void
315+
{
316+
self::expectException(ClosedException::class);
317+
318+
$loop = EventLoopFactory::create();
319+
$factory = new Factory($loop);
320+
$proxy = new Proxy(new Configuration($factory));
321+
$proxy->close();
322+
$proxy->close();
323+
}
324+
325+
/**
326+
* @test
327+
*/
328+
public function cannotUseClosedProxyHas(): void
329+
{
330+
self::expectException(ClosedException::class);
331+
332+
$loop = EventLoopFactory::create();
333+
$factory = new Factory($loop);
334+
$proxy = new Proxy(new Configuration($factory));
335+
$proxy->close();
336+
$proxy->has('string');
337+
}
338+
339+
/**
340+
* @test
341+
*/
342+
public function cannotUseClosedProxyShare(): void
343+
{
344+
self::expectException(ClosedException::class);
345+
346+
$loop = EventLoopFactory::create();
347+
$factory = new Factory($loop);
348+
$proxy = new Proxy(new Configuration($factory));
349+
$proxy->close();
350+
$proxy->share(new stdClass(), 'string');
351+
}
352+
353+
/**
354+
* @test
355+
*/
356+
public function cannotUseClosedProxyThread(): void
357+
{
358+
self::expectException(ClosedException::class);
359+
360+
$loop = EventLoopFactory::create();
361+
$factory = new Factory($loop);
362+
$proxy = new Proxy(new Configuration($factory));
363+
$proxy->close();
364+
$proxy->thread(new stdClass(), 'string');
365+
}
366+
367+
/**
368+
* @test
369+
*/
370+
public function cannotUseClosedProxyCreate(): void
371+
{
372+
self::expectException(ClosedException::class);
373+
374+
$loop = EventLoopFactory::create();
375+
$factory = new Factory($loop);
376+
$proxy = new Proxy(new Configuration($factory));
377+
$proxy->close();
378+
$proxy->create(new stdClass(), 'string');
379+
}
309380
}

0 commit comments

Comments
 (0)