Compare commits

...

38 Commits

Author SHA1 Message Date
as2252258 76351fbe66 eee 2026-06-24 20:11:12 +08:00
as2252258 8479106b9f eee 2026-06-12 23:57:25 +08:00
as2252258 ca8cc081bc Merge remote-tracking branch 'origin/master' 2026-04-17 14:11:05 +08:00
as2252258 a31c24ddf3 eee 2026-04-17 14:10:48 +08:00
as2252258 826503f4e6 add println function
Signed-off-by: 向林 <as2252258@163.com>
2026-01-08 08:26:08 +00:00
as2252258 eeb348c053 eee 2026-01-02 04:51:16 +08:00
as2252258 168954e4c4 update composer.json.
xx

Signed-off-by: 向林 <as2252258@163.com>
2025-12-31 06:59:26 +00:00
as2252258 6a27fa3b74 eee 2025-12-31 01:50:09 +08:00
as2252258 79d4f47a67 eee 2025-12-31 01:16:00 +08:00
as2252258 e6786666b7 eee 2025-12-31 00:50:04 +08:00
as2252258 b5c18fc074 eee 2025-12-31 00:43:25 +08:00
as2252258 86b9c46755 eee 2025-12-31 00:40:05 +08:00
as2252258 baea90e9e5 eee 2025-12-31 00:19:31 +08:00
as2252258 87e7535f27 eee 2025-12-23 20:24:00 +08:00
as2252258 cc073f13c2 update composer.json.
xxx

Signed-off-by: 向林 <as2252258@163.com>
2025-12-23 02:26:34 +00:00
as2252258 3afb1bd514 eee 2025-12-22 23:42:04 +08:00
as2252258 0e7d429bfc Merge remote-tracking branch 'origin/master' 2025-12-22 23:06:51 +08:00
as2252258 526aa9a63d eee 2025-12-22 23:06:36 +08:00
as2252258 48db719890 !1 Add README.md
Merge pull request !1 from gitee-agent/N/A
2025-12-22 14:31:18 +00:00
gitee-bot daa8311eb9 Add README.md 2025-12-22 13:38:31 +00:00
as2252258 a065e5da49 eee 2025-12-19 17:09:36 +08:00
as2252258 8ae2af7dd6 eee 2025-12-18 23:29:55 +08:00
as2252258 6f0376ac44 eee 2025-12-18 22:56:20 +08:00
as2252258 08a4d6af4e eee 2025-12-18 22:56:08 +08:00
as2252258 9899578d52 eee 2025-12-18 22:53:28 +08:00
as2252258 f97df5cfe5 eee 2025-12-18 22:35:21 +08:00
as2252258 34f8f6f523 eee 2025-12-18 21:30:00 +08:00
as2252258 f6f94aff32 eee 2025-12-18 15:39:47 +08:00
as2252258 377a9c17c3 eee 2025-12-18 15:03:43 +08:00
as2252258 174d2f1659 eee 2025-12-16 20:20:09 +08:00
as2252258 d6c8380c64 eee 2025-12-01 06:39:05 +08:00
as2252258 2e54326aba eee 2025-07-16 09:17:03 +08:00
as2252258 59632ac4a3 eee 2025-07-16 09:09:56 +08:00
as2252258 da5a6a6b83 eee 2025-07-14 18:12:17 +08:00
as2252258 d758d21f08 eee 2025-07-11 17:44:34 +08:00
as2252258 c59212da78 eee 2025-07-11 17:32:17 +08:00
as2252258 9ce0cb96bf eee 2025-07-11 16:27:14 +08:00
as2252258 c7b5d5fb59 eee 2025-01-18 20:45:37 +08:00
23 changed files with 1871 additions and 1197 deletions
+1
View File
@@ -34,3 +34,4 @@ runtime/
oot oot
d d
composer.lock composer.lock
.gstack/
+2 -68
View File
@@ -37,13 +37,6 @@ class Kiri
} }
/**
* @return Container|null
*/
public static function getContainerContext(): ?Container
{
return static::getContainer();
}
/** /**
@@ -89,7 +82,7 @@ class Kiri
if (Kiri::getPlatform()->isMac()) { if (Kiri::getPlatform()->isMac()) {
return; return;
} }
$name = '[' . \config('id', 'system-service') . ']'; $name = '[' . \config('site.id', 'system-service') . ']';
if (!empty($prefix)) { if (!empty($prefix)) {
$name .= '.' . $prefix; $name .= '.' . $prefix;
} }
@@ -104,7 +97,7 @@ class Kiri
public static function getStoragePath(): string public static function getStoragePath(): string
{ {
$default = APP_PATH . 'storage' . DIRECTORY_SEPARATOR; $default = APP_PATH . 'storage' . DIRECTORY_SEPARATOR;
$path = \config('storage', $default); $path = \config('site.log.path', $default);
if (!is_dir($path)) { if (!is_dir($path)) {
mkdir($path, 0777, true); mkdir($path, 0777, true);
} }
@@ -131,17 +124,6 @@ class Kiri
} }
/**
* @return bool
*/
public static function isDocker(): bool
{
$output = shell_exec('[ -f /.dockerenv ] && echo yes || echo no');
if (trim($output) === 'yes') {
return true;
}
return false;
}
/** /**
@@ -177,54 +159,6 @@ class Kiri
} }
/**
* @return mixed
*/
public static function localhost(): mixed
{
return current(swoole_get_local_ip());
}
/**
* @param array $v1
* @param array $v2
* @return float
*/
#[Pure] public static function distance(array $v1, array $v2): float
{
$maxX = max($v1['x'], $v2['x']);
$minX = min($v1['x'], $v2['x']);
$maxZ = max($v1['z'], $v2['z']);
$minZ = min($v1['z'], $v2['z']);
$dx = abs($maxX - $minX);
$dy = abs($maxZ - $minZ);
$sqrt = sqrt($dx * $dx + $dy * $dy);
if ($sqrt < 0) {
$sqrt = abs($sqrt);
}
return (float)$sqrt;
}
/**
* @param $tmp_name
* @return string
*/
public static function rename($tmp_name): string
{
$hash = md5_file($tmp_name);
$later = '.' . exif_imagetype($tmp_name);
$match = '/(\w{12})(\w{5})(\w{9})(\w{6})/';
$tmp = preg_replace($match, '$1-$2-$3-$4', $hash);
return strtoupper($tmp) . $later;
}
/** /**
+135
View File
@@ -0,0 +1,135 @@
# Kiri Core Framework Documentation
## Project Introduction
Kiri is a high-performance PHP-based core framework designed to provide developers with a simple and efficient development experience. The framework includes a variety of practical utility classes, exception handling mechanisms, configuration management, and a dependency injection container, making it suitable for building various types of applications.
### Key Features
- **Dependency Injection Container**: Provides powerful dependency management via `Kiri\Di\Container`.
- **Configuration Management**: Supports reading configuration from files and environment variables.
- **Exception Handling**: Offers a unified exception handling interface with support for registering custom exception handlers.
- **Logging**: Built-in `StdoutLogger` supporting multiple log levels.
- **Utility Classes**:
- `Str`: String operations such as encryption and random string generation.
- `Json`: JSON encoding/decoding and response construction.
- `Help`: Auxiliary functions including XML conversion, random number generation, and email sending.
- `DateFormat`: Date and time formatting tools.
- **Networking**: Supports local IP retrieval and Socket programming.
- **NoSQL Support**: Provides client wrappers for Redis and MongoDB with connection pool management.
## Installation
### System Requirements
- PHP 7.4 or higher
- Composer (for dependency management)
### Installation Steps
1. Ensure Composer is installed.
2. Run the following command to install dependencies:
```bash
composer install
```
## Usage Guide
### Initialize the Framework
```php
use Kiri\Kiri;
use Kiri\Application;
// Initialize the container
Kiri::setContainer(new Container());
// Create an application instance
$app = new Application(
new EventProvider(),
new ConfigProvider(),
Kiri::getContainer()
);
// Initialize the application
$app->init();
```
### Configuration Management
Configuration files can be loaded and accessed via the `ConfigProvider` class:
```php
$config = new ConfigProvider();
$databaseHost = $config->get('database.host');
```
### Dependency Injection
Use the container to inject dependencies:
```php
$service = Kiri::getContainer()->get(MyService::class);
```
### Logging
Use the built-in logger to output messages:
```php
Kiri::getLogger()->info('This is an info message.');
```
### Exception Handling
Register a custom exception handler:
```php
$errorHandler = new ErrorHandler();
$errorHandler->registerExceptionHandler(function (Throwable $e) {
echo "Unhandled exception: " . $e->getMessage();
});
```
### Database Connections
#### Redis
```php
$redis = new Redis();
$redis->connect();
$redis->set('key', 'value');
echo $redis->get('key');
```
#### MongoDB
```php
$mongo = new MongoDB();
$collection = $mongo->getCollection('users');
$result = $collection->find([]);
```
### Utility Class Examples
#### String Operations
```php
echo Str::rand(10); // Generate a random string
```
#### JSON Response
```php
echo Json::jsonSuccess(['data' => 'example'], 'Operation successful');
```
#### Date Formatting
```php
echo DateFormat::DaySecond(); // Get the number of seconds in a day
```
## Contribution Guidelines
Contributions are welcome! Please follow these steps:
1. Fork the project repository.
2. Create a new branch (`git checkout -b feature/new-feature`)
3. Commit your changes (`git commit -am 'Add new feature'`)
4. Push to the branch (`git push origin feature/new-feature`)
5. Create a Pull Request
## License
This project is licensed under the MIT License. For details, see the [LICENSE](LICENSE) file.
## Contact
If you have any questions or suggestions, please open an Issue or contact the project maintainers.
---
Thank you for choosing Kiri Core Framework! We look forward to your feedback and contributions.
+133
View File
@@ -0,0 +1,133 @@
# Kiri 核心框架文档
## 项目介绍
Kiri 是一个基于 PHP 的高性能核心框架,旨在为开发者提供简洁、高效的开发体验。该框架内置了多种实用工具类、异常处理机制、配置管理、容器依赖注入等功能,适用于构建各种类型的应用程序。
### 主要特性
- **依赖注入容器**:通过 `Kiri\Di\Container` 提供强大的依赖管理功能。
- **配置管理**:支持从文件和环境变量中读取配置。
- **异常处理**:提供统一的异常处理接口,支持注册自定义异常处理器。
- **日志记录**:内置 `StdoutLogger` 支持多种日志级别输出。
- **实用工具类**
- `Str`:字符串操作,如加密、随机字符串生成等。
- `Json`JSON 编码/解码及响应构造。
- `Help`:提供 XML 转换、随机数生成、邮件发送等辅助功能。
- `DateFormat`:日期和时间格式化工具。
- **网络功能**:支持本地 IP 获取、Socket 编程。
- **NoSQL 支持**:提供 Redis 和 MongoDB 的客户端封装,支持连接池管理。
## 安装
### 系统要求
- PHP 7.4 或更高版本
- Composer(用于依赖管理)
### 安装步骤
1. 确保已安装 Composer。
2. 执行以下命令安装依赖:
```bash
composer install
```
## 使用说明
### 初始化框架
```php
use Kiri\Kiri;
use Kiri\Application;
// 初始化容器
Kiri::setContainer(new Container());
// 创建应用实例
$app = new Application(
new EventProvider(),
new ConfigProvider(),
Kiri::getContainer()
);
// 初始化应用
$app->init();
```
### 配置管理
配置文件可通过 `ConfigProvider` 类进行加载和访问:
```php
$config = new ConfigProvider();
$databaseHost = $config->get('database.host');
```
### 依赖注入
使用容器进行依赖注入:
```php
$service = Kiri::getContainer()->get(MyService::class);
```
### 日志记录
使用内置日志记录器输出信息:
```php
Kiri::getLogger()->info('This is an info message.');
```
### 异常处理
注册自定义异常处理器:
```php
$errorHandler = new ErrorHandler();
$errorHandler->registerExceptionHandler(function (Throwable $e) {
echo "Unhandled exception: " . $e->getMessage();
});
```
### 数据库连接
#### Redis
```php
$redis = new Redis();
$redis->connect();
$redis->set('key', 'value');
echo $redis->get('key');
```
#### MongoDB
```php
$mongo = new MongoDB();
$collection = $mongo->getCollection('users');
$result = $collection->find([]);
```
### 工具类使用示例
#### 字符串处理
```php
echo Str::rand(10); // 生成随机字符串
```
#### JSON 响应
```php
echo Json::jsonSuccess(['data' => 'example'], 'Operation successful');
```
#### 日期格式化
```php
echo DateFormat::DaySecond(); // 获取一天的秒数
```
## 贡献指南
欢迎贡献代码!请遵循以下步骤:
1. Fork 项目仓库。
2. 创建新分支 (`git checkout -b feature/new-feature`)
3. 提交更改 (`git commit -am 'Add new feature'`)
4. 推送分支 (`git push origin feature/new-feature`)
5. 创建 Pull Request
## 许可证
该项目采用 MIT 许可证。详细信息请参阅 [LICENSE](LICENSE) 文件。
## 联系方式
如有问题或建议,请提交 Issue 或联系项目维护者。
---
感谢您选择 Kiri 核心框架!我们期待您的反馈与贡献。
+56 -59
View File
@@ -1,59 +1,56 @@
{ {
"name": "game-worker/kiri-core", "name": "game-worker/kiri-core",
"description": "test framework", "description": "test framework",
"authors": [ "authors": [
{ {
"name": "XiangLin", "name": "XiangLin",
"email": "as2252258@163.com" "email": "as2252258@163.com"
} }
], ],
"license": "MIT", "license": "MIT",
"require": { "require": {
"php": ">=8.3", "php": ">=8.5",
"ext-json": "*", "ext-json": "*",
"ext-fileinfo": "*", "ext-fileinfo": "*",
"ext-pdo": "*", "ext-pdo": "*",
"ext-redis": "*", "ext-redis": "*",
"ext-simplexml": "*", "ext-simplexml": "*",
"ext-libxml": "*", "ext-libxml": "*",
"ext-iconv": "*", "ext-iconv": "*",
"ext-mbstring": "*", "ext-mbstring": "*",
"ext-xml": "*", "ext-xml": "*",
"ext-curl": "*", "ext-curl": "*",
"ext-openssl": "*", "ext-openssl": "*",
"ext-swoole": "*", "ext-swoole": "*",
"ext-msgpack": "*", "ext-msgpack": "*",
"symfony/console": "~v5.3.10", "symfony/console": "^v8.0",
"psr/log": "1.*", "psr/log": "1.*",
"composer-runtime-api": "^2.0", "composer-runtime-api": "^2.0",
"psr/http-server-middleware": "1.0.1", "psr/http-server-middleware": "^1.0.2",
"ext-pcntl": "*", "ext-pcntl": "*",
"ext-sockets": "*", "ext-sockets": "*",
"nikic/php-parser": "^4.15", "nikic/php-parser": "^v5.5.0",
"ext-inotify": "*", "ext-inotify": "*",
"game-worker/kiri-pool": "~v1.0", "game-worker/kiri-pool": "^v1.0",
"monolog/monolog": "^2.9", "psr/container": "^2.0",
"psr/container": "^2.0", "swiftmailer/swiftmailer": "^v6.3.0"
"ext-libsodium": "*", },
"swiftmailer/swiftmailer": "^6.3" "replace": {
}, "symfony/polyfill-apcu": "*",
"replace": { "symfony/polyfill-php80": "*",
"symfony/polyfill-apcu": "*", "symfony/polyfill-mbstring": "*",
"symfony/polyfill-php80": "*", "symfony/polyfill-ctype": "*",
"symfony/polyfill-mbstring": "*", "symfony/polyfill-php73": "*",
"symfony/polyfill-ctype": "*", "symfony/polyfill-php72": "*",
"symfony/polyfill-php73": "*", "symfony/polyfill-php81": "*"
"symfony/polyfill-php72": "*", },
"symfony/polyfill-php81": "*" "autoload": {
}, "psr-4": {
"autoload": { "Kiri\\": "kiri-engine/"
"psr-4": { },
"Kiri\\": "kiri-engine/", "files": [
"Kiri\\Actor\\": "kiri-actor/" "Kiri.php",
}, "function.php"
"files": [ ]
"Kiri.php", }
"function.php" }
]
}
}
+778 -731
View File
File diff suppressed because it is too large Load Diff
+12 -4
View File
@@ -46,13 +46,21 @@ abstract class BaseApplication extends LocalService
public function __construct(public EventProvider $provider, public ConfigProvider $config, public ContainerInterface $container) public function __construct(public EventProvider $provider, public ConfigProvider $config, public ContainerInterface $container)
{ {
$this->mapping($config); $this->mapping($config);
$this->parseStorage($config);
$this->parseEvents($config);
parent::__construct(); parent::__construct();
} }
/**
* @return void
* @throws
*/
public function init(): void
{
$this->parseStorage($this->config);
$this->parseEvents($this->config);
}
/** /**
* @param ConfigProvider $config * @param ConfigProvider $config
* @return void * @return void
@@ -73,7 +81,7 @@ abstract class BaseApplication extends LocalService
*/ */
public function parseStorage(ConfigProvider $config): void public function parseStorage(ConfigProvider $config): void
{ {
$storage = $config->get('storage', 'storage'); $storage = $config->get('site.log.storage', 'storage');
if (!str_contains($storage, APP_PATH)) { if (!str_contains($storage, APP_PATH)) {
$storage = APP_PATH . $storage . '/'; $storage = APP_PATH . $storage . '/';
} }
+65 -129
View File
@@ -1,129 +1,65 @@
<?php <?php
/** declare(strict_types=1);
* Created by PhpStorm.
* User: whwyy namespace Kiri\Abstracts;
* Date: 2018/3/30 0030
* Time: 14:28 use Exception;
*/ use JetBrains\PhpStorm\Pure;
declare(strict_types=1); use Kiri;
use Kiri\Error\StdoutLogger;
namespace Kiri\Abstracts; use Kiri\Events\EventDispatch;
use Kiri\Events\EventProvider;
use Psr\Container\ContainerInterface;
use Exception;
use JetBrains\PhpStorm\Pure; class Component
use Kiri; {
use Kiri\Error\StdoutLogger;
use Kiri\Events\EventDispatch; public function __construct()
use Kiri\Events\EventProvider; {
use Psr\Container\ContainerInterface; }
/** public function init(): void
* Class Component {
* @package Kiri\Base }
* @property ContainerInterface $container
* @property EventDispatch $dispatch #[Pure] public static function className(): string
* @property EventProvider $provider {
*/ return static::class;
class Component implements Configure }
{
/**
* @throws
/** */
* BaseAbstract constructor. public function getLogger(): StdoutLogger
*/ {
public function __construct() return Kiri::getLogger();
{ }
}
public function getDispatch(): EventDispatch
{
/** return Kiri::getDi()->get(EventDispatch::class);
* @return void }
*/
public function init(): void public function getProvider(): EventProvider
{ {
} return Kiri::getDi()->get(EventProvider::class);
}
/** public function getContainer(): ContainerInterface
* @return string {
*/ return Kiri::getDi();
#[Pure] public static function className(): string }
{
return static::class; /**
} * @throws
*/
public function __get(string $name)
/** {
* @return StdoutLogger $method = 'get' . ucfirst($name);
* @throws if (method_exists($this, $method)) {
*/ return $this->{$method}();
public function getLogger(): StdoutLogger }
{ throw new Exception('Unable getting property ' . get_called_class() . '::' . $name);
return Kiri::getLogger(); }
}
}
/**
* @param string $name
* @return mixed
* @throws
*/
public function __get(string $name)
{
$method = 'get' . ucfirst($name);
if (method_exists($this, $method)) {
return $this->{$method}();
} else if (method_exists($this, $name)) {
return $this->{$name};
} else {
throw new Exception('Unable getting property ' . get_called_class() . '::' . $name);
}
}
/**
* @param string $name
* @param $value
* @return void
* @throws
*/
public function __set(string $name, $value): void
{
$method = 'set' . ucfirst($name);
if (method_exists($this, $method)) {
$this->{$method}($value);
} else if (method_exists($this, $name)) {
$this->{$name} = $value;
} else {
throw new Exception('Unable setting property ' . get_called_class() . '::' . $name);
}
}
/**
* @return EventDispatch
*/
public function getDispatch(): EventDispatch
{
return Kiri::getDi()->get(EventDispatch::class);
}
/**
* @return EventProvider
*/
public function getProvider(): EventProvider
{
return Kiri::getDi()->get(EventProvider::class);
}
/**
* @return ContainerInterface
*/
public function getContainer(): ContainerInterface
{
return Kiri::getDi();
}
}
-18
View File
@@ -1,18 +0,0 @@
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2018/3/30 0030
* Time: 14:11
*/
declare(strict_types=1);
namespace Kiri\Abstracts;
/**
* Interface Configure
* @package Kiri\Base
*/
interface Configure
{
}
+4 -6
View File
@@ -7,9 +7,7 @@ use Kiri\Coordinator;
class CoordinatorManager class CoordinatorManager
{ {
private static array $_items = [];
private static array $_waite = [];
/** /**
@@ -18,10 +16,10 @@ class CoordinatorManager
*/ */
public static function utility(string $category): Coordinator public static function utility(string $category): Coordinator
{ {
if (!((static::$_waite[$category] ?? null) instanceof Coordinator)) { if (!((static::$_items[$category] ?? null) instanceof Coordinator)) {
static::$_waite[$category] = new Coordinator(); static::$_items[$category] = new Coordinator();
} }
return static::$_waite[$category]; return static::$_items[$category];
} }
} }
+15 -15
View File
@@ -1,15 +1,15 @@
<?php <?php
namespace Kiri\Abstracts; namespace Kiri\Abstracts;
interface Kernel interface Kernel
{ {
/** /**
* @return array * @return array
*/ */
public function getCommands(): array; public function getCommands(): array;
} }
+12 -12
View File
@@ -1,12 +1,12 @@
<?php <?php
declare(strict_types=1); declare(strict_types=1);
namespace Kiri\Abstracts; namespace Kiri\Abstracts;
interface Provider interface Provider
{ {
public function onImport(); public function onImport();
} }
+14 -14
View File
@@ -1,14 +1,14 @@
<?php <?php
declare(strict_types=1); declare(strict_types=1);
namespace Kiri\Abstracts; namespace Kiri\Abstracts;
/** /**
* Class Providers * Class Providers
* @package Kiri\Abstracts * @package Kiri\Abstracts
*/ */
abstract class Providers extends Component implements Provider abstract class Providers extends Component implements Provider
{ {
} }
+13 -12
View File
@@ -54,12 +54,15 @@ class Application extends BaseApplication
*/ */
public function init(): void public function init(): void
{ {
$this->errorHandler->registerShutdownHandler(config('error.shutdown', [])); $this->errorHandler->registerShutdownHandler(config('site.error.shutdown', []));
$this->errorHandler->registerExceptionHandler(config('error.exception', [])); $this->errorHandler->registerExceptionHandler(config('site.error.exception', []));
$this->errorHandler->registerErrorHandler(config('error.error', [])); $this->errorHandler->registerErrorHandler(config('site.error.error', []));
$this->id = config('id', uniqid('id.'));
$this->id = config('site.id', uniqid('id.'));
$this->provider->on(OnBeforeCommandExecute::class, [$this, 'beforeCommandExecute']); $this->provider->on(OnBeforeCommandExecute::class, [$this, 'beforeCommandExecute']);
parent::init();
} }
@@ -70,13 +73,11 @@ class Application extends BaseApplication
*/ */
public function beforeCommandExecute(OnBeforeCommandExecute $beforeCommandExecute): void public function beforeCommandExecute(OnBeforeCommandExecute $beforeCommandExecute): void
{ {
if (!($beforeCommandExecute->command instanceof ServerCommand)) { if ($beforeCommandExecute->command instanceof ServerCommand) {
$scanner = $this->container->get(Scanner::class); return;
$scanner->load_directory(APP_PATH . 'app/'); }
} else if (config('reload.hot', false) === false) { $scanner = $this->container->get(Scanner::class);
$scanner = $this->container->get(Scanner::class); $scanner->scan(APP_PATH . 'app/');
$scanner->load_directory(APP_PATH . 'app/');
}
} }
@@ -124,7 +125,7 @@ class Application extends BaseApplication
{ {
$console = $this->container->get(ConsoleApplication::class); $console = $this->container->get(ConsoleApplication::class);
foreach ($command as $value) { foreach ($command as $value) {
$console->add($this->container->get($value)); $console->addCommand($this->container->get($value));
} }
} }
+19 -9
View File
@@ -1,15 +1,19 @@
<?php <?php
declare(strict_types=1); declare(strict_types=1);
namespace Kiri; namespace Kiri;
use Swoole\Coroutine;
use Swoole\Coroutine\Channel;
class Coordinator class Coordinator
{ {
const string WORKER_START = 'worker:start'; const string WORKER_START = 'worker:start';
private bool $waite = true; private bool $wait = true;
private ?Channel $channel = null;
/** /**
@@ -17,18 +21,24 @@ class Coordinator
*/ */
public function yield(): void public function yield(): void
{ {
while ($this->waite) { if (Coroutine::getCid() > 0) {
usleep(1000); $this->channel = new Channel(1);
} $this->channel->pop();
} else {
while ($this->wait) {
usleep(1000);
}
}
} }
/** /**
* @return void * @return void
*/ */
public function waite(): void public function wait(): void
{ {
$this->waite = true; $this->wait = true;
$this->channel = null;
} }
@@ -37,8 +47,8 @@ class Coordinator
*/ */
public function done(): void public function done(): void
{ {
$this->waite = false; $this->wait = false;
$this->channel?->push(true);
} }
} }
+1 -1
View File
@@ -185,7 +185,7 @@ class Str
* @return array * @return array
* 剩余天,带分秒 * 剩余天,带分秒
*/ */
public static function timeout($endTime, int $startTime = NULL): array public static function timeout($endTime, ?int $startTime = NULL): array
{ {
$endTime = $endTime - (!empty($startTime) ? $startTime : time()); $endTime = $endTime - (!empty($startTime) ? $startTime : time());
+4 -13
View File
@@ -22,14 +22,9 @@ class Environmental
*/ */
public function isMac(): bool public function isMac(): bool
{ {
$output = strtolower(PHP_OS | PHP_OS_FAMILY); $os = strtolower(PHP_OS);
if (str_contains('mac', $output)) {
return true; return str_contains($os, 'mac') || str_contains($os, 'darwin');
} else if (str_contains('darwin', $output)) {
return true;
} else {
return false;
}
} }
@@ -38,11 +33,7 @@ class Environmental
*/ */
#[Pure] public function isLinux(): bool #[Pure] public function isLinux(): bool
{ {
if (!static::isMac()) { return PHP_OS_FAMILY === 'Linux' || strtolower(PHP_OS) === 'linux';
return true;
} else {
return false;
}
} }
} }
+6 -7
View File
@@ -11,17 +11,12 @@ namespace Kiri\Error;
use Closure; use Closure;
use ErrorException; use ErrorException;
use Exception;
use Kiri\Abstracts\Component; use Kiri\Abstracts\Component;
use Psr\Container\ContainerInterface;
use Kiri\Di\Inject\Container;
use ReflectionException;
use Kiri\Events\OnSystemError; use Kiri\Events\OnSystemError;
use Throwable; use Throwable;
/** /**
* Class ErrorHandler * Class ErrorHandler
* hahahah
* @package Kiri\Base * @package Kiri\Base
* @property-read $asError * @property-read $asError
*/ */
@@ -94,7 +89,7 @@ class ErrorHandler extends Component implements ErrorInterface
return; return;
} }
$this->getLogger()->failure($lastError['message'] . PHP_EOL); $this->getLogger()->println(json_encode($lastError,JSON_UNESCAPED_UNICODE));
event(new OnSystemError()); event(new OnSystemError());
} }
@@ -109,7 +104,9 @@ class ErrorHandler extends Component implements ErrorInterface
{ {
$this->category = 'exception'; $this->category = 'exception';
$this->getLogger()->failure($exception); $this->getLogger()->println(throwable($exception));
json_log($exception);
event(new OnSystemError()); event(new OnSystemError());
} }
@@ -122,6 +119,8 @@ class ErrorHandler extends Component implements ErrorInterface
{ {
$error = func_get_args(); $error = func_get_args();
$this->getLogger()->println(json_encode($error,JSON_UNESCAPED_UNICODE));
event(new OnSystemError()); event(new OnSystemError());
throw new ErrorException($error[1], $error[0], 1, $error[2], $error[3]); throw new ErrorException($error[1], $error[0], 1, $error[2], $error[3]);
+23 -21
View File
@@ -9,7 +9,7 @@ use Monolog\Formatter\LineFormatter;
use Monolog\Handler\RotatingFileHandler; use Monolog\Handler\RotatingFileHandler;
use Monolog\Logger; use Monolog\Logger;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use ReflectionException; use Throwable;
/** /**
@@ -49,7 +49,7 @@ class StdoutLogger extends Component
{ {
parent::__construct(); parent::__construct();
$this->logger = new Logger(\config('id')); $this->logger = new Logger(\config('site.id'));
$this->levels = [ $this->levels = [
'debug' => $this->logger::DEBUG, 'debug' => $this->logger::DEBUG,
'info' => $this->logger::INFO, 'info' => $this->logger::INFO,
@@ -68,31 +68,32 @@ class StdoutLogger extends Component
* @param string $model * @param string $model
* @return bool * @return bool
*/ */
public function failure($message, string $model = 'app'): bool public function logCategory($message, string $model = 'app'): bool
{ {
if ($message instanceof \Exception) { if ($message instanceof \Exception) {
$this->errors[$model] = $message->getMessage(); $this->errors[$model] = $message->getMessage();
} else { } else {
$this->errors[$model] = $message; $this->errors[$model] = $message;
} }
return $this->dump($message); $this->println($message);
return false;
} }
/** /**
* @param $message * @param Throwable $exception
* @return bool * @param array $data
*/ * @param mixed|null $result
protected function dump($message): bool * @return bool
{ */
$message = throwable($message); public function json_log(Throwable $exception, array $data = [], mixed $result = null): mixed
if (str_contains($message, 'inotify_rm_watch')) { {
return false; json_log($exception, $data);
}
file_put_contents('php://output', '[' . date('Y-m-d H:i:s') . '] ' . $message, FILE_APPEND); $this->println($exception->getMessage());
$this->error($message, []);
return false; return $result;
} }
/** /**
@@ -119,9 +120,10 @@ class StdoutLogger extends Component
} else if (method_exists($this, $name)) { } else if (method_exists($this, $name)) {
$this->{$name}(...$arguments); $this->{$name}(...$arguments);
} }
} catch (\Throwable $exception) { } catch (Throwable $exception) {
file_put_contents('php://output', '[' . date('Y-m-d H:i:s') . '] ' . $exception->getMessage(), FILE_APPEND); $this->println($exception->getMessage());
} $this->json_log($exception);
}
} }
+417
View File
@@ -0,0 +1,417 @@
<?php
/**
* Created by PhpStorm.
* User: whwyy
* Date: 2024/12/19
* Time: 14:00
*/
declare(strict_types=1);
namespace Kiri\NoSql;
use Kiri;
use Kiri\Exception\RedisConnectException;
use Kiri\Pool\Pool;
use MongoDB\Client;
use MongoDB\Database;
use MongoDB\Collection;
use function config;
/**
* Class MongoDB
* @package Kiri\NoSql
* @mixin Client
* @mixin Database
* @mixin Collection
*/
class MongoDB
{
public string $host = 'localhost';
public int $port = 27017;
public string $database = '';
public string $username = '';
public string $password = '';
public string $authSource = 'admin';
public int $timeout = 30;
public array $options = [];
/**
* @var array|int[]
*/
public array $pool = ['min' => 1, 'max' => 100];
/**
* 初始化
*/
public function __construct()
{
Kiri::configure($this, config('mongodb', []));
}
/**
* @return void
* @throws
*/
public function init(): void
{
}
/**
* @param $name
* @param $arguments
* @return mixed
* @throws
*/
public function __call($name, $arguments): mixed
{
if (method_exists($this, $name)) {
return $this->{$name}(...$arguments);
} else {
return $this->proxy($name, $arguments);
}
}
/**
* 获取数据库实例
* @param string|null $database
* @return Database
* @throws
*/
public function getDatabase(?string $database = null): Database
{
$dbName = $database ?? $this->database;
if (empty($dbName)) {
throw new RedisConnectException('MongoDB database name is required.');
}
return $this->getClient()->selectDatabase($dbName);
}
/**
* 获取集合实例
* @param string $collection
* @param string|null $database
* @return Collection
* @throws
*/
public function getCollection(string $collection, ?string $database = null): Collection
{
return $this->getDatabase($database)->selectCollection($collection);
}
/**
* 代理方法调用到 MongoDB Client,内置连接健康检查和回收
* 异常时关闭连接并回退计数器,防止断连对象污染连接池
* @param $name
* @param $arguments
* @return mixed
* @throws
*/
public function proxy($name, $arguments): mixed
{
$client = $this->getClient();
try {
// 如果方法存在于 Client,直接调用
if (method_exists($client, $name)) {
return $client->{$name}(...$arguments);
}
// 如果方法存在于 Database,通过默认数据库调用
$database = $this->getDatabase();
if (method_exists($database, $name)) {
$result = $database->{$name}(...$arguments);
$this->returnClient($client);
return $result;
}
throw new \BadMethodCallException("Method {$name} does not exist on MongoDB Client or Database.");
} catch (\Throwable $throwable) {
\Kiri::getLogger()->json_log($throwable);
$this->closeClient($client);
return false;
}
$this->returnClient($client);
}
/**
* 归还连接
* @param Client $client
* @return void
*/
private function returnClient(Client $client): void
{
try {
$this->pool()->push($this->getName(), $client);
} catch (\Throwable) {
$this->closeClient($client);
}
}
/**
* 关闭连接并回退计数器
* @param Client $client
* @return void
*/
private function closeClient(Client $client): void
{
try {
$client->close();
} catch (\Throwable) {
}
$this->pool()->abandon($this->getName());
}
/**
* 执行 MongoDB 命令
* @param array|object $command
* @param array $options
* @param string|null $database
* @return array|object
* @throws
*/
public function command(array|object $command, array $options = [], ?string $database = null): array|object
{
$db = $this->getDatabase($database);
return $db->command($command, $options);
}
/**
* 插入文档
* @param string $collection
* @param array|object $document
* @param array $options
* @param string|null $database
* @return \MongoDB\InsertOneResult|\MongoDB\InsertManyResult
* @throws
*/
public function insert(string $collection, array|object $document, array $options = [], ?string $database = null)
{
$coll = $this->getCollection($collection, $database);
if (is_array($document) && isset($document[0]) && is_array($document[0])) {
// 批量插入
return $coll->insertMany($document, $options);
}
// 单条插入
return $coll->insertOne($document, $options);
}
/**
* 查找文档
* @param string $collection
* @param array $filter
* @param array $options
* @param string|null $database
* @return \MongoDB\Driver\Cursor
* @throws
*/
public function find(string $collection, array $filter = [], array $options = [], ?string $database = null)
{
$coll = $this->getCollection($collection, $database);
return $coll->find($filter, $options);
}
/**
* 查找单个文档
* @param string $collection
* @param array $filter
* @param array $options
* @param string|null $database
* @return array|object|null
* @throws
*/
public function findOne(string $collection, array $filter = [], array $options = [], ?string $database = null): array|object|null
{
$coll = $this->getCollection($collection, $database);
return $coll->findOne($filter, $options);
}
/**
* 更新文档
* @param string $collection
* @param array $filter
* @param array $update
* @param array $options
* @param string|null $database
* @return \MongoDB\UpdateResult
* @throws
*/
public function update(string $collection, array $filter, array $update, array $options = [], ?string $database = null)
{
$coll = $this->getCollection($collection, $database);
if (isset($options['multi']) && $options['multi']) {
unset($options['multi']);
return $coll->updateMany($filter, $update, $options);
}
return $coll->updateOne($filter, $update, $options);
}
/**
* 删除文档
* @param string $collection
* @param array $filter
* @param array $options
* @param string|null $database
* @return \MongoDB\DeleteResult
* @throws
*/
public function delete(string $collection, array $filter, array $options = [], ?string $database = null)
{
$coll = $this->getCollection($collection, $database);
if (isset($options['limit']) && $options['limit'] == 1) {
unset($options['limit']);
return $coll->deleteOne($filter, $options);
}
return $coll->deleteMany($filter, $options);
}
/**
* 统计文档数量
* @param string $collection
* @param array $filter
* @param array $options
* @param string|null $database
* @return int
* @throws
*/
public function count(string $collection, array $filter = [], array $options = [], ?string $database = null): int
{
$coll = $this->getCollection($collection, $database);
return $coll->countDocuments($filter, $options);
}
/**
* @return void
* @throws
*/
public function destroy(): void
{
$this->pool()->close($this->getName());
}
/**
* 获取 MongoDB 客户端
* @return Client
* @throws
*/
private function getClient(): Client
{
return $this->pool()->get($this->getName());
}
/**
* @return Pool
* @throws
*/
protected function pool(): Pool
{
$pool = Kiri::getPool();
if (!$pool->hasChannel($this->getName())) {
$pool->created($this->getName(), $this->pool['max'], [$this, 'connect']);
}
return $pool;
}
/**
* @return string
*/
private function getName(): string
{
return 'mongodb.' . $this->host . '.' . $this->database;
}
/**
* 创建 MongoDB 连接
* @return Client
* @throws
*/
protected function connect(): Client
{
$uri = $this->buildUri();
$clientOptions = $this->buildClientOptions();
try {
$client = new Client($uri, $clientOptions);
// 测试连接
$client->selectDatabase($this->database)->command(['ping' => 1]);
return $client;
} catch (\Throwable $e) {
\Kiri::getLogger()->json_log($e);
throw new RedisConnectException(sprintf('MongoDB Connect %s Fail: %s', $uri, $e->getMessage()));
}
}
/**
* 构建 MongoDB 连接 URI
* @return string
*/
private function buildUri(): string
{
$auth = '';
if (!empty($this->username) && !empty($this->password)) {
$auth = $this->username . ':' . urlencode($this->password) . '@';
}
// 支持多种 host 格式:host:port 或 host1,host2:port
$hosts = $this->host;
if (!str_contains($hosts, ',') && !str_contains($hosts, ':')) {
$hosts = $hosts . ':' . $this->port;
}
$uri = 'mongodb://' . $auth . $hosts;
// 添加数据库和认证源
$query = [];
if (!empty($this->database)) {
$query[] = 'database=' . $this->database;
}
if (!empty($this->authSource)) {
$query[] = 'authSource=' . $this->authSource;
}
if (!empty($query)) {
$uri .= '/?' . implode('&', $query);
}
return $uri;
}
/**
* 构建客户端选项
* @return array
*/
private function buildClientOptions(): array
{
return array_merge([
'connectTimeoutMS' => $this->timeout * 1000,
'serverSelectionTimeoutMS' => $this->timeout * 1000,
'socketTimeoutMS' => $this->timeout * 1000,
], $this->options);
}
}
@@ -7,18 +7,15 @@
*/ */
declare(strict_types=1); declare(strict_types=1);
namespace Kiri\Redis; namespace Kiri\NoSql;
use Exception;
use Kiri; use Kiri;
use Kiri\Exception\RedisConnectException; use Kiri\Exception\RedisConnectException;
use Kiri\Pool\Pool; use Kiri\Pool\Pool;
use RedisException;
use wchat\common\Result;
use function config; use function config;
/** /**
* Class Redis * Class NoSql
* @package Kiri\Cache * @package Kiri\Cache
* @mixin \Redis * @mixin \Redis
*/ */
@@ -106,13 +103,13 @@ class Redis
public function lock($key, int $timeout = 5): bool|int public function lock($key, int $timeout = 5): bool|int
{ {
$script = <<<SCRIPT $script = <<<SCRIPT
local _nx = redis.call('setnx',KEYS[1], ARGV[1]) local _nx = redis.call('setnx',KEYS[1], ARGV[1])
if (_nx ~= 0) then if (_nx ~= 0) then
redis.call('expire',KEYS[1], ARGV[1]) redis.call('expire',KEYS[1], ARGV[1])
return 1 return 1
end end
return 0 return 0
SCRIPT; SCRIPT;
return $this->eval($script, ['{lock}:' . $key, $timeout], 1); return $this->eval($script, ['{lock}:' . $key, $timeout], 1);
} }
@@ -139,6 +136,8 @@ SCRIPT;
/** /**
* 代理 Redis 方法调用,内置健康检查和连接回收
* 如果连接 ping 失败则关闭连接并移除,不归还池中防止污染
* @param $name * @param $name
* @param $arguments * @param $arguments
* @return mixed * @return mixed
@@ -150,15 +149,27 @@ SCRIPT;
try { try {
return $client->{$name}(...$arguments); return $client->{$name}(...$arguments);
} catch (\Throwable $throwable) { } catch (\Throwable $throwable) {
return trigger_print_error(throwable($throwable)); return $this->getLogger()->json_log($throwable, [], false);
} finally { } finally {
if ($client->ping('h') == 'h') { if ($client->ping('h') == 'h') {
$this->pool()->push($this->getName(), $client); $this->pool()->push($this->getName(), $client);
} else {
$client->close();
$this->pool()->abandon($this->getName());
} }
} }
} }
/**
* @return Kiri\Error\StdoutLogger
*/
protected function getLogger(): Kiri\Error\StdoutLogger
{
return Kiri::getLogger();
}
/** /**
* @return \Redis * @return \Redis
* @throws * @throws
@@ -200,10 +211,10 @@ SCRIPT;
{ {
$redis = new \Redis(); $redis = new \Redis();
if (!$redis->connect($this->host, $this->port, $this->timeout)) { if (!$redis->connect($this->host, $this->port, $this->timeout)) {
throw new RedisConnectException(sprintf('The Redis Connect %s::%d Fail.', $this->host, $this->port)); throw new RedisConnectException(sprintf('The NoSql Connect %s::%d Fail.', $this->host, $this->port));
} }
if (!empty($this->auth) && !$redis->auth($this->auth)) { if (!empty($this->auth) && !$redis->auth($this->auth)) {
throw new RedisConnectException(sprintf('Redis Error: %s, Host %s, Auth %s', $redis->getLastError(), $this->host, $this->auth)); throw new RedisConnectException(sprintf('NoSql Error: %s, Host %s, Auth %s', $redis->getLastError(), $this->host, $this->auth));
} }
$redis->select($this->databases); $redis->select($this->databases);
if ($this->read_timeout > 0) { if ($this->read_timeout > 0) {
+38 -20
View File
@@ -9,38 +9,55 @@
white-space: pre-wrap; white-space: pre-wrap;
word-wrap: break-word; word-wrap: break-word;
overflow-y: scroll; overflow-y: scroll;
overflow: hidden; overflow: hidden;
} }
</style> </style>
</head> </head>
<body style="background-color: #666;color: #fff;presentation-level: increment;"> <body style="background-color: #666;color: #fff;presentation-level: increment;">
<video id="output" width="320" height="240" autoplay></video> <!--<video id="output" width="320" height="240" autoplay></video>-->
<pre id="format"></pre> <pre id="format"></pre>
<script type="text/javascript"> <script type="text/javascript">
let sock, tick, format = document.getElementById('format'); let sock, tick, format = document.getElementById('format');
let buffer; // let buffer;
let ms = new MediaSource() // let ms = new MediaSource()
let output = document.getElementById('output') let unique = '';
output.src = URL.createObjectURL(ms)
ms.onsourceopen = () => { // let output = document.getElementById('output')
buffer = ms.addSourceBuffer('video/webm; codecs="vorbis,vp8"') // output.src = URL.createObjectURL(ms)
} // ms.onsourceopen = () => {
// buffer = ms.addSourceBuffer('video/webm; codecs="vorbis,vp8"')
// }
function message(message) { function message(message) {
// let div = document.createElement('div'); try {
// div.innerHTML = message.data; let data = JSON.parse(message.data);
// div.style.cssText = 'padding:5px 10px;background-color:#222;-webkit-border-radius: 5px;-moz-border-radius: 5px;border-radius: 5px;word-break: break-all;word-wrap: break-word;'; if (data.event === 'user::kick') {
// div.style.marginBottom = '10px'; return;
// let count = format.getElementsByTagName('div'); }
if (unique === '') {
unique = message.data;
}
if (data["ack"]) {
sock.send(JSON.stringify({'event': 'ack', 'id': unique, 'data': {'ack': data["ack"]}}));
}
} catch (e) {
if (unique === '') {
unique = message.data;
}
}
let div = document.createElement('div');
div.innerHTML = message.data;
div.style.cssText = 'padding:5px 10px;background-color:#222;-webkit-border-radius: 5px;-moz-border-radius: 5px;border-radius: 5px;word-break: break-all;word-wrap: break-word;';
div.style.marginBottom = '10px';
let count = format.getElementsByTagName('div');
buffer.appendBuffer(new Uint8Array(message.data)) format.insertBefore(div, count[0]);
// format.insertBefore(div, count[0]);
} }
function close(even) { function close(even) {
unique = '';
setTimeout(function () { setTimeout(function () {
connect(); connect();
sock.onmessage = message; sock.onmessage = message;
@@ -50,13 +67,14 @@
} }
function connect() { function connect() {
sock = new WebSocket('wss://center-wss.stupideyes.com/ws?access_token=6648f48a-466ba-6394-70527ef8b-bc47b8'); sock = new WebSocket('ws://121.40.147.153:6611/sockets/?auth=dG9rZW49NjYxNTBhMWQwYS0wMWItMDMxYS0wZTRjNTJiNGEtMjkzMTI5JnRpbWU9MTc4MjEyODcwMCZyZWZyZXNoPTJzMTdyR1BMWDRuWElKWExycTdNU1pQNEsyUXQwQ1pId1RsWUM5dzZJTmpLU1dvOThocW5KR0tQVFNCU2E2QTllNWRMTm9DYkRBaVhVQVd1cUU3Q1B5ejZLMTVzamdaTlpJWHhXNVlKeWQ2ODBaTkhZdktHUnd5RklKT1NZTEVBMURSb3JrbTUwRVUrTmpNMjJJL0lsMmpPT3p2MzFFNFZ4WkZwb1pXSmZVV015Q1VZenFtYTg4MDRHZ0Z3anZobDlYdWFkakR3QmhmZFd4QloxSC9HWndDRHdVQjN3elFrL01wUWFOSTB2YTlqZjZzQTRESFI2VlJtYWpxYWFHdkVNV3BGOXllbGVrTXFhcUhyT0tkdUpZRXVpSzEzZkNoRUljblFqdUVzWjdGUDBYVGlkNTUybUlyQnlYQjc0YktxQVRNbklvZlFQcnl3aEVUNGRSZVhhdz09');
sock.onopen = function () { // sock = new WebSocket('wss://meet-bottle.zhuangb123.com/socket/?auth=dG9rZW49M2I2ODJhNzg0NS0xMTktMzBiMS1mMDkxOGRhNjktNTg2ZDEyJnRpbWU9MTc1MzA4MTI5MyZyZWZyZXNoPXBDT0VFYk9KOG8xTEVZQytyUkR4VlZIaXR1TmVWcndCY2crRTBua2U1ZkJuUWNJaHl6NUtTV0x2ZExXa1Y5aXlyK3NmRnRwOVRCVU91MnhPSVRPRjROTjhoT0hlODNNVmZjN1NXb2QyeDY0TXEvZTFEUCtySjNzNjZhVlplcXdYV0QzV2VRd0V6YkowZ29oOFFqRHVvZGcyb281OEZkZVp5TjVIcHFyejRZQ0VMbkxydXlCUmpFdjNTWnRsQ3gxMWthNDNxbEwzM1lJYVlaV2t3dEhOMm9VaXllNFpKOHFnU1FueEZ4N0c4RDhabzBhajFFeEJIZTlJUFQ0VUo3UkR0V0g2Y3A3bkY3bXlkVHB4Wnp5NG1kRlgxa3M5eC9iVlJHaVFDRnU4VEFsUVdDdHEzbmJ1TnNYZVd3Q2dXWEd1OEUzMld3THVFRzRCZFRCanA2MGtYUT09');
sock.onopen = function (data) {
if (tick) { if (tick) {
clearInterval(tick) clearInterval(tick)
} }
tick = setInterval(function () { tick = setInterval(function () {
sock.send(JSON.stringify({'route': 'getUserPosition', 'tick': new Date().getTime()})); sock.send(JSON.stringify({'event': 'tick', 'id': unique, 'data': {'math': Math.ceil(Math.random() * 1000000)}}));
}, 3000) }, 3000)
} }
} }
+97 -43
View File
@@ -1,51 +1,105 @@
<?php <?php
ini_set('memory_limit','64GB'); use wchat\common\AppConfig;
use wchat\wx\V3\Libs\TransferDetail;
use wchat\wx\V3\Libs\TransferSceneReportInfo;
use wchat\wx\V3\WxV3Transfer;
use Swoole\Coroutine; //ini_set('memory_limit', '64G');
use Swoole\Coroutine\Http\Client;
use function Swoole\Coroutine\run;
function faker($page = 0) $msg = 'default';
{ try {
$client = new Client('openapi.stupideyes.com', 443, true);
$client->get('/faker?offset=' . $page);
$client->close();
return json_decode($client->getBody(), true); if (random_int(1, 10) % 3 === 0) {
} return;
run(function () {
$offset = 1;
$success = 0;
for ($i = 1; $i <= 10000; $i++) {
$faker = faker($offset);
$offset++;
go(function () use ($faker, $offset, &$success) {
$socket = new Swoole\Coroutine\Http\Client('43.248.128.57', 14101);
$socket->upgrade("/ws?access_token=" . $faker['params']['token']);
if ($socket->connected) {
$success += 1;
while (true) {
$socket->recv();
// $socket->push('hello');
// var_dump($socket->recv());
Coroutine::sleep(0.1);
}
} else {
$success -= 1;
echo 'websocket fail: ' . socket_strerror($socket->errCode) . PHP_EOL;
}
});
Coroutine::sleep(0.1);
var_dump($success);
} }
$msg = 'default2';
} catch (\Exception $e) {
}); } finally {
var_dump($msg);
}
//run(function () {
// $offset = 1;
// $success = 0;
//
// $group = new Coroutine\WaitGroup();
// for ($i = 0; $i < 54500; $i++) {
// $offset++;
//
// $group->add(1);
// Swoole\Coroutine::create(function () use ($offset, &$success) {
// $socket = new Swoole\Coroutine\Http\Client('192.168.0.57', 14101);
// $socket->upgrade("/websocket");
// if ($socket->connected) {
// $success += 1;
// while (true) {
// $socket->recv();
// Coroutine::sleep(0.1);
//
// $socket->push("2");
// }
// } else {
// echo 'websocket fail: ' . socket_strerror($socket->errCode) . PHP_EOL;
// echo $success;
// }
// # echo $offset . PHP_EOL;
// });
// }
// $group->wait();
//});
//
//
//function Index_Odd()
//{
//
//}
//class Dispatcher
//{
//
//
// public function dispatch(){
//
// }
//
//
// public static function dispatch1()
// {
//
// }
//
//
//}
//$t = microtime(true);
//var_dump(method_exists('Dispatcher', 'dispatch'));
//var_dump(method_exists('Dispatcher', 'dispatch1'));
//
//var_dump(microtime(true) - $t);
//
//$t = microtime(true);
//
//$r = new ReflectionClass('Dispatcher');
//
//var_dump($r->hasMethod('dispatch'));
//var_dump($r->hasMethod('dispatch1') && $r->getMethod('dispatch1')->isStatic());
//
//var_dump(microtime(true) - $t);
//$transferDetail = new TransferDetail();
//$transferDetail->setTransferAmount(1);
//$transferDetail->setTransferRemark("提现");
//$transferDetail->setTransferSceneId("1005");
//$transferDetail->setOpenid("xxxxx");
//$transferDetail->setNotifyUrl("https");
//$transferDetail->setOutBillNo("");
//$transferDetail->setTransferSceneReportInfos(new TransferSceneReportInfo('', ''), new TransferSceneReportInfo('', ''));
//$transferDetail->setUserName("");
//$transferDetail->setUserRecvPerception("");
//
//$transfer = new WxV3Transfer();
//$transfer->setPayConfig(AppConfig::instance((object)[]));
//$response = $transfer->transfer($transferDetail);