Compare commits
40 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 536e4c9bc5 | |||
| 91be2eba20 | |||
| d7f5f62c1c | |||
| 8b8bfa2a60 | |||
| 1ecf32bfa6 | |||
| 8c0c5b56c8 | |||
| 76351fbe66 | |||
| 8479106b9f | |||
| ca8cc081bc | |||
| a31c24ddf3 | |||
| 826503f4e6 | |||
| eeb348c053 | |||
| 168954e4c4 | |||
| 6a27fa3b74 | |||
| 79d4f47a67 | |||
| e6786666b7 | |||
| b5c18fc074 | |||
| 86b9c46755 | |||
| baea90e9e5 | |||
| 87e7535f27 | |||
| cc073f13c2 | |||
| 3afb1bd514 | |||
| 0e7d429bfc | |||
| 526aa9a63d | |||
| 48db719890 | |||
| daa8311eb9 | |||
| a065e5da49 | |||
| 8ae2af7dd6 | |||
| 6f0376ac44 | |||
| 08a4d6af4e | |||
| 9899578d52 | |||
| f97df5cfe5 | |||
| 34f8f6f523 | |||
| f6f94aff32 | |||
| 377a9c17c3 | |||
| 174d2f1659 | |||
| d6c8380c64 | |||
| 2e54326aba | |||
| 59632ac4a3 | |||
| da5a6a6b83 |
@@ -34,3 +34,4 @@ runtime/
|
|||||||
oot
|
oot
|
||||||
d
|
d
|
||||||
composer.lock
|
composer.lock
|
||||||
|
.gstack/
|
||||||
|
|||||||
@@ -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
@@ -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.
|
||||||
@@ -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 核心框架!我们期待您的反馈与贡献。
|
||||||
+51
-58
@@ -1,58 +1,51 @@
|
|||||||
{
|
{
|
||||||
"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": "^v7.3.1",
|
"symfony/console": "^v8.1.1",
|
||||||
"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": "^v5.5.0",
|
"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"
|
"replace": {
|
||||||
},
|
"symfony/polyfill-apcu": "*",
|
||||||
"replace": {
|
"symfony/polyfill-mbstring": "*",
|
||||||
"symfony/polyfill-apcu": "*",
|
"symfony/polyfill-ctype": "*"
|
||||||
"symfony/polyfill-php80": "*",
|
},
|
||||||
"symfony/polyfill-mbstring": "*",
|
"autoload": {
|
||||||
"symfony/polyfill-ctype": "*",
|
"psr-4": {
|
||||||
"symfony/polyfill-php73": "*",
|
"Kiri\\": "kiri-engine/"
|
||||||
"symfony/polyfill-php72": "*",
|
},
|
||||||
"symfony/polyfill-php81": "*"
|
"files": [
|
||||||
},
|
"Kiri.php",
|
||||||
"autoload": {
|
"function.php"
|
||||||
"psr-4": {
|
]
|
||||||
"Kiri\\": "kiri-engine/",
|
}
|
||||||
"Kiri\\Actor\\": "kiri-actor/"
|
}
|
||||||
},
|
|
||||||
"files": [
|
|
||||||
"Kiri.php",
|
|
||||||
"function.php"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
+759
-780
File diff suppressed because it is too large
Load Diff
@@ -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 . '/';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 = false;
|
||||||
|
|
||||||
|
private ?Channel $channel = null;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -17,18 +21,28 @@ class Coordinator
|
|||||||
*/
|
*/
|
||||||
public function yield(): void
|
public function yield(): void
|
||||||
{
|
{
|
||||||
while ($this->waite) {
|
if (Coroutine::getCid() > 0) {
|
||||||
usleep(1000);
|
if ($this->channel instanceof Channel) {
|
||||||
}
|
$this->channel->pop();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->wait === false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while ($this->wait === true) {
|
||||||
|
usleep(1000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function waite(): void
|
public function wait(): void
|
||||||
{
|
{
|
||||||
$this->waite = true;
|
Coroutine::getCid() > 0 ? $this->channel = new Channel(1) : $this->wait = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -37,8 +51,13 @@ class Coordinator
|
|||||||
*/
|
*/
|
||||||
public function done(): void
|
public function done(): void
|
||||||
{
|
{
|
||||||
$this->waite = false;
|
if (Coroutine::getCid() > 0) {
|
||||||
|
$this->channel?->push(true);
|
||||||
|
$this->channel->close();
|
||||||
|
$this->channel = null;
|
||||||
|
} else {
|
||||||
|
$this->wait = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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());
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,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());
|
||||||
}
|
}
|
||||||
@@ -104,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());
|
||||||
}
|
}
|
||||||
@@ -117,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]);
|
||||||
|
|||||||
@@ -9,6 +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 Throwable;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -48,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,
|
||||||
@@ -67,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -118,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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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,7 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Kiri\Redis;
|
namespace Kiri\NoSql;
|
||||||
|
|
||||||
use Kiri;
|
use Kiri;
|
||||||
use Kiri\Exception\RedisConnectException;
|
use Kiri\Exception\RedisConnectException;
|
||||||
@@ -15,7 +15,7 @@ use Kiri\Pool\Pool;
|
|||||||
use function config;
|
use function config;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Redis
|
* Class NoSql
|
||||||
* @package Kiri\Cache
|
* @package Kiri\Cache
|
||||||
* @mixin \Redis
|
* @mixin \Redis
|
||||||
*/
|
*/
|
||||||
@@ -103,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,6 +136,8 @@ SCRIPT;
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 代理 Redis 方法调用,内置健康检查和连接回收
|
||||||
|
* 如果连接 ping 失败则关闭连接并移除,不归还池中防止污染
|
||||||
* @param $name
|
* @param $name
|
||||||
* @param $arguments
|
* @param $arguments
|
||||||
* @return mixed
|
* @return mixed
|
||||||
@@ -147,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
|
||||||
@@ -197,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
@@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user