first commit
This commit is contained in:
60
vendor/webman/redis-queue/src/Client.php
vendored
Normal file
60
vendor/webman/redis-queue/src/Client.php
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace Webman\RedisQueue;
|
||||
|
||||
use Workerman\RedisQueue\Client as RedisClient;
|
||||
|
||||
/**
|
||||
* Class RedisQueue
|
||||
* @package support
|
||||
*
|
||||
* Strings methods
|
||||
* @method static void send($queue, $data, $delay=0)
|
||||
*/
|
||||
class Client
|
||||
{
|
||||
/**
|
||||
* @var Client[]
|
||||
*/
|
||||
protected static $_connections = null;
|
||||
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @return RedisClient
|
||||
*/
|
||||
public static function connection($name = 'default') {
|
||||
if (!isset(static::$_connections[$name])) {
|
||||
$config = config('redis_queue', config('plugin.webman.redis-queue.redis', []));
|
||||
if (!isset($config[$name])) {
|
||||
throw new \RuntimeException("RedisQueue connection $name not found");
|
||||
}
|
||||
$host = $config[$name]['host'];
|
||||
$options = $config[$name]['options'];
|
||||
$client = new RedisClient($host, $options);
|
||||
static::$_connections[$name] = $client;
|
||||
}
|
||||
return static::$_connections[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param $arguments
|
||||
* @return mixed
|
||||
*/
|
||||
public static function __callStatic($name, $arguments)
|
||||
{
|
||||
return static::connection('default')->{$name}(... $arguments);
|
||||
}
|
||||
}
|
||||
91
vendor/webman/redis-queue/src/Command/MakeConsumerCommand.php
vendored
Normal file
91
vendor/webman/redis-queue/src/Command/MakeConsumerCommand.php
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
namespace Webman\RedisQueue\Command;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Webman\Console\Util;
|
||||
|
||||
|
||||
class MakeConsumerCommand extends Command
|
||||
{
|
||||
protected static $defaultName = 'redis-queue:consumer';
|
||||
protected static $defaultDescription = 'Make redis-queue consumer';
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this->addArgument('name', InputArgument::REQUIRED, 'Consumer name');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
* @return int
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$name = $input->getArgument('name');
|
||||
$output->writeln("Make consumer $name");
|
||||
|
||||
$path = '';
|
||||
$namespace = 'app\\queue\\redis';
|
||||
if ($pos = strrpos($name, DIRECTORY_SEPARATOR)) {
|
||||
$path = substr($name, 0, $pos + 1);
|
||||
$name = substr($name, $pos + 1);
|
||||
$namespace .= '\\' . str_replace(DIRECTORY_SEPARATOR, '\\', trim($path, DIRECTORY_SEPARATOR));
|
||||
}
|
||||
$class = Util::nameToClass($name);
|
||||
$queue = Util::classToName($name);
|
||||
|
||||
$file = app_path() . "/queue/redis/{$path}$class.php";
|
||||
$this->createConsumer($namespace, $class, $queue, $file);
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $class
|
||||
* @param $queue
|
||||
* @param $file
|
||||
* @return void
|
||||
*/
|
||||
protected function createConsumer($namspace, $class, $queue, $file)
|
||||
{
|
||||
$path = pathinfo($file, PATHINFO_DIRNAME);
|
||||
if (!is_dir($path)) {
|
||||
mkdir($path, 0777, true);
|
||||
}
|
||||
$controller_content = <<<EOF
|
||||
<?php
|
||||
|
||||
namespace $namspace;
|
||||
|
||||
use Webman\\RedisQueue\\Consumer;
|
||||
|
||||
class $class implements Consumer
|
||||
{
|
||||
// 要消费的队列名
|
||||
public \$queue = '$queue';
|
||||
|
||||
// 连接名,对应 plugin/webman/redis-queue/redis.php 里的连接`
|
||||
public \$connection = 'default';
|
||||
|
||||
// 消费
|
||||
public function consume(\$data)
|
||||
{
|
||||
// 无需反序列化
|
||||
var_export(\$data);
|
||||
}
|
||||
}
|
||||
|
||||
EOF;
|
||||
file_put_contents($file, $controller_content);
|
||||
}
|
||||
|
||||
}
|
||||
25
vendor/webman/redis-queue/src/Consumer.php
vendored
Normal file
25
vendor/webman/redis-queue/src/Consumer.php
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
namespace Webman\RedisQueue;
|
||||
|
||||
|
||||
/**
|
||||
* Interface Consumer
|
||||
* @package Webman\RedisQueue
|
||||
*/
|
||||
interface Consumer
|
||||
{
|
||||
public function consume($data);
|
||||
}
|
||||
72
vendor/webman/redis-queue/src/Install.php
vendored
Normal file
72
vendor/webman/redis-queue/src/Install.php
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
namespace Webman\RedisQueue;
|
||||
|
||||
class Install
|
||||
{
|
||||
const WEBMAN_PLUGIN = true;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected static $pathRelation = array (
|
||||
'config/plugin/webman/redis-queue' => 'config/plugin/webman/redis-queue',
|
||||
);
|
||||
|
||||
/**
|
||||
* Install
|
||||
* @return void
|
||||
*/
|
||||
public static function install()
|
||||
{
|
||||
static::installByRelation();
|
||||
if (!is_dir(app_path() . '/queue/redis')){
|
||||
mkdir(app_path() . '/queue/redis', 0777, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Uninstall
|
||||
* @return void
|
||||
*/
|
||||
public static function uninstall()
|
||||
{
|
||||
self::uninstallByRelation();
|
||||
}
|
||||
|
||||
/**
|
||||
* installByRelation
|
||||
* @return void
|
||||
*/
|
||||
public static function installByRelation()
|
||||
{
|
||||
foreach (static::$pathRelation as $source => $dest) {
|
||||
if ($pos = strrpos($dest, '/')) {
|
||||
$parent_dir = base_path().'/'.substr($dest, 0, $pos);
|
||||
if (!is_dir($parent_dir)) {
|
||||
mkdir($parent_dir, 0777, true);
|
||||
}
|
||||
}
|
||||
//symlink(__DIR__ . "/$source", base_path()."/$dest");
|
||||
copy_dir(__DIR__ . "/$source", base_path()."/$dest");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* uninstallByRelation
|
||||
* @return void
|
||||
*/
|
||||
public static function uninstallByRelation()
|
||||
{
|
||||
foreach (static::$pathRelation as $source => $dest) {
|
||||
$path = base_path()."/$dest";
|
||||
if (!is_dir($path) && !is_file($path)) {
|
||||
continue;
|
||||
}
|
||||
/*if (is_link($path) {
|
||||
unlink($path);
|
||||
}*/
|
||||
remove_dir($path);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
70
vendor/webman/redis-queue/src/Process/Consumer.php
vendored
Normal file
70
vendor/webman/redis-queue/src/Process/Consumer.php
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
|
||||
namespace Webman\RedisQueue\Process;
|
||||
|
||||
use support\Container;
|
||||
use Webman\RedisQueue\Client;
|
||||
|
||||
/**
|
||||
* Class Consumer
|
||||
* @package process
|
||||
*/
|
||||
class Consumer
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $_consumerDir = '';
|
||||
|
||||
/**
|
||||
* StompConsumer constructor.
|
||||
* @param string $consumer_dir
|
||||
*/
|
||||
public function __construct($consumer_dir = '')
|
||||
{
|
||||
$this->_consumerDir = $consumer_dir;
|
||||
}
|
||||
|
||||
/**
|
||||
* onWorkerStart.
|
||||
*/
|
||||
public function onWorkerStart()
|
||||
{
|
||||
if (!is_dir($this->_consumerDir)) {
|
||||
echo "Consumer directory {$this->_consumerDir} not exists\r\n";
|
||||
return;
|
||||
}
|
||||
$dir_iterator = new \RecursiveDirectoryIterator($this->_consumerDir);
|
||||
$iterator = new \RecursiveIteratorIterator($dir_iterator);
|
||||
foreach ($iterator as $file) {
|
||||
if (is_dir($file)) {
|
||||
continue;
|
||||
}
|
||||
$fileinfo = new \SplFileInfo($file);
|
||||
$ext = $fileinfo->getExtension();
|
||||
if ($ext === 'php') {
|
||||
$class = str_replace('/', "\\", substr(substr($file, strlen(base_path())), 0, -4));
|
||||
if (is_a($class, 'Webman\RedisQueue\Consumer', true)) {
|
||||
$consumer = Container::get($class);
|
||||
$connection_name = $consumer->connection ?? 'default';
|
||||
$queue = $consumer->queue;
|
||||
$connection = Client::connection($connection_name);
|
||||
$connection->subscribe($queue, [$consumer, 'consume']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
78
vendor/webman/redis-queue/src/Redis.php
vendored
Normal file
78
vendor/webman/redis-queue/src/Redis.php
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace Webman\RedisQueue;
|
||||
|
||||
use Workerman\Timer;
|
||||
|
||||
/**
|
||||
* Class RedisQueue
|
||||
* @package support
|
||||
*
|
||||
* Strings methods
|
||||
* @method static void send($queue, $data, $delay=0)
|
||||
*/
|
||||
class Redis
|
||||
{
|
||||
/**
|
||||
* @var RedisConnection[]
|
||||
*/
|
||||
protected static $_connections = [];
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @return RedisConnection
|
||||
*/
|
||||
public static function connection($name = 'default') {
|
||||
if (!isset(static::$_connections[$name])) {
|
||||
$configs = config('redis_queue', config('plugin.webman.redis-queue.redis', []));
|
||||
if (!isset($configs[$name])) {
|
||||
throw new \RuntimeException("RedisQueue connection $name not found");
|
||||
}
|
||||
$config = $configs[$name];
|
||||
static::$_connections[$name] = static::connect($config);
|
||||
}
|
||||
return static::$_connections[$name];
|
||||
}
|
||||
|
||||
protected static function connect($config)
|
||||
{
|
||||
if (!extension_loaded('redis')) {
|
||||
throw new \RuntimeException('Please make sure the PHP Redis extension is installed and enabled.');
|
||||
}
|
||||
|
||||
$redis = new RedisConnection();
|
||||
$address = $config['host'];
|
||||
$config = [
|
||||
'host' => parse_url($address, PHP_URL_HOST),
|
||||
'port' => parse_url($address, PHP_URL_PORT),
|
||||
'db' => $config['options']['database'] ?? $config['options']['db'] ?? 0,
|
||||
'auth' => $config['options']['auth'] ?? '',
|
||||
'timeout' => $config['options']['timeout'] ?? 2,
|
||||
'ping' => $config['options']['ping'] ?? 55,
|
||||
'prefix' => $config['options']['prefix'] ?? '',
|
||||
];
|
||||
$redis->connectWithConfig($config);
|
||||
return $redis;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param $arguments
|
||||
* @return mixed
|
||||
*/
|
||||
public static function __callStatic($name, $arguments)
|
||||
{
|
||||
return static::connection('default')->{$name}(... $arguments);
|
||||
}
|
||||
}
|
||||
99
vendor/webman/redis-queue/src/RedisConnection.php
vendored
Normal file
99
vendor/webman/redis-queue/src/RedisConnection.php
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of webman.
|
||||
*
|
||||
* Licensed under The MIT License
|
||||
* For full copyright and license information, please see the MIT-LICENSE.txt
|
||||
* Redistributions of files must retain the above copyright notice.
|
||||
*
|
||||
* @author walkor<walkor@workerman.net>
|
||||
* @copyright walkor<walkor@workerman.net>
|
||||
* @link http://www.workerman.net/
|
||||
* @license http://www.opensource.org/licenses/mit-license.php MIT License
|
||||
*/
|
||||
namespace Webman\RedisQueue;
|
||||
|
||||
use Workerman\Timer;
|
||||
use Workerman\Worker;
|
||||
|
||||
class RedisConnection extends \Redis
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $config = [];
|
||||
|
||||
/**
|
||||
* @param array $config
|
||||
* @return void
|
||||
*/
|
||||
public function connectWithConfig(array $config = [])
|
||||
{
|
||||
static $timer;
|
||||
if ($config) {
|
||||
$this->config = $config;
|
||||
}
|
||||
if (false === $this->connect($this->config['host'], $this->config['port'], $this->config['timeout'] ?? 2)) {
|
||||
throw new \RuntimeException("Redis connect {$this->config['host']}:{$this->config['port']} fail.");
|
||||
}
|
||||
if (!empty($this->config['auth'])) {
|
||||
$this->auth($this->config['auth']);
|
||||
}
|
||||
if (!empty($this->config['db'])) {
|
||||
$this->select($this->config['db']);
|
||||
}
|
||||
if (!empty($this->config['prefix'])) {
|
||||
$this->setOption(\Redis::OPT_PREFIX, $this->config['prefix']);
|
||||
}
|
||||
if (Worker::getAllWorkers() && !$timer) {
|
||||
$timer = Timer::add($this->config['ping'] ?? 55, function () {
|
||||
$this->execCommand('ping');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $command
|
||||
* @param ...$args
|
||||
* @return mixed
|
||||
* @throws \Throwable
|
||||
*/
|
||||
protected function execCommand($command, ...$args)
|
||||
{
|
||||
try {
|
||||
return $this->{$command}(...$args);
|
||||
} catch (\Throwable $e) {
|
||||
$msg = strtolower($e->getMessage());
|
||||
if ($msg === 'connection lost' || strpos($msg, 'went away')) {
|
||||
$this->connectWithConfig();
|
||||
return $this->{$command}(...$args);
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $queue
|
||||
* @param $data
|
||||
* @param $delay
|
||||
* @return bool
|
||||
*/
|
||||
public function send($queue, $data, $delay = 0)
|
||||
{
|
||||
$queue_waiting = '{redis-queue}-waiting';
|
||||
$queue_delay = '{redis-queue}-delayed';
|
||||
$now = time();
|
||||
$package_str = json_encode([
|
||||
'id' => time().rand(),
|
||||
'time' => $now,
|
||||
'delay' => $delay,
|
||||
'attempts' => 0,
|
||||
'queue' => $queue,
|
||||
'data' => $data
|
||||
]);
|
||||
if ($delay) {
|
||||
return (bool)$this->execCommand('zAdd' ,$queue_delay, $now + $delay, $package_str);
|
||||
}
|
||||
return (bool)$this->execCommand('lPush', $queue_waiting.$queue, $package_str);
|
||||
}
|
||||
}
|
||||
4
vendor/webman/redis-queue/src/config/plugin/webman/redis-queue/app.php
vendored
Normal file
4
vendor/webman/redis-queue/src/config/plugin/webman/redis-queue/app.php
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
<?php
|
||||
return [
|
||||
'enable' => true,
|
||||
];
|
||||
7
vendor/webman/redis-queue/src/config/plugin/webman/redis-queue/command.php
vendored
Normal file
7
vendor/webman/redis-queue/src/config/plugin/webman/redis-queue/command.php
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
use Webman\RedisQueue\Command\MakeConsumerCommand;
|
||||
|
||||
return [
|
||||
MakeConsumerCommand::class
|
||||
];
|
||||
11
vendor/webman/redis-queue/src/config/plugin/webman/redis-queue/process.php
vendored
Normal file
11
vendor/webman/redis-queue/src/config/plugin/webman/redis-queue/process.php
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
return [
|
||||
'consumer' => [
|
||||
'handler' => Webman\RedisQueue\Process\Consumer::class,
|
||||
'count' => 8, // 可以设置多进程同时消费
|
||||
'constructor' => [
|
||||
// 消费者类目录
|
||||
'consumer_dir' => app_path() . '/queue/redis'
|
||||
]
|
||||
]
|
||||
];
|
||||
13
vendor/webman/redis-queue/src/config/plugin/webman/redis-queue/redis.php
vendored
Normal file
13
vendor/webman/redis-queue/src/config/plugin/webman/redis-queue/redis.php
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
return [
|
||||
'default' => [
|
||||
'host' => 'redis://127.0.0.1:6379',
|
||||
'options' => [
|
||||
'auth' => null, // 密码,字符串类型,可选参数
|
||||
'db' => 0, // 数据库
|
||||
'prefix' => '', // key 前缀
|
||||
'max_attempts' => 5, // 消费失败后,重试次数
|
||||
'retry_seconds' => 5, // 重试间隔,单位秒
|
||||
]
|
||||
],
|
||||
];
|
||||
Reference in New Issue
Block a user