Skip to content

Commit

Permalink
Merge branch 'workbunny:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
cclilshy authored Oct 14, 2024
2 parents 5ea639d + cc88a7b commit 043edc6
Show file tree
Hide file tree
Showing 21 changed files with 334 additions and 44 deletions.
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,25 @@ composer require workbunny/webman-coroutine
| - | [`Utils`说明](https://github.com/workbunny/webman-coroutine/tree/main/docs/doc/utils.md) |
| - | [自定义拓展](https://github.com/workbunny/webman-coroutine/tree/main/docs/doc/custom.md) |

## 参与开发

- [Issues](https://github.com/workbunny/webman-coroutine/issues)
- [PR](https://github.com/workbunny/webman-coroutine/pulls)

### 规范

- 新特性提交请先提交feature-issue,再提交PR,避免重复开发;
- Bug修复请先提交bug-repo-issue,再提交PR,避免重复开发;

### 工具

- 代码格式化:`composer cs-fix`
- 静态检查:`composer php-stan`
- 测试与覆盖:`composer unit-test`,命令运行后会在项目创建的`coverage`目录下生成报告
- function-apis文档生成:
- 使用`composer doc-install`或自行安装phpDocumentor
- 在项目根目录使用`phpDocumentor`生成文档

## ♨️ 相关文章

* [webman如何使用swow事件驱动和协程?](https://mp.weixin.qq.com/s?__biz=MzUzMDMxNTQ4Nw==&mid=2247496493&idx=1&sn=4ab95befc894d556eac26d405f354a40&chksm=fa51129dcd269b8b61fc5b1a15a9a23b99b61c0780b9a341dfe3733692e85a1bc5e323ee9775#rd)
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,6 @@
"allow-plugins": {
"symfony/flex": false
},
"process-timeout": 600
"process-timeout": 6000
}
}
5 changes: 4 additions & 1 deletion src/Events/SwooleEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,10 @@ public function del($fd, $flag)
}
}

/** @inheritdoc */
/**
* @inheritdoc
* @codeCoverageIgnore 忽略覆盖
*/
public function loop()
{
// 阻塞等待
Expand Down
5 changes: 4 additions & 1 deletion src/Events/SwowEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,10 @@ public function clearAllTimer()
$this->_timer = [];
}

/** @inheritdoc */
/**
* @codeCoverageIgnore 忽略覆盖
* @inheritdoc
*/
public function loop()
{
// workerman 4.x时,如果不阻塞,则会返回event-loop exited错误
Expand Down
13 changes: 11 additions & 2 deletions src/Handlers/DefaultHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

namespace Workbunny\WebmanCoroutine\Handlers;

use Workbunny\WebmanCoroutine\Exceptions\TimeoutException;

/**
* 默认处理器,使用workerman基础事件
*/
Expand Down Expand Up @@ -34,8 +36,15 @@ public static function initEnv(): void
/** @inheritdoc */
public static function waitFor(?\Closure $closure = null, float|int $timeout = -1): void
{
if ($closure) {
call_user_func($closure);
$time = microtime(true);
while (true) {
if ($closure and call_user_func($closure) === true) {
return;
}
if ($timeout > 0 && microtime(true) - $time >= $timeout) {
throw new TimeoutException("Timeout after $timeout seconds.");
}
sleep(max(intval($timeout), 0));
}
}
}
2 changes: 1 addition & 1 deletion src/Handlers/HandlerMethods.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
trait HandlerMethods
{
/**
* 为了测试可以mock
* @codeCoverageIgnore 为了测试可以mock
*
* @return string
*/
Expand Down
1 change: 1 addition & 0 deletions src/Handlers/RippleHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public static function waitFor(?\Closure $closure = null, float|int $timeout = -
}

/**
* @codeCoverageIgnore 用于测试mock,忽略覆盖
* @param int|float $second
* @return void
*/
Expand Down
4 changes: 3 additions & 1 deletion src/Handlers/RippleWorkerman5Handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

namespace Workbunny\WebmanCoroutine\Handlers;

use Workbunny\WebmanCoroutine\Exceptions\TimeoutException;
use function Workbunny\WebmanCoroutine\package_installed;

/**
Expand Down Expand Up @@ -43,13 +44,14 @@ public static function waitFor(?\Closure $closure = null, float|int $timeout = -
return;
}
if ($timeout > 0 && microtime(true) - $time >= $timeout) {
return;
throw new TimeoutException("Timeout after $timeout seconds.");
}
static::_sleep($timeout);
}
}

/**
* @codeCoverageIgnore mock忽略覆盖
* @param int|float $second
* @return void
*/
Expand Down
4 changes: 4 additions & 0 deletions src/Handlers/SwooleHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@ public static function waitFor(?\Closure $closure = null, float|int $timeout = -
if ($timeout > 0 && microtime(true) - $time >= $timeout) {
throw new TimeoutException("Timeout after $timeout seconds.");
}
/**
* @codeCoverageIgnoreStart 忽略覆盖,该部分直接由swoole接管,无需覆盖
*/
usleep(max((int) ($timeout * 1000 * 1000), 0));
/** @codeCoverageIgnoreEnd */
}
}
}
4 changes: 4 additions & 0 deletions src/Handlers/SwowHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,11 @@ public static function waitFor(?\Closure $closure = null, float|int $timeout = -
if ($timeout > 0 && microtime(true) - $time >= $timeout) {
throw new TimeoutException("Timeout after $timeout seconds.");
}
/**
* @codeCoverageIgnoreStart 忽略覆盖,该部分直接由swow接管,无需覆盖
*/
usleep(max((int) ($timeout * 1000 * 1000), 0));
/** @codeCoverageIgnoreEnd */
}
}
}
4 changes: 2 additions & 2 deletions src/Utils/Pool/Pool.php
Original file line number Diff line number Diff line change
Expand Up @@ -208,11 +208,11 @@ public function __construct(string $name, int $index, mixed $element, bool $clon
if (is_callable($element)) {
Worker::log("Pool $name#$index element is callable. ");
}
$this->_element = $clone ? match (true) {
$this->_element = !$clone ? $element : (match (true) {
is_object($element) => clone $element,
is_array($element) => self::_deepCopyArray($element),
default => $element,
} : $element;
});
}

/**
Expand Down
4 changes: 4 additions & 0 deletions tests/HandlersCase/DefaultHandlerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Workbunny\Tests\HandlersCase;

use PHPUnit\Framework\TestCase;
use Workbunny\WebmanCoroutine\Exceptions\TimeoutException;
use Workbunny\WebmanCoroutine\Handlers\DefaultHandler;

class DefaultHandlerTest extends TestCase
Expand Down Expand Up @@ -36,8 +37,11 @@ public function testWaitFor()
});
$this->assertTrue($return);

// 模拟超时
$this->expectException(TimeoutException::class);
$return = false;
DefaultHandler::waitFor(function () use (&$return) {
sleep(2);
return false;
}, 1);
$this->assertFalse($return);
Expand Down
33 changes: 33 additions & 0 deletions tests/HandlersCase/RevoltHandlerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,38 @@ public function testWaitFor()
return false;
}, 1);
$this->assertFalse($return);

// 模拟毫秒以下超时
$this->expectException(TimeoutException::class);
$return = false;
RevoltHandler::waitFor(function () use (&$return) {
return false;
}, 0.00099);
$this->assertFalse($return);
}

/**
*
* @return void
*/
public function testSleep()
{
$suspensionMock = Mockery::mock('alias:\Revolt\EventLoop\Suspension');
$suspensionMock->shouldReceive('resume')->andReturnNull();
$suspensionMock->shouldReceive('suspend')->andReturnNull();

$eventLoopMock = Mockery::mock('alias:\Revolt\EventLoop');
$eventLoopMock->shouldReceive('getSuspension')->andReturn($suspensionMock);
$eventLoopMock->shouldReceive('defer')->andReturnUsing(function ($closure) {
$closure();
});
$eventLoopMock->shouldReceive('delay')->andReturnUsing(function ($timeout, $closure) {
$closure();
});

RevoltHandler::sleep( 1);
RevoltHandler::sleep( 0.00099);
RevoltHandler::sleep( 0);
$this->assertTrue(true);
}
}
1 change: 1 addition & 0 deletions tests/HandlersCase/RippleHandlerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ public function testWaitFor()
$this->expectException(TimeoutException::class);
$return = false;
$rippleHandlerMock::waitFor(function () use (&$return) {
sleep(2);
return false;
}, 1);
$this->assertFalse($return);
Expand Down
43 changes: 40 additions & 3 deletions tests/HandlersCase/RippleWorkerman5HandlerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,53 @@
namespace Workbunny\Tests\HandlersCase;

use Mockery;
use Workbunny\WebmanCoroutine\Handlers\RippleHandler;
use PHPUnit\Framework\TestCase;
use Workbunny\WebmanCoroutine\Exceptions\TimeoutException;
use Workbunny\WebmanCoroutine\Handlers\RippleWorkerman5Handler;

class RippleWorkerman5HandlerTest extends RippleHandlerTest
class RippleWorkerman5HandlerTest extends TestCase
{
public function testIsAvailable()
{
$rippleHandlerMock = Mockery::mock(RippleHandler::class . '[_getWorkerVersion]');
$rippleHandlerMock = Mockery::mock(RippleWorkerman5Handler::class . '[_getWorkerVersion]');
$rippleHandlerMock->shouldAllowMockingProtectedMethods();
$rippleHandlerMock->shouldReceive('_getWorkerVersion')->andReturn('4.0.0');
$this->assertFalse($rippleHandlerMock::isAvailable());
// todo 可用的情况
}

public function testInitEnv()
{
RippleWorkerman5Handler::initEnv();
$this->assertTrue(true);
}

public function testWaitFor()
{
$rippleHandlerMock = Mockery::mock(RippleWorkerman5Handler::class . '[_sleep]');
$rippleHandlerMock->shouldAllowMockingProtectedMethods();
$rippleHandlerMock->shouldReceive('_sleep')->andReturnNull();

$return = false;
$rippleHandlerMock::waitFor(function () use (&$return) {
return $return = true;
});
$this->assertTrue($return);

$return = false;
$rippleHandlerMock::waitFor(function () use (&$return) {
sleep(1);

return $return = true;
});
$this->assertTrue($return);
// 模拟超时
$this->expectException(TimeoutException::class);
$return = false;
$rippleHandlerMock::waitFor(function () use (&$return) {
sleep(2);
return false;
}, 1);
$this->assertFalse($return);
}
}
1 change: 1 addition & 0 deletions tests/HandlersCase/SwooleHandlerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public function testWaitFor()
$this->expectException(TimeoutException::class);
$return = false;
SwooleHandler::waitFor(function () use (&$return) {
sleep(2);
return false;
}, 1);
$this->assertFalse($return);
Expand Down
49 changes: 48 additions & 1 deletion tests/HandlersCase/SwooleWorkerman5HandlerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,53 @@

namespace Workbunny\Tests\HandlersCase;

class SwooleWorkerman5HandlerTest extends SwooleHandlerTest
use Mockery;
use PHPUnit\Framework\TestCase;
use Workbunny\WebmanCoroutine\Exceptions\TimeoutException;
use Workbunny\WebmanCoroutine\Handlers\SwooleWorkerman5Handler as SwooleHandler;

class SwooleWorkerman5HandlerTest extends TestCase
{
protected function tearDown(): void
{
parent::tearDown();
Mockery::close();
}

public function testIsAvailable()
{
$this->markTestSkipped('Skipped. ');
}

public function testInitEnv()
{
Mockery::mock('alias:Swoole\Runtime')->shouldReceive('enableCoroutine')->andReturnNull();
SwooleHandler::initEnv();
$this->assertTrue(true);
}

public function testWaitFor()
{
$return = false;
SwooleHandler::waitFor(function () use (&$return) {
return $return = true;
});
$this->assertTrue($return);

$return = false;
SwooleHandler::waitFor(function () use (&$return) {
sleep(1);

return $return = true;
});
$this->assertTrue($return);
// 模拟超时
$this->expectException(TimeoutException::class);
$return = false;
SwooleHandler::waitFor(function () use (&$return) {
sleep(2);
return false;
}, 1);
$this->assertFalse($return);
}
}
1 change: 1 addition & 0 deletions tests/HandlersCase/SwowHandlerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public function testWaitFor()
$this->expectException(TimeoutException::class);
$return = false;
SwowHandler::waitFor(function () use (&$return) {
sleep(2);
return false;
}, 1);
$this->assertFalse($return);
Expand Down
Loading

0 comments on commit 043edc6

Please sign in to comment.