mirror of
https://gitee.com/hyperf/hyperf.git
synced 2024-11-29 18:27:44 +08:00
Merge branch 'master' into 2.2-merge
# Conflicts: # composer.json # phpunit.xml
This commit is contained in:
commit
c0c0c47a22
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@ -20,7 +20,7 @@ jobs:
|
||||
fail-fast: false
|
||||
env:
|
||||
SW_VERSION: ${{ matrix.sw-version }}
|
||||
YASD_VERSION: 'v0.3.7'
|
||||
YASD_VERSION: 'v0.3.8'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
@ -1,4 +1,22 @@
|
||||
# v2.1.17 - TBD
|
||||
# v2.1.19 - TBD
|
||||
|
||||
# v2.1.18 - 2021-05-24
|
||||
|
||||
## Fixed
|
||||
|
||||
- [#3598](https://github.com/hyperf/hyperf/pull/3598) Fixed bug that `increment/decrement` does not works as expect when used in transaction for model-cache.
|
||||
- [#3607](https://github.com/hyperf/hyperf/pull/3607) Fixed bug that coroutine won't destruct when using `onOpen` in coroutine style websocket server.
|
||||
- [#3610](https://github.com/hyperf/hyperf/pull/3610) Fixed bug that `fromSub()` and `joinSub()` don't work with table prefix.
|
||||
|
||||
# v2.1.17 - 2021-05-17
|
||||
|
||||
## Fixed
|
||||
|
||||
- [#3856](https://github.com/hyperf/hyperf/pull/3586) Fixed bug that coroutine won't destruct for keepalive request in swow server.
|
||||
|
||||
## Added
|
||||
|
||||
- [#3329](https://github.com/hyperf/hyperf/pull/3329) The `enable` parameter of the `@Crontab` supports `array`, which you can dynamically control whether the task is executed or not.
|
||||
|
||||
# v2.1.16 - 2021-04-26
|
||||
|
||||
|
@ -35,7 +35,7 @@
|
||||
## 数据库
|
||||
|
||||
- [hyperf/database](https://github.com/hyperf/database) Hyperf 官方提供的基于 Eloquent 衍生的数据库 ORM,可复用于其它框架
|
||||
- [hyperf/model](https://github.com/hyperf/model) Hyperf 官方提供的基于 [hyperf/database](https://github.com/hyperf/database) 组件的自动模型缓存组件
|
||||
- [hyperf/model-cache](https://github.com/hyperf/model-cache) Hyperf 官方提供的基于 [hyperf/database](https://github.com/hyperf/database) 组件的自动模型缓存组件
|
||||
- [reasno/fastmongo](https://github.com/Reasno/fastmongo) 基于 `hyperf/gotask` 实现的协程化 `MongoDB` 客户端
|
||||
- [hyperf-ext/translatable](https://github.com/hyperf-ext/translatable) 为模型提供多语言能力
|
||||
|
||||
|
@ -1,5 +1,23 @@
|
||||
# 版本更新记录
|
||||
|
||||
# v2.1.18 - 2021-05-24
|
||||
|
||||
## 修复
|
||||
|
||||
- [#3598](https://github.com/hyperf/hyperf/pull/3598) 修复事务回滚时,模型累加、累减操作会导致模型缓存产生脏数据的问题。
|
||||
- [#3607](https://github.com/hyperf/hyperf/pull/3607) 修复在使用协程风格的 `WebSocket` 服务时,`onOpen` 事件无法在事件结束后销毁协程的问题。
|
||||
- [#3610](https://github.com/hyperf/hyperf/pull/3610) 修复数据库存在前缀时,`fromSub()` 和 `joinSub()` 无法正常使用的问题。
|
||||
|
||||
# v2.1.17 - 2021-05-17
|
||||
|
||||
## 修复
|
||||
|
||||
- [#3856](https://github.com/hyperf/hyperf/pull/3586) 修复 `Swow` 服务处理 `keepalive` 的请求时,协程无法在每个请求后结束的问题。
|
||||
|
||||
## 新增
|
||||
|
||||
- [#3329](https://github.com/hyperf/hyperf/pull/3329) `@Crontab` 注解的 `enable` 参数增加支持设置数组, 你可以通过它动态的控制定时任务是否启动。
|
||||
|
||||
# v2.1.16 - 2021-04-26
|
||||
|
||||
## 修复
|
||||
|
@ -36,7 +36,7 @@ php bin/hyperf.php vendor:publish hyperf/metric
|
||||
`default`:配置文件内的 `default` 对应的值则为使用的驱动名称。驱动的具体配置在 `metric` 项下定义,使用与 `key` 相同的驱动。
|
||||
|
||||
```php
|
||||
'default' => env('TELEMETRY_DRIVER', 'prometheus'),
|
||||
'default' => env('METRIC_DRIVER', 'prometheus'),
|
||||
```
|
||||
|
||||
* `use_standalone_process`: 是否使用 `独立监控进程`。推荐开启。关闭后将在 `Worker 进程` 中处理指标收集与上报。
|
||||
@ -63,7 +63,7 @@ php bin/hyperf.php vendor:publish hyperf/metric
|
||||
use Hyperf\Metric\Adapter\Prometheus\Constants;
|
||||
|
||||
return [
|
||||
'default' => env('TELEMETRY_DRIVER', 'prometheus'),
|
||||
'default' => env('METRIC_DRIVER', 'prometheus'),
|
||||
'use_standalone_process' => env('TELEMETRY_USE_STANDALONE_PROCESS', true),
|
||||
'enable_default_metric' => env('TELEMETRY_ENABLE_DEFAULT_TELEMETRY', true),
|
||||
'default_metric_interval' => env('DEFAULT_METRIC_INTERVAL', 5),
|
||||
@ -116,7 +116,7 @@ Prometheus 有两种工作模式,爬模式与推模式(通过 Prometheus Pus
|
||||
|
||||
```php
|
||||
return [
|
||||
'default' => env('TELEMETRY_DRIVER', 'statd'),
|
||||
'default' => env('METRIC_DRIVER', 'statd'),
|
||||
'use_standalone_process' => env('TELEMETRY_USE_STANDALONE_PROCESS', true),
|
||||
'enable_default_metric' => env('TELEMETRY_ENABLE_DEFAULT_TELEMETRY', true),
|
||||
'metric' => [
|
||||
@ -141,7 +141,7 @@ StatsD 目前只支持 UDP 模式,需要配置 UDP 地址 `udp_host`,UDP 端
|
||||
|
||||
```php
|
||||
return [
|
||||
'default' => env('TELEMETRY_DRIVER', 'influxdb'),
|
||||
'default' => env('METRIC_DRIVER', 'influxdb'),
|
||||
'use_standalone_process' => env('TELEMETRY_USE_STANDALONE_PROCESS', true),
|
||||
'enable_default_metric' => env('TELEMETRY_ENABLE_DEFAULT_TELEMETRY', true),
|
||||
'metric' => [
|
||||
|
@ -35,7 +35,7 @@
|
||||
## 數據庫
|
||||
|
||||
- [hyperf/database](https://github.com/hyperf/database) Hyperf 官方提供的基於 Eloquent 衍生的數據庫 ORM,可複用於其它框架
|
||||
- [hyperf/model](https://github.com/hyperf/model) Hyperf 官方提供的基於 [hyperf/database](https://github.com/hyperf/database) 組件的自動模型緩存組件
|
||||
- [hyperf/model-cache](https://github.com/hyperf/model-cache) Hyperf 官方提供的基於 [hyperf/database](https://github.com/hyperf/database) 組件的自動模型緩存組件
|
||||
- [reasno/fastmongo](https://github.com/Reasno/fastmongo) 基於 `hyperf/gotask` 實現的協程化 `MongoDB` 客户端
|
||||
- [hyperf-ext/translatable](https://github.com/hyperf-ext/translatable) 為模型提供多語言能力
|
||||
|
||||
|
@ -1,5 +1,23 @@
|
||||
# 版本更新記錄
|
||||
|
||||
# v2.1.18 - 2021-05-24
|
||||
|
||||
## 修復
|
||||
|
||||
- [#3598](https://github.com/hyperf/hyperf/pull/3598) 修復事務回滾時,模型累加、累減操作會導致模型緩存產生髒數據的問題。
|
||||
- [#3607](https://github.com/hyperf/hyperf/pull/3607) 修復在使用協程風格的 `WebSocket` 服務時,`onOpen` 事件無法在事件結束後銷燬協程的問題。
|
||||
- [#3610](https://github.com/hyperf/hyperf/pull/3610) 修復數據庫存在前綴時,`fromSub()` 和 `joinSub()` 無法正常使用的問題。
|
||||
|
||||
# v2.1.17 - 2021-05-17
|
||||
|
||||
## 修復
|
||||
|
||||
- [#3856](https://github.com/hyperf/hyperf/pull/3586) 修復 `Swow` 服務處理 `keepalive` 的請求時,協程無法在每個請求後結束的問題。
|
||||
|
||||
## 新增
|
||||
|
||||
- [#3329](https://github.com/hyperf/hyperf/pull/3329) `@Crontab` 註解的 `enable` 參數增加支持設置數組, 你可以通過它動態的控制定時任務是否啟動。
|
||||
|
||||
# v2.1.16 - 2021-04-26
|
||||
|
||||
## 修復
|
||||
|
@ -39,7 +39,7 @@ php bin/hyperf.php vendor:publish hyperf/metric
|
||||
`default`:配置文件內的 `default` 對應的值則為使用的驅動名稱。驅動的具體配置在 `metric` 項下定義,使用與 `key` 相同的驅動。
|
||||
|
||||
```php
|
||||
'default' => env('TELEMETRY_DRIVER', 'prometheus'),
|
||||
'default' => env('METRIC_DRIVER', 'prometheus'),
|
||||
```
|
||||
|
||||
* `use_standalone_process`: 是否使用 `獨立監控進程`。推薦開啟。關閉後將在 `Worker 進程` 中處理指標收集與上報。
|
||||
@ -66,7 +66,7 @@ php bin/hyperf.php vendor:publish hyperf/metric
|
||||
use Hyperf\Metric\Adapter\Prometheus\Constants;
|
||||
|
||||
return [
|
||||
'default' => env('TELEMETRY_DRIVER', 'prometheus'),
|
||||
'default' => env('METRIC_DRIVER', 'prometheus'),
|
||||
'use_standalone_process' => env('TELEMETRY_USE_STANDALONE_PROCESS', true),
|
||||
'enable_default_metric' => env('TELEMETRY_ENABLE_DEFAULT_TELEMETRY', true),
|
||||
'default_metric_interval' => env('DEFAULT_METRIC_INTERVAL', 5),
|
||||
@ -119,7 +119,7 @@ Prometheus 有兩種工作模式,爬模式與推模式(通過 Prometheus Pus
|
||||
|
||||
```php
|
||||
return [
|
||||
'default' => env('TELEMETRY_DRIVER', 'statd'),
|
||||
'default' => env('METRIC_DRIVER', 'statd'),
|
||||
'use_standalone_process' => env('TELEMETRY_USE_STANDALONE_PROCESS', true),
|
||||
'enable_default_metric' => env('TELEMETRY_ENABLE_DEFAULT_TELEMETRY', true),
|
||||
'metric' => [
|
||||
@ -144,7 +144,7 @@ StatsD 目前只支持 UDP 模式,需要配置 UDP 地址 `udp_host`,UDP 端
|
||||
|
||||
```php
|
||||
return [
|
||||
'default' => env('TELEMETRY_DRIVER', 'influxdb'),
|
||||
'default' => env('METRIC_DRIVER', 'influxdb'),
|
||||
'use_standalone_process' => env('TELEMETRY_USE_STANDALONE_PROCESS', true),
|
||||
'enable_default_metric' => env('TELEMETRY_ENABLE_DEFAULT_TELEMETRY', true),
|
||||
'metric' => [
|
||||
|
@ -35,7 +35,7 @@
|
||||
## 資料庫
|
||||
|
||||
- [hyperf/database](https://github.com/hyperf/database) Hyperf 官方提供的基於 Eloquent 衍生的資料庫 ORM,可複用於其它框架
|
||||
- [hyperf/model](https://github.com/hyperf/model) Hyperf 官方提供的基於 [hyperf/database](https://github.com/hyperf/database) 元件的自動模型快取元件
|
||||
- [hyperf/model-cache](https://github.com/hyperf/model-cache) Hyperf 官方提供的基於 [hyperf/database](https://github.com/hyperf/database) 元件的自動模型快取元件
|
||||
- [reasno/fastmongo](https://github.com/Reasno/fastmongo) 基於 `hyperf/gotask` 實現的協程化 `MongoDB` 客戶端
|
||||
- [hyperf-ext/translatable](https://github.com/hyperf-ext/translatable) 為模型提供多語言能力
|
||||
|
||||
|
@ -1,5 +1,23 @@
|
||||
# 版本更新記錄
|
||||
|
||||
# v2.1.18 - 2021-05-24
|
||||
|
||||
## 修復
|
||||
|
||||
- [#3598](https://github.com/hyperf/hyperf/pull/3598) 修復事務回滾時,模型累加、累減操作會導致模型快取產生髒資料的問題。
|
||||
- [#3607](https://github.com/hyperf/hyperf/pull/3607) 修復在使用協程風格的 `WebSocket` 服務時,`onOpen` 事件無法在事件結束後銷燬協程的問題。
|
||||
- [#3610](https://github.com/hyperf/hyperf/pull/3610) 修復資料庫存在字首時,`fromSub()` 和 `joinSub()` 無法正常使用的問題。
|
||||
|
||||
# v2.1.17 - 2021-05-17
|
||||
|
||||
## 修復
|
||||
|
||||
- [#3856](https://github.com/hyperf/hyperf/pull/3586) 修復 `Swow` 服務處理 `keepalive` 的請求時,協程無法在每個請求後結束的問題。
|
||||
|
||||
## 新增
|
||||
|
||||
- [#3329](https://github.com/hyperf/hyperf/pull/3329) `@Crontab` 註解的 `enable` 引數增加支援設定陣列, 你可以通過它動態的控制定時任務是否啟動。
|
||||
|
||||
# v2.1.16 - 2021-04-26
|
||||
|
||||
## 修復
|
||||
|
@ -36,7 +36,7 @@ php bin/hyperf.php vendor:publish hyperf/metric
|
||||
`default`:配置檔案內的 `default` 對應的值則為使用的驅動名稱。驅動的具體配置在 `metric` 項下定義,使用與 `key` 相同的驅動。
|
||||
|
||||
```php
|
||||
'default' => env('TELEMETRY_DRIVER', 'prometheus'),
|
||||
'default' => env('METRIC_DRIVER', 'prometheus'),
|
||||
```
|
||||
|
||||
* `use_standalone_process`: 是否使用 `獨立監控程序`。推薦開啟。關閉後將在 `Worker 程序` 中處理指標收集與上報。
|
||||
@ -63,7 +63,7 @@ php bin/hyperf.php vendor:publish hyperf/metric
|
||||
use Hyperf\Metric\Adapter\Prometheus\Constants;
|
||||
|
||||
return [
|
||||
'default' => env('TELEMETRY_DRIVER', 'prometheus'),
|
||||
'default' => env('METRIC_DRIVER', 'prometheus'),
|
||||
'use_standalone_process' => env('TELEMETRY_USE_STANDALONE_PROCESS', true),
|
||||
'enable_default_metric' => env('TELEMETRY_ENABLE_DEFAULT_TELEMETRY', true),
|
||||
'default_metric_interval' => env('DEFAULT_METRIC_INTERVAL', 5),
|
||||
@ -116,7 +116,7 @@ Prometheus 有兩種工作模式,爬模式與推模式(通過 Prometheus Pus
|
||||
|
||||
```php
|
||||
return [
|
||||
'default' => env('TELEMETRY_DRIVER', 'statd'),
|
||||
'default' => env('METRIC_DRIVER', 'statd'),
|
||||
'use_standalone_process' => env('TELEMETRY_USE_STANDALONE_PROCESS', true),
|
||||
'enable_default_metric' => env('TELEMETRY_ENABLE_DEFAULT_TELEMETRY', true),
|
||||
'metric' => [
|
||||
@ -141,7 +141,7 @@ StatsD 目前只支援 UDP 模式,需要配置 UDP 地址 `udp_host`,UDP 埠
|
||||
|
||||
```php
|
||||
return [
|
||||
'default' => env('TELEMETRY_DRIVER', 'influxdb'),
|
||||
'default' => env('METRIC_DRIVER', 'influxdb'),
|
||||
'use_standalone_process' => env('TELEMETRY_USE_STANDALONE_PROCESS', true),
|
||||
'enable_default_metric' => env('TELEMETRY_ENABLE_DEFAULT_TELEMETRY', true),
|
||||
'metric' => [
|
||||
|
@ -18,6 +18,7 @@
|
||||
<directory suffix="Test.php">./src/config-zookeeper/tests</directory>
|
||||
<directory suffix="Test.php">./src/constants/tests</directory>
|
||||
<directory suffix="Test.php">./src/consul/tests</directory>
|
||||
<directory suffix="Test.php">./src/crontab/tests</directory>
|
||||
<directory suffix="Test.php">./src/dag/tests</directory>
|
||||
<directory suffix="Test.php">./src/database/tests</directory>
|
||||
<directory suffix="Test.php">./src/db/tests</directory>
|
||||
@ -83,6 +84,7 @@
|
||||
<directory suffix=".php">./src/config/src</directory>
|
||||
<directory suffix=".php">./src/constants/src</directory>
|
||||
<directory suffix=".php">./src/consul/src</directory>
|
||||
<directory suffix=".php">./src/crontab/src</directory>
|
||||
<directory suffix=".php">./src/dag/src</directory>
|
||||
<directory suffix=".php">./src/database/src</directory>
|
||||
<directory suffix=".php">./src/db-connection/src</directory>
|
||||
@ -113,6 +115,7 @@
|
||||
<directory suffix=".php">./src/task/src</directory>
|
||||
<directory suffix=".php">./src/utils/src</directory>
|
||||
<directory suffix=".php">./src/websocket-client/src</directory>
|
||||
<directory suffix=".php">./src/websocket-server/src</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
</phpunit>
|
||||
|
@ -68,7 +68,7 @@ class Crontab extends AbstractAnnotation
|
||||
public $memo = '';
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
* @var array|bool
|
||||
*/
|
||||
public $enable = true;
|
||||
|
||||
@ -99,10 +99,23 @@ class Crontab extends AbstractAnnotation
|
||||
}
|
||||
|
||||
public function collectClass(string $className): void
|
||||
{
|
||||
$this->parseName($className);
|
||||
$this->parseCallback($className);
|
||||
$this->parseEnable($className);
|
||||
|
||||
parent::collectClass($className);
|
||||
}
|
||||
|
||||
protected function parseName(string $className): void
|
||||
{
|
||||
if (! $this->name) {
|
||||
$this->name = $className;
|
||||
}
|
||||
}
|
||||
|
||||
protected function parseCallback(string $className): void
|
||||
{
|
||||
if (! $this->callback) {
|
||||
$reflectionClass = ReflectionManager::reflectClass($className);
|
||||
$reflectionMethods = $reflectionClass->getMethods(ReflectionMethod::IS_PUBLIC);
|
||||
@ -127,6 +140,22 @@ class Crontab extends AbstractAnnotation
|
||||
} elseif (is_string($this->callback)) {
|
||||
$this->callback = [$className, $this->callback];
|
||||
}
|
||||
parent::collectClass($className);
|
||||
}
|
||||
|
||||
protected function parseEnable(string $className): void
|
||||
{
|
||||
if (is_string($this->enable) && $this->enable === 'true') {
|
||||
$this->enable = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_string($this->enable) && $this->enable === 'false') {
|
||||
$this->enable = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_string($this->enable)) {
|
||||
$this->enable = [$className, $this->enable];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,9 +17,11 @@ use Hyperf\Crontab\Annotation\Crontab as CrontabAnnotation;
|
||||
use Hyperf\Crontab\Crontab;
|
||||
use Hyperf\Crontab\CrontabManager;
|
||||
use Hyperf\Di\Annotation\AnnotationCollector;
|
||||
use Hyperf\Di\ReflectionManager;
|
||||
use Hyperf\Event\Contract\ListenerInterface;
|
||||
use Hyperf\Process\Event\BeforeCoroutineHandle;
|
||||
use Hyperf\Process\Event\BeforeProcessHandle;
|
||||
use Hyperf\Utils\ApplicationContext;
|
||||
|
||||
class CrontabRegisterListener implements ListenerInterface
|
||||
{
|
||||
@ -64,9 +66,8 @@ class CrontabRegisterListener implements ListenerInterface
|
||||
{
|
||||
$crontabs = $this->parseCrontabs();
|
||||
foreach ($crontabs as $crontab) {
|
||||
if ($crontab instanceof Crontab) {
|
||||
if ($crontab instanceof Crontab && $this->crontabManager->register($crontab)) {
|
||||
$this->logger->debug(sprintf('Crontab %s have been registered.', $crontab->getName()));
|
||||
$this->crontabManager->register($crontab);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -88,7 +89,7 @@ class CrontabRegisterListener implements ListenerInterface
|
||||
return array_values($crontabs);
|
||||
}
|
||||
|
||||
private function getCrontabsFromMethod()
|
||||
private function getCrontabsFromMethod(): array
|
||||
{
|
||||
$result = AnnotationCollector::getMethodsByAnnotation(CrontabAnnotation::class);
|
||||
$crontabs = [];
|
||||
@ -110,7 +111,43 @@ class CrontabRegisterListener implements ListenerInterface
|
||||
isset($annotation->onOneServer) && $crontab->setOnOneServer($annotation->onOneServer);
|
||||
isset($annotation->callback) && $crontab->setCallback($annotation->callback);
|
||||
isset($annotation->memo) && $crontab->setMemo($annotation->memo);
|
||||
isset($annotation->enable) && $crontab->setEnable($annotation->enable);
|
||||
isset($annotation->enable) && $crontab->setEnable($this->resolveCrontabEnableMethod($annotation->enable));
|
||||
|
||||
return $crontab;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|bool $enable
|
||||
*/
|
||||
private function resolveCrontabEnableMethod($enable): bool
|
||||
{
|
||||
if (is_bool($enable)) {
|
||||
return $enable;
|
||||
}
|
||||
|
||||
$className = reset($enable);
|
||||
$method = end($enable);
|
||||
|
||||
try {
|
||||
$reflectionClass = ReflectionManager::reflectClass($className);
|
||||
$reflectionMethod = $reflectionClass->getMethod($method);
|
||||
|
||||
if ($reflectionMethod->isPublic()) {
|
||||
if ($reflectionMethod->isStatic()) {
|
||||
return $className::$method();
|
||||
}
|
||||
|
||||
$container = ApplicationContext::getContainer();
|
||||
if ($container->has($className)) {
|
||||
return $container->get($className)->{$method}();
|
||||
}
|
||||
}
|
||||
|
||||
$this->logger->info('Crontab enable method is not public, skip register.');
|
||||
} catch (\ReflectionException $e) {
|
||||
$this->logger->error('Resolve crontab enable failed, skip register.');
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
66
src/crontab/tests/CrontabAnnotationTest.php
Normal file
66
src/crontab/tests/CrontabAnnotationTest.php
Normal file
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace HyperfTest\Crontab;
|
||||
|
||||
use Hyperf\Crontab\Annotation\Crontab;
|
||||
use HyperfTest\Crontab\Stub\FooCron;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @coversNothing
|
||||
*/
|
||||
class CrontabAnnotationTest extends TestCase
|
||||
{
|
||||
public function testCallableNotExist()
|
||||
{
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
$annotation = new Crontab();
|
||||
$annotation->collectClass(FooCron::class);
|
||||
}
|
||||
|
||||
public function testCallableNormal()
|
||||
{
|
||||
$annotation = new Crontab();
|
||||
$annotation->callback = 'execute';
|
||||
$annotation->collectClass(FooCron::class);
|
||||
$this->assertEquals([FooCron::class, 'execute'], $annotation->callback);
|
||||
}
|
||||
|
||||
public function testEnable()
|
||||
{
|
||||
$annotation = new Crontab();
|
||||
$annotation->callback = 'execute';
|
||||
$annotation->collectClass(FooCron::class);
|
||||
$this->assertTrue($annotation->enable);
|
||||
|
||||
$annotation = new Crontab();
|
||||
$annotation->callback = 'execute';
|
||||
$annotation->enable = 'true';
|
||||
$annotation->collectClass(FooCron::class);
|
||||
$this->assertTrue($annotation->enable);
|
||||
|
||||
$annotation = new Crontab();
|
||||
$annotation->callback = 'execute';
|
||||
$annotation->enable = 'isEnable';
|
||||
$annotation->collectClass(FooCron::class);
|
||||
$this->assertEquals([FooCron::class, 'isEnable'], $annotation->enable);
|
||||
}
|
||||
|
||||
public function testCollectMethod()
|
||||
{
|
||||
$annotation = new Crontab();
|
||||
$annotation->collectMethod(FooCron::class, 'cron');
|
||||
$this->assertSame(FooCron::class . '::cron', $annotation->name);
|
||||
$this->assertSame([FooCron::class, 'cron'], $annotation->callback);
|
||||
}
|
||||
}
|
122
src/crontab/tests/CrontabRegisterListenerTest.php
Normal file
122
src/crontab/tests/CrontabRegisterListenerTest.php
Normal file
@ -0,0 +1,122 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace HyperfTest\Crontab;
|
||||
|
||||
use Hyperf\Config\Config;
|
||||
use Hyperf\Contract\ConfigInterface;
|
||||
use Hyperf\Contract\StdoutLoggerInterface;
|
||||
use Hyperf\Crontab\Annotation\Crontab;
|
||||
use Hyperf\Crontab\Annotation\Crontab as CrontabAnnotation;
|
||||
use Hyperf\Crontab\CrontabManager;
|
||||
use Hyperf\Crontab\Listener\CrontabRegisterListener;
|
||||
use Hyperf\Crontab\Parser;
|
||||
use Hyperf\Di\Annotation\AnnotationCollector;
|
||||
use Hyperf\Di\Container;
|
||||
use Hyperf\Utils\ApplicationContext;
|
||||
use Hyperf\Utils\Reflection\ClassInvoker;
|
||||
use HyperfTest\Crontab\Stub\FooCron;
|
||||
use HyperfTest\Crontab\Stub\FooCron2;
|
||||
use Mockery;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Psr\Container\ContainerInterface;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @coversNothing
|
||||
*/
|
||||
class CrontabRegisterListenerTest extends TestCase
|
||||
{
|
||||
protected $prevContainer;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
if (ApplicationContext::hasContainer()) {
|
||||
$this->prevContainer = ApplicationContext::getContainer();
|
||||
}
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
if ($this->prevContainer instanceof ContainerInterface) {
|
||||
ApplicationContext::setContainer($this->prevContainer);
|
||||
}
|
||||
}
|
||||
|
||||
public function testBuildCrontabWithoutConstructorByAnnotationEnableMethod()
|
||||
{
|
||||
$container = Mockery::mock(Container::class);
|
||||
$container->shouldReceive('has')->with(FooCron2::class)->andReturnTrue();
|
||||
$container->shouldReceive('get')->with(FooCron2::class)->andReturn(new FooCron2());
|
||||
ApplicationContext::setContainer($container);
|
||||
|
||||
$crontabAnnotation = new Crontab();
|
||||
$crontabAnnotation->callback = 'execute';
|
||||
$crontabAnnotation->enable = 'isEnable';
|
||||
$crontabAnnotation->collectClass(FooCron2::class);
|
||||
|
||||
$annotationCrontabs = AnnotationCollector::getClassesByAnnotation(CrontabAnnotation::class);
|
||||
|
||||
$manager = new CrontabManager(new Parser());
|
||||
$class = new ClassInvoker(new CrontabRegisterListener($manager, Mockery::mock(StdoutLoggerInterface::class), Mockery::mock(ConfigInterface::class)));
|
||||
|
||||
$crontab = $class->buildCrontabByAnnotation($annotationCrontabs[FooCron2::class]);
|
||||
|
||||
$this->assertTrue($crontab->isEnable());
|
||||
}
|
||||
|
||||
public function testBuildCrontabWithConstructorByAnnotationEnableMethod()
|
||||
{
|
||||
$container = Mockery::mock(Container::class);
|
||||
$container->shouldReceive('has')->with(FooCron::class)->andReturnTrue();
|
||||
$container->shouldReceive('get')->with(FooCron::class)->andReturn(new FooCron(new Config([
|
||||
'enable' => true,
|
||||
])));
|
||||
ApplicationContext::setContainer($container);
|
||||
|
||||
$crontabAnnotation = new Crontab();
|
||||
$crontabAnnotation->callback = 'execute';
|
||||
$crontabAnnotation->enable = 'isEnable';
|
||||
$crontabAnnotation->collectClass(FooCron::class);
|
||||
|
||||
$annotationCrontabs = AnnotationCollector::getClassesByAnnotation(CrontabAnnotation::class);
|
||||
|
||||
$manager = new CrontabManager(new Parser());
|
||||
$class = new ClassInvoker(new CrontabRegisterListener($manager, Mockery::mock(StdoutLoggerInterface::class), Mockery::mock(ConfigInterface::class)));
|
||||
|
||||
$crontab = $class->buildCrontabByAnnotation($annotationCrontabs[FooCron::class]);
|
||||
|
||||
$this->assertTrue($crontab->isEnable());
|
||||
}
|
||||
|
||||
public function testBuildCrontabWithStaticMethodByAnnotationEnableMethod()
|
||||
{
|
||||
$container = Mockery::mock(Container::class);
|
||||
$container->shouldReceive('has')->with(FooCron::class)->andReturnTrue();
|
||||
$container->shouldReceive('get')->with(FooCron::class)->andReturn(new FooCron(new Config([
|
||||
'enable' => true,
|
||||
])));
|
||||
ApplicationContext::setContainer($container);
|
||||
|
||||
$crontabAnnotation = new Crontab();
|
||||
$crontabAnnotation->callback = 'execute';
|
||||
$crontabAnnotation->enable = 'isEnableCrontab';
|
||||
$crontabAnnotation->collectClass(FooCron::class);
|
||||
|
||||
$annotationCrontabs = AnnotationCollector::getClassesByAnnotation(CrontabAnnotation::class);
|
||||
|
||||
$manager = new CrontabManager(new Parser());
|
||||
$class = new ClassInvoker(new CrontabRegisterListener($manager, Mockery::mock(StdoutLoggerInterface::class), Mockery::mock(ConfigInterface::class)));
|
||||
$crontab = $class->buildCrontabByAnnotation($annotationCrontabs[FooCron::class]);
|
||||
|
||||
$this->assertTrue($crontab->isEnable());
|
||||
}
|
||||
}
|
Binary file not shown.
@ -26,6 +26,11 @@ class ParserCronNumberTest extends TestCase
|
||||
ini_set('date.timezone', 'Asia/Shanghai');
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
ini_set('date.timezone', '');
|
||||
}
|
||||
|
||||
public function testParse()
|
||||
{
|
||||
$parser = new Parser();
|
||||
|
@ -26,6 +26,11 @@ class ParserTest extends TestCase
|
||||
ini_set('date.timezone', 'Asia/Shanghai');
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
ini_set('date.timezone', '');
|
||||
}
|
||||
|
||||
public function testParseSecondLevel()
|
||||
{
|
||||
$crontabString = '*/11 * * * * *';
|
||||
|
42
src/crontab/tests/Stub/FooCron.php
Normal file
42
src/crontab/tests/Stub/FooCron.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace HyperfTest\Crontab\Stub;
|
||||
|
||||
use Hyperf\Contract\ConfigInterface;
|
||||
|
||||
class FooCron
|
||||
{
|
||||
protected $config;
|
||||
|
||||
public function __construct(ConfigInterface $config)
|
||||
{
|
||||
$this->config = $config->get('enable', false);
|
||||
}
|
||||
|
||||
public function execute()
|
||||
{
|
||||
}
|
||||
|
||||
public function isEnable()
|
||||
{
|
||||
return (bool) $this->config;
|
||||
}
|
||||
|
||||
public static function isEnableCrontab(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected function bar()
|
||||
{
|
||||
}
|
||||
}
|
24
src/crontab/tests/Stub/FooCron2.php
Normal file
24
src/crontab/tests/Stub/FooCron2.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace HyperfTest\Crontab\Stub;
|
||||
|
||||
class FooCron2
|
||||
{
|
||||
public function execute()
|
||||
{
|
||||
}
|
||||
|
||||
public function isEnable()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
@ -28,7 +28,6 @@ use Psr\EventDispatcher\EventDispatcherInterface;
|
||||
use Psr\EventDispatcher\StoppableEventInterface;
|
||||
|
||||
/**
|
||||
* @mixin Builder
|
||||
* @mixin ModelIDE
|
||||
*/
|
||||
abstract class Model implements ArrayAccess, Arrayable, Jsonable, JsonSerializable, CompressInterface
|
||||
|
@ -324,7 +324,7 @@ class Builder
|
||||
{
|
||||
[$query, $bindings] = $this->createSub($query);
|
||||
|
||||
return $this->fromRaw('(' . $query . ') as ' . $this->grammar->wrap($as), $bindings);
|
||||
return $this->fromRaw('(' . $query . ') as ' . $this->grammar->wrapTable($as), $bindings);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -455,7 +455,7 @@ class Builder
|
||||
{
|
||||
[$query, $bindings] = $this->createSub($query);
|
||||
|
||||
$expression = '(' . $query . ') as ' . $this->grammar->wrap($as);
|
||||
$expression = '(' . $query . ') as ' . $this->grammar->wrapTable($as);
|
||||
|
||||
$this->addBinding($bindings, 'join');
|
||||
|
||||
|
@ -659,6 +659,25 @@ class DatabaseQueryBuilderTest extends TestCase
|
||||
$this->assertEquals([], $builder->getBindings());
|
||||
}
|
||||
|
||||
public function testJoinSubWithPrefix()
|
||||
{
|
||||
$builder = $this->getBuilder();
|
||||
$builder->getGrammar()->setTablePrefix('prefix_');
|
||||
$builder->from('users')->joinSub('select * from "contacts"', 'sub', 'users.id', '=', 'sub.id');
|
||||
$this->assertEquals('select * from "prefix_users" inner join (select * from "contacts") as "prefix_sub" on "prefix_users"."id" = "prefix_sub"."id"', $builder->toSql());
|
||||
}
|
||||
|
||||
public function testFromSubWithPrefix()
|
||||
{
|
||||
$builder = $this->getBuilder();
|
||||
$builder->getGrammar()->setTablePrefix('prefix_');
|
||||
$builder->fromSub(function ($query) {
|
||||
$query->select(new Raw('max(last_seen_at) as last_seen_at'))->from('user_sessions')->where('foo', '=', '1');
|
||||
}, 'sessions')->where('bar', '<', '10');
|
||||
$this->assertEquals('select * from (select max(last_seen_at) as last_seen_at from "prefix_user_sessions" where "foo" = ?) as "prefix_sessions" where "bar" < ?', $builder->toSql());
|
||||
$this->assertEquals(['1', '10'], $builder->getBindings());
|
||||
}
|
||||
|
||||
protected function getBuilder()
|
||||
{
|
||||
$grammar = new Grammar();
|
||||
|
@ -78,7 +78,9 @@ trait Cacheable
|
||||
{
|
||||
$res = parent::increment($column, $amount, $extra);
|
||||
if ($res > 0) {
|
||||
if (empty($extra)) {
|
||||
if ($this->getConnection()->transactionLevel() && $this instanceof CacheableInterface) {
|
||||
InvalidCacheManager::instance()->push($this);
|
||||
} elseif (empty($extra)) {
|
||||
// Only increment a column's value.
|
||||
/** @var Manager $manager */
|
||||
$manager = $this->getContainer()->get(Manager::class);
|
||||
@ -101,7 +103,9 @@ trait Cacheable
|
||||
{
|
||||
$res = parent::decrement($column, $amount, $extra);
|
||||
if ($res > 0) {
|
||||
if (empty($extra)) {
|
||||
if ($this->getConnection()->transactionLevel() && $this instanceof CacheableInterface) {
|
||||
InvalidCacheManager::instance()->push($this);
|
||||
} elseif (empty($extra)) {
|
||||
// Only decrement a column's value.
|
||||
/** @var Manager $manager */
|
||||
$manager = $this->getContainer()->get(Manager::class);
|
||||
|
@ -12,10 +12,13 @@ declare(strict_types=1);
|
||||
namespace HyperfTest\ModelCache;
|
||||
|
||||
use Hyperf\Database\Model\Relations\Relation;
|
||||
use Hyperf\DbConnection\Db;
|
||||
use Hyperf\DbConnection\Listener\InitTableCollectorListener;
|
||||
use Hyperf\ModelCache\EagerLoad\EagerLoader;
|
||||
use Hyperf\ModelCache\InvalidCacheManager;
|
||||
use Hyperf\ModelCache\Listener\EagerLoadListener;
|
||||
use Hyperf\Redis\RedisProxy;
|
||||
use Hyperf\Utils\Reflection\ClassInvoker;
|
||||
use HyperfTest\ModelCache\Stub\BookModel;
|
||||
use HyperfTest\ModelCache\Stub\ContainerStub;
|
||||
use HyperfTest\ModelCache\Stub\ImageModel;
|
||||
@ -381,4 +384,104 @@ class ModelCacheTest extends TestCase
|
||||
BookModel::findFromCache(1);
|
||||
$this->assertSame(100, $redis->ttl('{mc:default:m:book}:id:1'));
|
||||
}
|
||||
|
||||
public function testModelSaveInTransaction()
|
||||
{
|
||||
$container = ContainerStub::mockContainer();
|
||||
|
||||
$id = 209;
|
||||
UserModel::query()->firstOrCreate(['id' => $id], [
|
||||
'name' => uniqid(),
|
||||
'gender' => 1,
|
||||
]);
|
||||
|
||||
$redis = $container->make(RedisProxy::class, ['pool' => 'default']);
|
||||
|
||||
wait(function () use ($redis, $id) {
|
||||
Db::beginTransaction();
|
||||
try {
|
||||
$model = UserModel::findFromCache($id);
|
||||
/* @var \Redis $redis */
|
||||
$this->assertEquals(1, $redis->exists('{mc:default:m:user}:id:' . $id));
|
||||
$model->gender = 2;
|
||||
$model->save();
|
||||
$this->assertEquals(1, $redis->hGet('{mc:default:m:user}:id:' . $id, 'gender'));
|
||||
$invoker = new ClassInvoker(InvalidCacheManager::instance());
|
||||
$this->assertSame(1, count($invoker->models));
|
||||
Db::commit();
|
||||
} catch (\Throwable $exception) {
|
||||
Db::rollBack();
|
||||
}
|
||||
});
|
||||
|
||||
$this->assertSame(0, $redis->exists('{mc:default:m:user}:id:' . $id));
|
||||
|
||||
UserModel::query(true)->where('id', $id)->delete();
|
||||
}
|
||||
|
||||
public function testModelIncrInTransaction()
|
||||
{
|
||||
$container = ContainerStub::mockContainer();
|
||||
|
||||
$id = 209;
|
||||
UserModel::query()->firstOrCreate(['id' => $id], [
|
||||
'name' => uniqid(),
|
||||
'gender' => 1,
|
||||
]);
|
||||
|
||||
$redis = $container->make(RedisProxy::class, ['pool' => 'default']);
|
||||
|
||||
wait(function () use ($redis, $id) {
|
||||
Db::beginTransaction();
|
||||
try {
|
||||
$model = UserModel::findFromCache($id);
|
||||
/* @var \Redis $redis */
|
||||
$this->assertEquals(1, $redis->exists('{mc:default:m:user}:id:' . $id));
|
||||
$model->increment('gender');
|
||||
$this->assertEquals(1, $redis->hGet('{mc:default:m:user}:id:' . $id, 'gender'));
|
||||
$invoker = new ClassInvoker(InvalidCacheManager::instance());
|
||||
$this->assertSame(1, count($invoker->models));
|
||||
Db::commit();
|
||||
} catch (\Throwable $exception) {
|
||||
Db::rollBack();
|
||||
}
|
||||
});
|
||||
|
||||
$this->assertSame(0, $redis->exists('{mc:default:m:user}:id:' . $id));
|
||||
|
||||
UserModel::query(true)->where('id', $id)->delete();
|
||||
}
|
||||
|
||||
public function testModelDecrInTransaction()
|
||||
{
|
||||
$container = ContainerStub::mockContainer();
|
||||
|
||||
$id = 209;
|
||||
UserModel::query()->firstOrCreate(['id' => $id], [
|
||||
'name' => uniqid(),
|
||||
'gender' => 1,
|
||||
]);
|
||||
|
||||
$redis = $container->make(RedisProxy::class, ['pool' => 'default']);
|
||||
|
||||
wait(function () use ($redis, $id) {
|
||||
Db::beginTransaction();
|
||||
try {
|
||||
$model = UserModel::findFromCache($id);
|
||||
/* @var \Redis $redis */
|
||||
$this->assertEquals(1, $redis->exists('{mc:default:m:user}:id:' . $id));
|
||||
$model->decrement('gender');
|
||||
$this->assertEquals(1, $redis->hGet('{mc:default:m:user}:id:' . $id, 'gender'));
|
||||
$invoker = new ClassInvoker(InvalidCacheManager::instance());
|
||||
$this->assertSame(1, count($invoker->models));
|
||||
Db::commit();
|
||||
} catch (\Throwable $exception) {
|
||||
Db::rollBack();
|
||||
}
|
||||
});
|
||||
|
||||
$this->assertSame(0, $redis->exists('{mc:default:m:user}:id:' . $id));
|
||||
|
||||
UserModel::query(true)->where('id', $id)->delete();
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ use Hyperf\Database\Model\Events\Deleted;
|
||||
use Hyperf\Database\Model\Events\Saved;
|
||||
use Hyperf\DbConnection\Collector\TableCollector;
|
||||
use Hyperf\DbConnection\ConnectionResolver;
|
||||
use Hyperf\DbConnection\Db;
|
||||
use Hyperf\DbConnection\Frequency;
|
||||
use Hyperf\DbConnection\Pool\DbPool;
|
||||
use Hyperf\DbConnection\Pool\PoolFactory;
|
||||
@ -42,6 +43,7 @@ use Hyperf\Redis\Pool\RedisPool;
|
||||
use Hyperf\Redis\RedisProxy;
|
||||
use Hyperf\Utils\ApplicationContext;
|
||||
use Hyperf\Utils\Packer\PhpSerializerPacker;
|
||||
use Hyperf\Utils\Waiter;
|
||||
use Mockery;
|
||||
use Psr\EventDispatcher\EventDispatcherInterface;
|
||||
use Psr\Log\LogLevel;
|
||||
@ -168,6 +170,8 @@ class ContainerStub
|
||||
$container->shouldReceive('get')->with(Manager::class)->andReturn(new Manager($container));
|
||||
$container->shouldReceive('get')->with(PhpSerializerPacker::class)->andReturn(new PhpSerializerPacker());
|
||||
$container->shouldReceive('get')->with(EagerLoader::class)->andReturn(new EagerLoader());
|
||||
$container->shouldReceive('get')->with(Waiter::class)->andReturn(new Waiter());
|
||||
$container->shouldReceive('get')->with(Db::class)->andReturn(new Db($container));
|
||||
return $container;
|
||||
}
|
||||
}
|
||||
|
@ -127,7 +127,11 @@ class SwowServer implements ServerInterface
|
||||
$handler->initCoreMiddleware($name);
|
||||
}
|
||||
if ($server instanceof HttpServer) {
|
||||
$server->handle([$handler, $method]);
|
||||
$server->handle(static function ($request, $session) use ($handler, $method) {
|
||||
wait(static function () use ($request, $session, $handler, $method) {
|
||||
$handler->{$method}($request, $session);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
@ -302,7 +302,7 @@ class Server implements MiddlewareInitializerInterface, OnHandShakeInterface, On
|
||||
};
|
||||
|
||||
if ($server instanceof SwooleResponse) {
|
||||
$onOpen();
|
||||
wait($onOpen);
|
||||
} else {
|
||||
defer($onOpen);
|
||||
}
|
||||
|
61
src/websocket-server/tests/ServerTest.php
Normal file
61
src/websocket-server/tests/ServerTest.php
Normal file
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace HyperfTest\WebSocketServer;
|
||||
|
||||
use Hyperf\Contract\StdoutLoggerInterface;
|
||||
use Hyperf\Dispatcher\HttpDispatcher;
|
||||
use Hyperf\ExceptionHandler\ExceptionHandlerDispatcher;
|
||||
use Hyperf\HttpServer\ResponseEmitter;
|
||||
use Hyperf\Utils\ApplicationContext;
|
||||
use Hyperf\Utils\Coroutine;
|
||||
use Hyperf\Utils\Reflection\ClassInvoker;
|
||||
use Hyperf\Utils\Waiter;
|
||||
use Hyperf\WebSocketServer\Server;
|
||||
use HyperfTest\WebSocketServer\Stub\WebSocketStub;
|
||||
use Mockery;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Swoole\Http\Request as SwooleRequest;
|
||||
use Swoole\Http\Response as SwooleResponse;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @coversNothing
|
||||
*/
|
||||
class ServerTest extends TestCase
|
||||
{
|
||||
protected function tearDown(): void
|
||||
{
|
||||
Mockery::close();
|
||||
}
|
||||
|
||||
public function testDeferOnOpenInCoroutineStyleServer()
|
||||
{
|
||||
$container = Mockery::mock(ContainerInterface::class);
|
||||
ApplicationContext::setContainer($container);
|
||||
$container->shouldReceive('get')->with(WebSocketStub::class)->andReturn(new WebSocketStub());
|
||||
$container->shouldReceive('get')->with(Waiter::class)->andReturn(new Waiter());
|
||||
|
||||
$server = new Server(
|
||||
$container,
|
||||
Mockery::mock(HttpDispatcher::class),
|
||||
Mockery::mock(ExceptionHandlerDispatcher::class),
|
||||
Mockery::mock(ResponseEmitter::class),
|
||||
Mockery::mock(StdoutLoggerInterface::class),
|
||||
);
|
||||
|
||||
$server = new ClassInvoker($server);
|
||||
$server->deferOnOpen(new SwooleRequest(), WebSocketStub::class, new SwooleResponse());
|
||||
$this->assertNotEquals(Coroutine::id(), WebSocketStub::$coroutineId);
|
||||
$this->assertFalse(\Swoole\Coroutine::exists(WebSocketStub::$coroutineId));
|
||||
}
|
||||
}
|
26
src/websocket-server/tests/Stub/WebSocketStub.php
Normal file
26
src/websocket-server/tests/Stub/WebSocketStub.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://hyperf.wiki
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace HyperfTest\WebSocketServer\Stub;
|
||||
|
||||
use Hyperf\Contract\OnOpenInterface;
|
||||
use Hyperf\Utils\Coroutine;
|
||||
use Swoole\Http\Request;
|
||||
|
||||
class WebSocketStub implements OnOpenInterface
|
||||
{
|
||||
public static $coroutineId = 0;
|
||||
|
||||
public function onOpen($server, Request $request): void
|
||||
{
|
||||
static::$coroutineId = Coroutine::id();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user