diff --git a/Database/Base/BaseActiveRecord.php b/Database/Base/BaseActiveRecord.php
index 14ae4b69..d217e4c7 100644
--- a/Database/Base/BaseActiveRecord.php
+++ b/Database/Base/BaseActiveRecord.php
@@ -20,6 +20,7 @@ use Database\Mysql\Columns;
use Database\Relation;
use Snowflake\Error\Logger;
use Exception;
+use Snowflake\Exception\ComponentException;
use validator\Validator;
use Database\IOrm;
use Snowflake\Snowflake;
@@ -118,10 +119,11 @@ abstract class BaseActiveRecord extends Component implements IOrm, \ArrayAccess
* @return mixed
*
* get last exception or other error
+ * @throws ComponentException
*/
public function getLastError()
{
- return Logger::getLastError('mysql');
+ return Snowflake::get()->getLogger()->getLastError('mysql');
}
/**
diff --git a/http-server/Events/Callback.php b/http-server/Abstracts/Callback.php
similarity index 83%
rename from http-server/Events/Callback.php
rename to http-server/Abstracts/Callback.php
index 01e92413..848a35f1 100644
--- a/http-server/Events/Callback.php
+++ b/http-server/Abstracts/Callback.php
@@ -1,7 +1,7 @@
container = $container;
- }
-
-
-
/**
* @param $server
@@ -46,8 +31,10 @@ abstract class Callback extends Application
$this->eventNotify($message, $event);
Snowflake::clearProcessId($server->worker_pid);
- Logger::write($this->_MESSAGE[$message] . $worker_id);
- Logger::clear();
+
+ $logger = Snowflake::get()->getLogger();
+ $logger->write($this->_MESSAGE[$message] . $worker_id);
+ $logger->clear();
}
diff --git a/http-server/Events/Trigger/OnAfterReload.php b/http-server/Events/OnAfterReload.php
similarity index 64%
rename from http-server/Events/Trigger/OnAfterReload.php
rename to http-server/Events/OnAfterReload.php
index 5e275ba4..38ce2e0c 100644
--- a/http-server/Events/Trigger/OnAfterReload.php
+++ b/http-server/Events/OnAfterReload.php
@@ -1,10 +1,10 @@
isEstablished($fd)) {
+ return;
+ }
+ $manager = Snowflake::get()->annotation->get('websocket');
+ $name = $manager->getName(AWebsocket::CLOSE);
+ } else if ($server instanceof HServer) {
+ $manager = Snowflake::get()->annotation->get('http');
+ $name = $manager->getName(Annotation::CLOSE);
+ } else {
+ $manager = Snowflake::get()->annotation->get('tcp');
+ $name = $manager->getName(Tcp::CLOSE);
+ }
+ if (!$manager->has($name)) {
+ return;
+ }
+ $manager->runWith($name, [$fd]);
+ } catch (\Throwable $exception) {
+ $this->addError($exception->getMessage());
+ } finally {
+ $event = Snowflake::get()->event;
+ $event->trigger(Event::RELEASE_ALL);
+
+ $logger = Snowflake::get()->getLogger();
+ $logger->insert();
+ }
+ }
+
+
+}
diff --git a/http-server/Events/Trigger/OnConnect.php b/http-server/Events/OnConnect.php
similarity index 82%
rename from http-server/Events/Trigger/OnConnect.php
rename to http-server/Events/OnConnect.php
index bf9625b2..607cd5ad 100644
--- a/http-server/Events/Trigger/OnConnect.php
+++ b/http-server/Events/OnConnect.php
@@ -1,18 +1,18 @@
header['sec-websocket-key'];
+ $patten = '#^[+/0-9A-Za-z]{21}[AQgw]==$#';
+ if (0 === preg_match($patten, $secWebSocketKey) || 16 !== strlen(base64_decode($secWebSocketKey))) {
+ return false;
+ }
+ $key = base64_encode(sha1(
+ $request->header['sec-websocket-key'] . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11',
+ TRUE
+ ));
+ $headers = [
+ 'Upgrade' => 'websocket',
+ 'Connection' => 'Upgrade',
+ 'Sec-websocket-Accept' => $key,
+ 'Sec-websocket-Version' => '13',
+ ];
+ if (isset($request->header['sec-websocket-protocol'])) {
+ $headers['Sec-websocket-Protocol'] = $request->header['sec-websocket-protocol'];
+ }
+ foreach ($headers as $key => $val) {
+ $response->header($key, $val);
+ }
+
+ /** @var AWebsocket $manager */
+ $manager = Snowflake::get()->annotation->get('websocket');
+ if ($manager->has($manager->getName(AWebsocket::HANDSHAKE))) {
+ $manager->runWith($manager->getName(AWebsocket::HANDSHAKE), [$request, $response]);
+ } else {
+ $response->status(502);
+ $response->end();
+ }
+ return true;
+ }
+
+
+}
diff --git a/http-server/Events/Trigger/OnManagerStart.php b/http-server/Events/OnManagerStart.php
similarity index 88%
rename from http-server/Events/Trigger/OnManagerStart.php
rename to http-server/Events/OnManagerStart.php
index b87246fd..817ff9e0 100644
--- a/http-server/Events/Trigger/OnManagerStart.php
+++ b/http-server/Events/OnManagerStart.php
@@ -1,10 +1,10 @@
opcode == 0x08) {
+ return;
+ }
+
+ $event = Snowflake::get()->event;
+ if ($event->exists(Event::SERVER_MESSAGE)) {
+ $event->trigger(Event::SERVER_MESSAGE, [$server, $frame]);
+ } else {
+ $frame->data = json_decode($frame->data, true);
+ }
+
+ /** @var AWebsocket $manager */
+ $manager = Snowflake::get()->annotation->get('websocket');
+ $manager->runWith($manager->getName(AWebsocket::MESSAGE, [null, null, $frame->data['route']]), [$frame, $server]);
+ } catch (\Exception $exception) {
+ $this->addError($exception->getMessage(), 'websocket');
+ $server->send($frame->fd, $exception->getMessage());
+ } finally {
+ $event = Snowflake::get()->event;
+ $event->trigger(Event::EVENT_AFTER_REQUEST);
+ Snowflake::get()->logger->insert();
+ }
+ }
+
+
+
+
+}
diff --git a/http-server/Events/Packet.php b/http-server/Events/OnPacket.php
similarity index 54%
rename from http-server/Events/Packet.php
rename to http-server/Events/OnPacket.php
index 6f901591..c2a7a0e5 100644
--- a/http-server/Events/Packet.php
+++ b/http-server/Events/OnPacket.php
@@ -4,18 +4,60 @@
namespace HttpServer\Events;
-use Exception;
+use Closure;
+use HttpServer\Events\Abstracts\Callback;
+use Snowflake\Core\JSON;
use Snowflake\Event;
use Snowflake\Snowflake;
use Swoole\Server;
+use Exception;
/**
* Class OnPacket
- * @package HttpServer\Events\Trigger
+ * @package HttpServer\Events
*/
-class Packet extends Service
+class OnPacket extends Callback
{
+
+ /** @var Closure|array */
+ public $unpack;
+
+
+ /** @var Closure|array */
+ public $pack;
+
+
+ /**
+ * @param $data
+ * @return mixed
+ * @throws Exception
+ */
+ public function pack($data)
+ {
+ $callback = $this->pack;
+ if (is_callable($callback, true)) {
+ return $callback($data);
+ }
+ return JSON::encode($data);
+ }
+
+
+ /**
+ * @param $data
+ * @return mixed
+ */
+ public function unpack($data)
+ {
+ $callback = $this->unpack;
+ if (is_callable($callback, true)) {
+ return $callback($data);
+ }
+ return JSON::decode($data);
+ }
+
+
+
/**
* @param Server $server
* @param $data
@@ -41,4 +83,5 @@ class Packet extends Service
}
}
+
}
diff --git a/http-server/Events/Trigger/OnPipeMessage.php b/http-server/Events/OnPipeMessage.php
similarity index 64%
rename from http-server/Events/Trigger/OnPipeMessage.php
rename to http-server/Events/OnPipeMessage.php
index 9230c145..31f8525d 100644
--- a/http-server/Events/Trigger/OnPipeMessage.php
+++ b/http-server/Events/OnPipeMessage.php
@@ -1,10 +1,10 @@
pack;
+ if (is_callable($callback, true)) {
+ return $callback($data);
+ }
+ return JSON::encode($data);
+ }
+
+
+ /**
+ * @param $data
+ * @return mixed
+ */
+ public function unpack($data)
+ {
+ $callback = $this->unpack;
+ if (is_callable($callback, true)) {
+ return $callback($data);
+ }
+ return JSON::decode($data);
+ }
+
+
/**
* @param Server $server
* @param int $fd
@@ -25,7 +65,7 @@ class Receive extends Service
* @return mixed
* @throws Exception
*/
- public function onReceive(\Swoole\Server $server, int $fd, int $reactorId, string $data)
+ public function onHandler(\Swoole\Server $server, int $fd, int $reactorId, string $data)
{
try {
$client = [$fd];
diff --git a/http-server/Events/Http.php b/http-server/Events/OnRequest.php
similarity index 59%
rename from http-server/Events/Http.php
rename to http-server/Events/OnRequest.php
index ed18553b..33bfd0b1 100644
--- a/http-server/Events/Http.php
+++ b/http-server/Events/OnRequest.php
@@ -4,66 +4,31 @@
namespace HttpServer\Events;
+use Exception;
+use HttpServer\Events\Abstracts\Callback;
use HttpServer\Http\Context;
use HttpServer\Http\Request as HRequest;
use HttpServer\Http\Response as HResponse;
-use HttpServer\ServerManager;
-use ReflectionException;
-use Snowflake\Application;
+use HttpServer\Service\Http;
use Snowflake\Core\JSON;
-use Snowflake\Exception\NotFindClassException;
use Snowflake\Snowflake;
use Swoole\Error;
use Swoole\Http\Request;
use Swoole\Http\Response;
-use Exception;
-use Swoole\Http\Server;
-use Swoole\Process\Pool;
-class Http extends Server
+/**
+ * Class OnRequest
+ * @package HttpServer\Events
+ */
+class OnRequest extends Callback
{
- /** @var Application */
- protected $application;
-
-
- /**
- * Receive constructor.
- * @param $application
- * @param $host
- * @param null $port
- * @param null $mode
- * @param null $sock_type
- */
- public function __construct($application, $host, $port = null, $mode = null, $sock_type = null)
- {
- $application->set(Http::class, $this);
- $this->application = $application;
- parent::__construct($host, $port, $mode, $sock_type);
- }
-
-
- /**
- * @param array $settings
- * @param null $pool
- * @param array $events
- * @param array $config
- * @return mixed|void
- * @throws NotFindClassException
- * @throws ReflectionException
- * @throws Exception
- */
- public function set(array $settings, $pool = null, $events = [], $config = [])
- {
- parent::set($settings);
- ServerManager::set($this, $settings, $this->application, $events, $config);
- }
/**
* @param Request $request
* @param Response $response
- * @throws \Exception
+ * @throws Exception
*/
public function onHandler(Request $request, Response $response)
{
@@ -79,7 +44,7 @@ class Http extends Server
}
} finally {
$dividing_line = str_pad('', 100, '-');
- $this->application->debug($dividing_line, 'app');
+ $this->debug($dividing_line, 'app');
}
}
@@ -96,7 +61,7 @@ class Http extends Server
'file' => $exception->getFile(),
'line' => $exception->getLine()
];
- $this->application->error(var_export($errorInfo, true));
+ $this->error(var_export($errorInfo, true));
$code = $exception->getCode() ?? 500;
$trance = array_slice($exception->getTrace(), 0, 10);
@@ -119,4 +84,5 @@ class Http extends Server
return [$request, $response];
}
+
}
diff --git a/http-server/Events/OnShutdown.php b/http-server/Events/OnShutdown.php
new file mode 100644
index 00000000..8ee61e84
--- /dev/null
+++ b/http-server/Events/OnShutdown.php
@@ -0,0 +1,80 @@
+system_mail($email, $nickname);
+ }
+
+
+ /**
+ * @param $email
+ * @param $nickname
+ */
+ protected function system_mail($email, $nickname)
+ {
+ try {
+ $mail = new PHPMailer(true);
+ //Server settings
+ $mail->SMTPDebug = SMTP::DEBUG_SERVER; // Enable verbose debug output
+ $mail->isSMTP(); // Send using SMTP
+ $mail->Host = 'smtp1.example.com'; // Set the SMTP server to send through
+ $mail->SMTPAuth = true; // Enable SMTP authentication
+ $mail->Username = 'user@example.com'; // SMTP username
+ $mail->Password = 'secret'; // SMTP password
+ $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // Enable TLS encryption; `PHPMailer::ENCRYPTION_SMTPS` encouraged
+ $mail->Port = 587; // TCP port to connect to, use 465 for `PHPMailer::ENCRYPTION_SMTPS` above
+
+ //Recipients
+ $mail->setFrom('system@example.com', '系统管理员');
+ $mail->addAddress($email, $nickname); // Add a recipient
+
+ // Attachments
+// $mail->addAttachment('/var/tmp/file.tar.gz'); // Add attachments
+// $mail->addAttachment('/tmp/image.jpg', 'new.jpg'); // Optional name
+
+ // Content
+ $mail->isHTML(true); // Set email format to HTML
+ $mail->Subject = 'Here is the subject';
+ $mail->Body = 'This is the HTML message body in bold!';
+ $mail->AltBody = 'This is the body in plain text for non-HTML mail clients';
+
+ $mail->send();
+ echo 'Message has been sent';
+ } catch (Exception $e) {
+ echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";
+ }
+ }
+
+
+}
diff --git a/http-server/Events/Trigger/OnStart.php b/http-server/Events/OnStart.php
similarity index 86%
rename from http-server/Events/Trigger/OnStart.php
rename to http-server/Events/OnStart.php
index eeabb94d..c25bab9b 100644
--- a/http-server/Events/Trigger/OnStart.php
+++ b/http-server/Events/OnStart.php
@@ -1,10 +1,10 @@
event;
$event->trigger(Event::RELEASE_ALL);
-
- $this->endCoroutine();
Timer::clearAll();
}
return $finish;
diff --git a/http-server/Events/Trigger/OnWorkerError.php b/http-server/Events/OnWorkerError.php
similarity index 77%
rename from http-server/Events/Trigger/OnWorkerError.php
rename to http-server/Events/OnWorkerError.php
index 93cb8e5e..e9ef9f1c 100644
--- a/http-server/Events/Trigger/OnWorkerError.php
+++ b/http-server/Events/OnWorkerError.php
@@ -1,10 +1,10 @@
worker_pid);
$get_name = $this->get_process_name($server, $worker_id);
@@ -69,7 +67,7 @@ class OnWorkerStart extends Callback
}
$event->trigger(Event::SERVER_WORKER_START);
} catch (\Throwable $exception) {
- Logger::write($exception->getMessage(), 'worker');
+ Snowflake::get()->getLogger()->write($exception->getMessage(), 'worker');
}
}
diff --git a/http-server/Events/Trigger/OnWorkerStop.php b/http-server/Events/OnWorkerStop.php
similarity index 76%
rename from http-server/Events/Trigger/OnWorkerStop.php
rename to http-server/Events/OnWorkerStop.php
index 96c94901..7eb531c2 100644
--- a/http-server/Events/Trigger/OnWorkerStop.php
+++ b/http-server/Events/OnWorkerStop.php
@@ -1,10 +1,10 @@
set($host . ':' . $port, $this);
- $this->application = $application;
- parent::__construct($host, $port, $mode, $sock_type);
- }
-
-
- /**
- * @param array $settings
- * @param null $pool
- * @param array $events
- * @param array $config
- * @return mixed|void
- * @throws NotFindClassException
- * @throws ReflectionException
- * @throws Exception
- */
- public function set(array $settings, $pool = null, $events = [], $config = [])
- {
- parent::set($settings);
- ServerManager::set($this, $settings, $this->application, $events, $config);
- }
-
-
- /**
- * @param $callbacks
- */
- protected function bindCallback($callbacks)
- {
- if (empty($callbacks) || !is_array($callbacks)) {
- return;
- }
- foreach ($callbacks as $callback) {
- $this->on($callback[0], [$this, $callback[1][1]]);
- }
- }
-
-
- /**
- * @param $eventName
- * @return array
- * @throws NotFindClassException
- * @throws ReflectionException
- * @throws Exception
- */
- protected function createHandler($eventName)
- {
- $classPrefix = 'HttpServer\Events\Trigger\On' . ucfirst($eventName);
- if (!class_exists($classPrefix)) {
- throw new Exception('class not found.');
- }
- $class = Snowflake::createObject($classPrefix, [Snowflake::get()]);
- return [$class, 'onHandler'];
- }
-
-
- /**
- * @param $data
- * @return mixed
- * @throws Exception
- */
- public function pack($data)
- {
- $callback = $this->pack;
- if (is_callable($callback, true)) {
- return $callback($data);
- }
- return JSON::encode($data);
- }
-
-
- /**
- * @param $data
- * @return mixed
- */
- public function unpack($data)
- {
- $callback = $this->unpack;
- if (is_callable($callback, true)) {
- return $callback($data);
- }
- return JSON::decode($data);
- }
-
-}
diff --git a/http-server/Events/Trigger/OnClose.php b/http-server/Events/Trigger/OnClose.php
deleted file mode 100644
index 49378a49..00000000
--- a/http-server/Events/Trigger/OnClose.php
+++ /dev/null
@@ -1,17 +0,0 @@
-set(WebSocket::class, $this);
- $this->application = $application;
- parent::__construct($host, $port, $mode, $sock_type);
- }
-
-
- /**
- * @param array $settings
- * @param null $pool
- * @param array $events
- * @param array $config
- * @return mixed|void
- * @throws NotFindClassException
- * @throws ReflectionException
- * @throws Exception
- */
- public function set(array $settings, $pool = null, $events = [], $config = [])
- {
- parent::set($settings);
-
- ServerManager::set($this, $settings, $this->application, $events, $config);
- }
-
-
- /**
- * @param Server $server
- * @param Frame $frame
- * @throws
- */
- public function onMessage(Server $server, Frame $frame)
- {
- try {
- if ($frame->opcode == 0x08) {
- return;
- }
-
- $event = Snowflake::get()->event;
- if ($event->exists(Event::SERVER_MESSAGE)) {
- $event->trigger(Event::SERVER_MESSAGE, [$server, $frame]);
- } else {
- $frame->data = json_decode($frame->data, true);
- }
-
- /** @var AWebsocket $manager */
- $manager = Snowflake::get()->annotation->get('websocket');
- $manager->runWith($manager->getName(AWebsocket::MESSAGE, [null, null, $frame->data['route']]), [$frame, $server]);
- } catch (Exception $exception) {
- $this->application->addError($exception->getMessage(), 'websocket');
- $server->send($frame->fd, $exception->getMessage());
- } finally {
- $event = Snowflake::get()->event;
- $event->trigger(Event::EVENT_AFTER_REQUEST);
- Logger::insert();
- }
- }
-
- /**
- * @param SRequest $request
- * @param SResponse $response
- * @return bool
- * @throws Exception
- */
- protected function connect($request, $response)
- {
- /** @var AWebsocket $manager */
- $manager = Snowflake::get()->annotation->get('websocket');
- $manager->runWith($manager->getName(AWebsocket::HANDSHAKE), [$request, $response]);
- return true;
- }
-
- /**
- * @param SRequest $request
- * @param SResponse $response
- * @return bool|string
- * @throws Exception
- */
- public function onHandshake(SRequest $request, SResponse $response)
- {
- /** @var Server $server */
- $secWebSocketKey = $request->header['sec-websocket-key'];
- $patten = '#^[+/0-9A-Za-z]{21}[AQgw]==$#';
- if (0 === preg_match($patten, $secWebSocketKey) || 16 !== strlen(base64_decode($secWebSocketKey))) {
- return false;
- }
- $key = base64_encode(sha1(
- $request->header['sec-websocket-key'] . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11',
- TRUE
- ));
- $headers = [
- 'Upgrade' => 'websocket',
- 'Connection' => 'Upgrade',
- 'Sec-websocket-Accept' => $key,
- 'Sec-websocket-Version' => '13',
- ];
- if (isset($request->header['sec-websocket-protocol'])) {
- $headers['Sec-websocket-Protocol'] = $request->header['sec-websocket-protocol'];
- }
- foreach ($headers as $key => $val) {
- $response->header($key, $val);
- }
- return $this->connect($request, $response);
- }
-
- /**
- * @param Server $server
- * @param int $fd
- * @throws Exception
- */
- public function onClose(Server $server, int $fd)
- {
- try {
- /** @var AWebsocket $manager */
- $manager = Snowflake::get()->annotation->get('websocket');
- $manager->runWith($manager->getName(AWebsocket::CLOSE), [$fd]);
- } catch (\Throwable $exception) {
- $this->application->addError($exception->getMessage());
- } finally {
- $event = Snowflake::get()->event;
- $event->trigger(Event::RELEASE_ALL);
- Logger::insert();
- }
- }
-
-}
diff --git a/http-server/IInterface/Service.php b/http-server/IInterface/Service.php
new file mode 100644
index 00000000..b883bd7f
--- /dev/null
+++ b/http-server/IInterface/Service.php
@@ -0,0 +1,13 @@
+ [SWOOLE_SOCK_TCP, WebSocket::class],
];
+ /** @var Http|WebSocket|Packet|Receive */
+ private $baseServer;
+
+
/**
* @param array $configs
- * @return array
+ * @return Http|Packet|Receive|WebSocket
* @throws Exception
*/
public function initCore(array $configs)
{
- $response = [];
+ $configs = $this->sortServers($configs);
foreach ($configs as $server) {
- $response[] = $this->create($server);
+ $this->create($server);
}
- return $response;
+ $this->onProcessListener();
+ return $this->getServer();
+ }
+
+
+ /**
+ * @throws ReflectionException
+ * @throws ConfigException
+ * @throws NotFindClassException
+ * @throws Exception
+ */
+ public function onProcessListener()
+ {
+ $processes = Config::get('processes');
+ if (empty($processes) || !is_array($processes)) {
+ return;
+ }
+
+ $application = Snowflake::get();
+ foreach ($processes as $name => $process) {
+ $class = Snowflake::createObject($process);
+
+ if (!method_exists($class, 'onHandler')) {
+ continue;
+ }
+
+ $system = new Process([$class, 'onHandler'], false, null, true);
+ if (Snowflake::isLinux()) {
+ $system->name($name);
+ }
+ $this->baseServer->addProcess($system);
+ $application->set($name, $process);
+ }
+ }
+
+
+ /**
+ * @return Http|WebSocket|Packet|Receive
+ */
+ public function getServer()
+ {
+ return $this->baseServer;
}
@@ -74,6 +129,7 @@ class Server extends Application
/**
* @param $config
+ * @throws Exception
*/
protected function createEventListen($config)
{
@@ -94,33 +150,83 @@ class Server extends Application
*/
private function dispatchCreate($config, $settings)
{
- switch ($config['type']) {
- case self::HTTP:
- $handler = [
- ['request', [Http::class, 'onHandler']]
- ];
- break;
- case self::TCP:
- $handler = [
- ['receive', [Receive::class, 'onReceive']]
- ];
- break;
- case self::PACKAGE:
- $handler = [
- ['packet', [Packet::class, 'onHandler']]
- ];
- break;
- case self::WEBSOCKET:
- $handler = [
- ['handshake', [WebSocket::class, 'onHandshake']],
- ['message', [WebSocket::class, 'onMessage']],
- ['close', [WebSocket::class, 'onClose']],
- ];
- break;
- default:
- throw new Exception('Unknown server type(' . $config['type'] . ').');
+ if (!($this->baseServer instanceof \Swoole\Server)) {
+ $this->baseServer = new ($this->dispatch($config['type']))();
+ $this->baseServer->set($settings);
+ } else {
+ $newListener = $this->baseServer->addlistener($config['host'], $config['port'], SWOOLE_TCP);
+ if (!empty($settings)) {
+ $newListener->set($settings);
+ }
+ $this->onListenerBind($config, $newListener);
}
- return [$this->server[$config['type']], $config, $handler, $settings];
+ return $this->baseServer;
+ }
+
+
+ /**
+ * @param $config
+ * @param $newListener
+ * @throws Exception
+ */
+ private function onListenerBind($config, $newListener)
+ {
+ if ($config['type'] == self::HTTP) {
+ $newListener->on('request', [OnRequest::class, 'onHandler']);
+ } else if ($config['type'] == self::TCP || $config['type'] == self::PACKAGE) {
+ $newListener->on('connect', [OnConnect::class, 'onHandler']);
+ $newListener->on('close', [OnClose::class, 'onHandler']);
+ if ($config['type'] == self::PACKAGE) {
+ $newListener->on('packet', [OnPacket::class, 'onHandler']);
+ } else {
+ $newListener->on('receive', [OnReceive::class, 'onHandler']);
+ }
+ $newListener->on('connect', [OnConnect::class, 'onHandler']);
+ $newListener->on('close', [OnClose::class, 'onHandler']);
+ } else if ($config['type'] == self::WEBSOCKET) {
+ throw new Exception('Base server must instanceof \Swoole\WebSocket\Server::class.');
+ } else {
+ throw new Exception('Unknown server type(' . $config['type'] . ').');
+ }
+ }
+
+
+ /**
+ * @param $type
+ * @return string
+ */
+ private function dispatch($type)
+ {
+ $default = [
+ self::HTTP => \Swoole\Http\Server::class,
+ self::WEBSOCKET => \Swoole\WebSocket\Server::class,
+ self::TCP => \Swoole\Server::class,
+ self::PACKAGE => \Swoole\Server::class
+ ];
+ return $default[$type] ?? \Swoole\Server::class;
+ }
+
+ /**
+ * @param $servers
+ * @return array
+ */
+ private function sortServers($servers)
+ {
+ $array = [];
+ foreach ($servers as $server) {
+ switch ($server['type']) {
+ case self::WEBSOCKET:
+ array_unshift($array, $server);
+ break;
+ case self::HTTP:
+ case self::PACKAGE | self::TCP:
+ $array[] = $server;
+ break;
+ default:
+ $array[] = $server;
+ }
+ }
+ return $array;
}
diff --git a/http-server/ServerManager.php b/http-server/ServerManager.php
deleted file mode 100644
index 4c666da6..00000000
--- a/http-server/ServerManager.php
+++ /dev/null
@@ -1,191 +0,0 @@
-set($settings ?? [], $pool, $handlers, $config);
- static::notice($application, $workerId, $config);
- if (property_exists($server, 'pack')) {
- $server->pack = $config['message']['pack'] ?? function ($data) {
- return $data;
- };
- }
- if (property_exists($server, 'unpack')) {
- $server->unpack = $config['message']['unpack'] ?? function ($data) {
- return $data;
- };
- }
- return $server->start();
- } catch (Exception $exception) {
- echo $exception->getMessage() . PHP_EOL;
- return $pool->shutdown();
- }
- }
-
-
- /**
- * @param $application
- * @param $config
- * @param $category
- * @return array
- */
- protected static function parameter($application, $config, $category)
- {
- return [$application, $config['host'], $config['port'], SWOOLE_PROCESS, $category[0]];
- }
-
-
- /**
- * @param $process
- * @param $application
- * @param $pool
- * @param $workerId
- * @return mixed
- */
- protected static function createProcess($process, $application, $pool, $workerId)
- {
- $process = new $process($application);
- $application->debug(sprintf('Worker #%d is running.', $workerId));
- return $process->start();
- }
-
-
- /**
- * @param $application
- * @param $workerId
- * @param $config
- */
- protected static function notice($application, $workerId, $config)
- {
- $application->debug(sprintf('Worker #%d Listener %s::%d is running.', $workerId, $config['host'], $config['port']));
- }
-
- /**
- * @param $server
- * @param $settings
- * @param \Snowflake\Application $application
- * @param array $events
- * @param array $config
- * @return mixed|void
- * @throws NotFindClassException
- * @throws ReflectionException
- */
- public static function set($server, $settings, $application, $events = [], $config = [])
- {
- $server->on('start', static::createHandler('start'));
- $server->on('shutdown', static::createHandler('shutdown'));
- $server->on('workerStop', static::createHandler('workerStop'));
- $server->on('workerExit', static::createHandler('workerExit'));
- $server->on('workerStart', static::createHandler('workerStart'));
- $server->on('workerError', static::createHandler('workerError'));
- $server->on('managerStop', static::createHandler('managerStop'));
- $server->on('managerStart', static::createHandler('managerStart'));
- static::addListener($server, $application, $config);
- static::bindCallback($server, $events);
- static::addTask($server, $settings);
- }
-
-
- /**
- * @param $server
- * @param $settings
- * @throws NotFindClassException
- * @throws ReflectionException
- */
- protected static function addTask($server, $settings)
- {
- if (($taskNumber = $settings['task_worker_num'] ?? 0) > 0) {
- $server->on('finish', static::createHandler('finish'));
- $callback = static::createHandler('task');
- if ($settings['task_enable_coroutine'] ?? false) {
- $server->on('task', [$callback, 'onContinueTask']);
- } else {
- $server->on('task', [$callback, 'onTask']);
- }
- }
- }
-
-
- /**
- * @param $server
- * @param $application
- * @param $config
- * @return void
- */
- protected static function addListener($server, $application, $config)
- {
- $grpc = $config['grpc'] ?? [];
- if (empty($grpc) || !is_array($grpc)) {
- return;
- }
- $listener = $server->addListener($grpc['host'], $grpc['port'], $grpc['mode']);
- $listener->set($grpc['settings'] ?? []);
- if (!isset($grpc['receive'])) {
- $application->error(sprintf('must add listener %s::%s callback', $grpc['host'], $grpc['port']));
- return;
- }
- if ($grpc['receive'] instanceof \Closure) {
- $grpc['receive'] = \Closure::bind($grpc['receive'], $server);
- }
- $listener->on('receive', $grpc['receive']);
- }
-
-
- /**
- * @param $server
- * @param $callbacks
- */
- protected static function bindCallback($server, $callbacks)
- {
- if (empty($callbacks) || !is_array($callbacks)) {
- return;
- }
- foreach ($callbacks as $callback) {
- $server->on($callback[0], [$server, $callback[1][1]]);
- }
- }
-
-
- /**
- * @param $eventName
- * @return array
- * @throws NotFindClassException
- * @throws ReflectionException
- * @throws Exception
- */
- protected static function createHandler($eventName)
- {
- $classPrefix = 'HttpServer\Events\Trigger\On' . ucfirst($eventName);
- if (!class_exists($classPrefix)) {
- throw new Exception('class not found.');
- }
- $class = Snowflake::createObject($classPrefix, [Snowflake::get()]);
- return [$class, 'onHandler'];
- }
-
-}
diff --git a/http-server/Service/Abstracts/Http.php b/http-server/Service/Abstracts/Http.php
new file mode 100644
index 00000000..993d5b97
--- /dev/null
+++ b/http-server/Service/Abstracts/Http.php
@@ -0,0 +1,17 @@
+application = Snowflake::get();
+ parent::__construct($host, $port, $mode, $sock_type);
+ }
+
+
+ /**
+ * @param array $settings
+ * @return mixed|void
+ */
+ public function set(array $settings)
+ {
+ parent::set($settings); // TODO: Change the autogenerated stub
+ $this->onInit();
+ }
+
+
+ /**
+ * @return mixed|void
+ * @throws NotFindClassException
+ * @throws ReflectionException
+ */
+ public function onHandlerListener()
+ {
+ $this->on('start', $this->createHandler('start'));
+ $this->on('shutdown', $this->createHandler('shutdown'));
+ $this->on('workerStop', $this->createHandler('workerStop'));
+ $this->on('workerExit', $this->createHandler('workerExit'));
+ $this->on('workerStart', $this->createHandler('workerStart'));
+ $this->on('workerError', $this->createHandler('workerError'));
+ $this->on('managerStop', $this->createHandler('managerStop'));
+ $this->on('managerStart', $this->createHandler('managerStart'));
+ $this->addTask();
+ }
+
+
+ /**
+ * @throws NotFindClassException
+ * @throws ReflectionException
+ */
+ protected function addTask()
+ {
+ $settings = $this->setting;
+ if (($taskNumber = $settings['task_worker_num'] ?? 0) > 0) {
+ $this->on('finish', $this->createHandler('finish'));
+ $callback = $this->createHandler('task');
+ if ($settings['task_enable_coroutine'] ?? false) {
+ $this->on('task', [$callback, 'onContinueTask']);
+ } else {
+ $this->on('task', [$callback, 'onTask']);
+ }
+ }
+ }
+
+
+ /**
+ * @param $eventName
+ * @return array
+ * @throws NotFindClassException
+ * @throws ReflectionException
+ * @throws Exception
+ */
+ protected function createHandler($eventName)
+ {
+ $classPrefix = 'HttpServer\Events\On' . ucfirst($eventName);
+ if (!class_exists($classPrefix)) {
+ throw new Exception('class not found.');
+ }
+ $class = Snowflake::createObject($classPrefix, [Snowflake::get()]);
+ return [$class, 'onHandler'];
+ }
+
+
+}
diff --git a/http-server/Service/Abstracts/Tcp.php b/http-server/Service/Abstracts/Tcp.php
new file mode 100644
index 00000000..0b2de150
--- /dev/null
+++ b/http-server/Service/Abstracts/Tcp.php
@@ -0,0 +1,24 @@
+onHandlerListener();
+ $this->onBaseListener();
+ }
+
+
+ /**
+ * @throws NotFindClassException
+ * @throws ReflectionException
+ */
+ public function onBaseListener()
+ {
+ $this->on('request', $this->createHandler('request'));
+ }
+
+
+}
diff --git a/http-server/Service/Packet.php b/http-server/Service/Packet.php
new file mode 100644
index 00000000..616064db
--- /dev/null
+++ b/http-server/Service/Packet.php
@@ -0,0 +1,46 @@
+onHandlerListener();
+ $this->onBaseListener();
+ }
+
+
+ /**
+ * @throws NotFindClassException
+ * @throws ReflectionException
+ */
+ public function onBaseListener()
+ {
+ $this->on('connect', $this->createHandler('connect'));
+ $this->on('packet', $this->createHandler('packet'));
+ $this->on('close', $this->createHandler('close'));
+ }
+
+
+}
diff --git a/http-server/Service/Receive.php b/http-server/Service/Receive.php
new file mode 100644
index 00000000..4185627a
--- /dev/null
+++ b/http-server/Service/Receive.php
@@ -0,0 +1,46 @@
+onHandlerListener();
+ $this->onBaseListener();
+ }
+
+
+ /**
+ * @throws NotFindClassException
+ * @throws ReflectionException
+ */
+ public function onBaseListener()
+ {
+ $this->on('connect', $this->createHandler('connect'));
+ $this->on('receive', $this->createHandler('receive'));
+ $this->on('close', $this->createHandler('close'));
+ }
+
+
+}
diff --git a/http-server/Service/Websocket.php b/http-server/Service/Websocket.php
new file mode 100644
index 00000000..fc6018b2
--- /dev/null
+++ b/http-server/Service/Websocket.php
@@ -0,0 +1,45 @@
+onHandlerListener();
+ $this->onBaseListener();
+ }
+
+
+ /**
+ * @throws NotFindClassException
+ * @throws ReflectionException
+ */
+ public function onBaseListener()
+ {
+ $this->on('handshake', $this->createHandler('handshake'));
+ $this->on('message', $this->createHandler('message'));
+ $this->on('close', $this->createHandler('close'));
+ }
+
+}
diff --git a/http-server/config.php b/http-server/config.php
index 04a003a0..e0f0c5ab 100644
--- a/http-server/config.php
+++ b/http-server/config.php
@@ -78,19 +78,6 @@ return [
'worker_num' => 10,
'enable_coroutine' => 1
],
- 'grpc' => [
- 'host' => '127.0.0.1',
- 'port' => 5555,
- 'mode' => SWOOLE_SOCK_TCP,
- 'receive' => function ($server, int $fd, int $reactorId, string $data) {
- $server->push(1, 'success.');
- $server->send($fd, 'success.');
-
- $socket = Snowflake::get()->get(\HttpServer\Events\WebSocket::class);
- $socket->push(1, 'hello word~~~~~~~~~~~~~');
- },
- 'settings' => []
- ],
'events' => [
Event::SERVER_WORKER_START => function () {
$path = APP_PATH . 'app/Websocket';
diff --git a/system/Abstracts/BaseApplication.php b/system/Abstracts/BaseApplication.php
index 51b6f711..4fca5e95 100644
--- a/system/Abstracts/BaseApplication.php
+++ b/system/Abstracts/BaseApplication.php
@@ -307,7 +307,6 @@ abstract class BaseApplication extends Service
}
-
/**
* @return Router
* @throws ComponentException
@@ -348,6 +347,7 @@ abstract class BaseApplication extends Service
'router' => ['class' => Router::class],
'redis' => ['class' => Redis::class],
'jwt' => ['class' => Jwt::class],
+ 'server' => ['class' => Server::class],
]);
}
}
diff --git a/system/Abstracts/BaseObject.php b/system/Abstracts/BaseObject.php
index 6c02c312..7135588c 100644
--- a/system/Abstracts/BaseObject.php
+++ b/system/Abstracts/BaseObject.php
@@ -134,7 +134,6 @@ class BaseObject implements Configure
}
echo "\033[35m[DEBUG][" . date('Y-m-d H:i:s') . ']: ' . $message . "\033[0m";
echo PHP_EOL;
- Logger::trance($message, 'debug');
}
@@ -151,7 +150,6 @@ class BaseObject implements Configure
}
echo "\033[34m[INFO][" . date('Y-m-d H:i:s') . ']: ' . $message . "\033[0m";
echo PHP_EOL;
- Logger::trance($message, 'info');
}
/**
@@ -167,7 +165,6 @@ class BaseObject implements Configure
}
echo "\033[36m[SUCCESS][" . date('Y-m-d H:i:s') . ']: ' . $message . "\033[0m";
echo PHP_EOL;
- Logger::trance($message, 'success');
}
@@ -184,7 +181,6 @@ class BaseObject implements Configure
}
echo "\033[33m[SUCCESS][" . date('Y-m-d H:i:s') . ']: ' . $message . "\033[0m";
echo PHP_EOL;
- Logger::trance($message, 'warning');
}
@@ -194,7 +190,7 @@ class BaseObject implements Configure
* @param string|null $file
* @throws Exception
*/
- public function error($message, string $method = null, string $file = null)
+ public function error($message, $method = null, $file = null)
{
if (!empty($file)) {
echo "\033[41;37m[ERROR][" . date('Y-m-d H:i:s') . ']: ' . $file . "\033[0m";
@@ -205,7 +201,6 @@ class BaseObject implements Configure
}
echo "\033[41;37m[ERROR][" . date('Y-m-d H:i:s') . ']: ' . (empty($method) ? '' : $method . ': ') . $message . "\033[0m";
echo PHP_EOL;
- Logger::error($message, 'error');
}
}
diff --git a/system/Application.php b/system/Application.php
index 0f53e5b8..99662926 100644
--- a/system/Application.php
+++ b/system/Application.php
@@ -34,16 +34,12 @@ class Application extends BaseApplication
*/
public function init()
{
+ /** @var Server $https */
+ $https = $this->make(Server::class, Server::class);
+ $https->initCore(Config::get('servers', true));
+
$process = Snowflake::get()->processes;
- if (Config::has('servers', true)) {
- /** @var Server $https */
- $https = $this->make(Server::class, Server::class);
- $servers = $https->initCore(Config::get('servers'));
- $process->push($servers);
- }
- if (Config::has('processes', true)) {
- $process->push(Config::get('processes'));
- }
+ $process->initCore();
}
diff --git a/system/Error/ErrorHandler.php b/system/Error/ErrorHandler.php
index d29a2ca3..b1a77d4b 100644
--- a/system/Error/ErrorHandler.php
+++ b/system/Error/ErrorHandler.php
@@ -101,7 +101,7 @@ class ErrorHandler extends Component implements ErrorInterface
$data = JSON::to(500, 'Error : ' . $error[1], $path);
- Logger::error($data, 'error');
+ Snowflake::get()->getLogger()->error($data, 'error');
$event = Snowflake::get()->event;
$event->trigger(Event::RELEASE_ALL);
@@ -123,7 +123,7 @@ class ErrorHandler extends Component implements ErrorInterface
$data = JSON::to($code, $this->category . ': ' . $message, $path);
- Logger::trance($data, $this->category);
+ Snowflake::get()->getLogger()->trance($data, $this->category);
return response()->send($data);
}
@@ -154,6 +154,6 @@ class ErrorHandler extends Component implements ErrorInterface
*/
public function writer($message, $category = 'app')
{
- Logger::debug($message, $category);
+ Snowflake::get()->getLogger()->debug($message, $category);
}
}
diff --git a/system/Error/Logger.php b/system/Error/Logger.php
index 3da4d1ea..fdc09e4f 100644
--- a/system/Error/Logger.php
+++ b/system/Error/Logger.php
@@ -9,6 +9,7 @@
namespace Snowflake\Error;
use Exception;
+use Snowflake\Abstracts\Component;
use Snowflake\Core\JSON;
use Snowflake\Snowflake;
use Swoole\Process;
@@ -17,21 +18,23 @@ use Swoole\Process;
* Class Logger
* @package Snowflake\Snowflake\Error
*/
-class Logger
+class Logger extends Component
{
- private static $logs = [];
+ private $logs = [];
- public static $worker_id;
+ public $worker_id;
/**
* @param $message
* @param string $category
+ * @param null $_
* @throws Exception
*/
- public static function debug($message, $category = 'app')
+ public function debug($message, $category = 'app', $_ = null)
{
- static::writer($message, $category);
+ parent::debug($message);
+ $this->writer($message, $category);
}
@@ -40,30 +43,34 @@ class Logger
* @param string $category
* @throws Exception
*/
- public static function trance($message, $category = 'app')
+ public function trance($message, $category = 'app')
{
- static::writer($message, $category);
+ $this->writer($message, $category);
}
/**
* @param $message
* @param string $category
+ * @param null $_
* @throws Exception
*/
- public static function error($message, $category = 'app')
+ public function error($message, $category = 'error', $_ = null)
{
- static::writer($message, $category);
+ parent::error($message);
+ $this->writer($message, $category);
}
/**
* @param $message
* @param string $category
+ * @param null $_
* @throws Exception
*/
- public static function success($message, $category = 'app')
+ public function success($message, $category = 'app', $_ = null)
{
- static::writer($message, $category);
+ parent::success($message);
+ $this->writer($message, $category);
}
/**
@@ -72,23 +79,23 @@ class Logger
* @return string
* @throws Exception
*/
- private static function writer($message, $category = 'app')
+ private function writer($message, $category = 'app')
{
if ($message instanceof \Throwable) {
$message = $message->getMessage();
} else {
if (is_array($message) || is_object($message)) {
- $message = static::arrayFormat($message);
+ $message = $this->arrayFormat($message);
}
}
if (is_array($message)) {
- $message = static::arrayFormat($message);
+ $message = $this->arrayFormat($message);
}
if (!empty($message)) {
- if (!is_array(static::$logs)) {
- static::$logs = [];
+ if (!is_array($this->$logs)) {
+ $this->$logs = [];
}
- static::$logs[] = [$category, $message];
+ $this->$logs[] = [$category, $message];
}
return $message;
}
@@ -99,7 +106,7 @@ class Logger
* @param $category
* @throws Exception
*/
- public static function print_r($message, $category = '')
+ public function print_r($message, $category = '')
{
/** @var Process $logger */
$logger = Snowflake::get()->logger;
@@ -111,10 +118,10 @@ class Logger
* @param string $application
* @return mixed
*/
- public static function getLastError($application = 'app')
+ public function getLastError($application = 'app')
{
$_tmp = [];
- foreach (static::$logs as $key => $val) {
+ foreach ($this->logs as $key => $val) {
if ($val[0] != $application) {
continue;
}
@@ -131,7 +138,7 @@ class Logger
* @param string $category
* @throws Exception
*/
- public static function write(string $messages, $category = 'app')
+ public function write(string $messages, $category = 'app')
{
if (empty($messages)) {
return;
@@ -146,7 +153,7 @@ class Logger
* @param $logFile
* @return false|string
*/
- private static function getSource($logFile)
+ private function getSource($logFile)
{
if (!file_exists($logFile)) {
shell_exec('echo 3 > /proc/sys/vm/drop_caches');
@@ -162,37 +169,37 @@ class Logger
* @throws Exception
* 写入日志
*/
- public static function insert()
+ public function insert()
{
- if (empty(static::$logs)) {
+ if (empty($this->logs)) {
return;
}
- foreach (static::$logs as $log) {
+ foreach ($this->logs as $log) {
[$category, $message] = $log;
- static::write($message, $category);
+ $this->write($message, $category);
}
- static::$logs = [];
+ $this->logs = [];
}
/**
* @return array
*/
- public static function clear()
+ public function clear()
{
- return static::$logs = [];
+ return $this->logs = [];
}
/**
* @param $data
* @return string
*/
- private static function arrayFormat($data)
+ private function arrayFormat($data)
{
if (is_string($data)) {
return $data;
}
if ($data instanceof Exception) {
- $data = static::getException($data);
+ $data = $this->getException($data);
} else if (is_object($data)) {
$data = get_object_vars($data);
}
@@ -200,7 +207,7 @@ class Logger
$_tmp = [];
foreach ($data as $key => $val) {
if (is_array($val)) {
- $_tmp[] = static::arrayFormat($val);
+ $_tmp[] = $this->arrayFormat($val);
} else {
$_tmp[] = (is_string($key) ? $key . ' : ' : '') . $val;
}
@@ -212,7 +219,7 @@ class Logger
* @param Exception $exception
* @return array
*/
- private static function getException($exception)
+ private function getException($exception)
{
$_tmp = [$exception->getMessage()];
$_tmp[] = $exception->getFile() . ' on line ' . $exception->getLine();
diff --git a/system/Processes.php b/system/Processes.php
index f5bc52d5..9be41f62 100644
--- a/system/Processes.php
+++ b/system/Processes.php
@@ -5,7 +5,6 @@ namespace Snowflake;
use Exception;
-use HttpServer\ServerManager;
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use Snowflake\Abstracts\Component;
@@ -27,75 +26,11 @@ class Processes extends Component
*/
public function initCore()
{
- $application = Snowflake::get();
- $server = $application->set(Pool::class, new Pool($this->size(), SWOOLE_IPC_UNIXSOCK));
- $server->on('workerStart', function (Pool $pool, int $workerId) use ($application) {
- ServerManager::create($pool, $this->processes[$workerId], $workerId);
- });
- $server->on('workerStop', function (Pool $pool, int $workerId) {
- $event = Snowflake::get()->event;
- if ($event->exists(Event::PROCESS_WORKER_STOP)) {
- $event->trigger(Event::PROCESS_WORKER_STOP);
- }
+ $manager = Snowflake::get()->servers;
- $email = Config::get('admin.email');
- if (!empty($email)) {
- $nickname = Config::get('admin.name', false, '亲爱的开发者');
- $this->system_mail($email, $nickname);
- }
- });
- $server->on('message', function (Pool $pool, $message) {
- file_put_contents(storage('a.log'), $message);
- });
- return $server;
- }
+ $serverConfig = Config::get('servers', true);
-
- /**
- * @param $email
- * @param $nickname
- */
- protected function system_mail($email, $nickname)
- {
- try {
- $mail = new PHPMailer(true);
- //Server settings
- $mail->SMTPDebug = SMTP::DEBUG_SERVER; // Enable verbose debug output
- $mail->isSMTP(); // Send using SMTP
- $mail->Host = 'smtp1.example.com'; // Set the SMTP server to send through
- $mail->SMTPAuth = true; // Enable SMTP authentication
- $mail->Username = 'user@example.com'; // SMTP username
- $mail->Password = 'secret'; // SMTP password
- $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // Enable TLS encryption; `PHPMailer::ENCRYPTION_SMTPS` encouraged
- $mail->Port = 587; // TCP port to connect to, use 465 for `PHPMailer::ENCRYPTION_SMTPS` above
-
- //Recipients
- $mail->setFrom('system@example.com', '系统管理员');
- $mail->addAddress($email, $nickname); // Add a recipient
-
- // Attachments
-// $mail->addAttachment('/var/tmp/file.tar.gz'); // Add attachments
-// $mail->addAttachment('/tmp/image.jpg', 'new.jpg'); // Optional name
-
- // Content
- $mail->isHTML(true); // Set email format to HTML
- $mail->Subject = 'Here is the subject';
- $mail->Body = 'This is the HTML message body in bold!';
- $mail->AltBody = 'This is the body in plain text for non-HTML mail clients';
-
- $mail->send();
- echo 'Message has been sent';
- } catch (Exception $e) {
- echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";
- }
- }
-
- /**
- * @return int
- */
- protected function size()
- {
- return count($this->processes);
+ return $manager->initCore($serverConfig);
}
@@ -107,17 +42,4 @@ class Processes extends Component
$server = $this->initCore();
$server->start();
}
-
-
- /**
- * @param array $servers
- * @return $this
- */
- public function push(array $servers)
- {
- foreach ($servers as $server) {
- $this->processes[] = $server;
- }
- return $this;
- }
}