初始化代码
This commit is contained in:
255
vendor/topthink/think-swoole/src/Sandbox.php
vendored
Normal file
255
vendor/topthink/think-swoole/src/Sandbox.php
vendored
Normal file
@@ -0,0 +1,255 @@
|
||||
<?php
|
||||
|
||||
namespace think\swoole;
|
||||
|
||||
use Closure;
|
||||
use RuntimeException;
|
||||
use Symfony\Component\VarDumper\VarDumper;
|
||||
use think\App;
|
||||
use think\Config;
|
||||
use think\Container;
|
||||
use think\Event;
|
||||
use think\Http;
|
||||
use think\service\PaginatorService;
|
||||
use think\swoole\contract\ResetterInterface;
|
||||
use think\swoole\coroutine\Context;
|
||||
use think\swoole\middleware\ResetVarDumper;
|
||||
use think\swoole\resetters\ClearInstances;
|
||||
use think\swoole\resetters\ResetConfig;
|
||||
use think\swoole\resetters\ResetEvent;
|
||||
use think\swoole\resetters\ResetService;
|
||||
use Throwable;
|
||||
|
||||
class Sandbox
|
||||
{
|
||||
/**
|
||||
* The app containers in different coroutine environment.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $snapshots = [];
|
||||
|
||||
/** @var Manager */
|
||||
protected $manager;
|
||||
|
||||
/** @var App */
|
||||
protected $app;
|
||||
|
||||
/** @var Config */
|
||||
protected $config;
|
||||
|
||||
/** @var Event */
|
||||
protected $event;
|
||||
|
||||
/** @var ResetterInterface[] */
|
||||
protected $resetters = [];
|
||||
protected $services = [];
|
||||
|
||||
public function __construct(Container $app, Manager $manager)
|
||||
{
|
||||
$this->manager = $manager;
|
||||
$this->setBaseApp($app);
|
||||
$this->initialize();
|
||||
}
|
||||
|
||||
public function setBaseApp(Container $app)
|
||||
{
|
||||
$this->app = $app;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getBaseApp()
|
||||
{
|
||||
return $this->app;
|
||||
}
|
||||
|
||||
protected function initialize()
|
||||
{
|
||||
Container::setInstance(function () {
|
||||
return $this->getApplication();
|
||||
});
|
||||
|
||||
$this->app->bind(Http::class, \think\swoole\Http::class);
|
||||
|
||||
$this->setInitialConfig();
|
||||
$this->setInitialServices();
|
||||
$this->setInitialEvent();
|
||||
$this->setInitialResetters();
|
||||
//兼容var-dumper
|
||||
$this->compatibleVarDumper();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function run(Closure $callable, $fd = null, $persistent = false)
|
||||
{
|
||||
$this->init($fd);
|
||||
|
||||
try {
|
||||
$this->getApplication()->invoke($callable, [$this]);
|
||||
} catch (Throwable $e) {
|
||||
$this->manager->logServerError($e);
|
||||
} finally {
|
||||
$this->clear(!$persistent);
|
||||
}
|
||||
}
|
||||
|
||||
public function init($fd = null)
|
||||
{
|
||||
if (!is_null($fd)) {
|
||||
Context::setData('_fd', $fd);
|
||||
}
|
||||
$this->setInstance($app = $this->getApplication());
|
||||
$this->resetApp($app);
|
||||
}
|
||||
|
||||
public function clear($snapshot = true)
|
||||
{
|
||||
if ($snapshot) {
|
||||
unset($this->snapshots[$this->getSnapshotId()]);
|
||||
}
|
||||
|
||||
Context::clear();
|
||||
$this->setInstance($this->getBaseApp());
|
||||
gc_collect_cycles();
|
||||
}
|
||||
|
||||
public function getApplication()
|
||||
{
|
||||
$snapshot = $this->getSnapshot();
|
||||
if ($snapshot instanceof Container) {
|
||||
return $snapshot;
|
||||
}
|
||||
|
||||
$snapshot = clone $this->getBaseApp();
|
||||
$this->setSnapshot($snapshot);
|
||||
|
||||
return $snapshot;
|
||||
}
|
||||
|
||||
protected function getSnapshotId()
|
||||
{
|
||||
if ($fd = Context::getData('_fd')) {
|
||||
return "fd_" . $fd;
|
||||
} else {
|
||||
return Context::getCoroutineId();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current snapshot.
|
||||
* @return App|null
|
||||
*/
|
||||
public function getSnapshot()
|
||||
{
|
||||
return $this->snapshots[$this->getSnapshotId()] ?? null;
|
||||
}
|
||||
|
||||
public function setSnapshot(Container $snapshot)
|
||||
{
|
||||
$this->snapshots[$this->getSnapshotId()] = $snapshot;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setInstance(Container $app)
|
||||
{
|
||||
$app->instance('app', $app);
|
||||
$app->instance(Container::class, $app);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set initial config.
|
||||
*/
|
||||
protected function setInitialConfig()
|
||||
{
|
||||
$this->config = clone $this->getBaseApp()->config;
|
||||
}
|
||||
|
||||
protected function setInitialEvent()
|
||||
{
|
||||
$this->event = clone $this->getBaseApp()->event;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get config snapshot.
|
||||
*/
|
||||
public function getConfig()
|
||||
{
|
||||
return $this->config;
|
||||
}
|
||||
|
||||
public function getEvent()
|
||||
{
|
||||
return $this->event;
|
||||
}
|
||||
|
||||
public function getServices()
|
||||
{
|
||||
return $this->services;
|
||||
}
|
||||
|
||||
protected function setInitialServices()
|
||||
{
|
||||
$app = $this->getBaseApp();
|
||||
|
||||
$services = [
|
||||
PaginatorService::class,
|
||||
];
|
||||
|
||||
$services = array_merge($services, $this->config->get('swoole.services', []));
|
||||
|
||||
foreach ($services as $service) {
|
||||
if (class_exists($service) && !in_array($service, $this->services)) {
|
||||
$serviceObj = new $service($app);
|
||||
$this->services[$service] = $serviceObj;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize resetters.
|
||||
*/
|
||||
protected function setInitialResetters()
|
||||
{
|
||||
$app = $this->getBaseApp();
|
||||
|
||||
$resetters = [
|
||||
ClearInstances::class,
|
||||
ResetConfig::class,
|
||||
ResetEvent::class,
|
||||
ResetService::class,
|
||||
];
|
||||
|
||||
$resetters = array_merge($resetters, $this->config->get('swoole.resetters', []));
|
||||
|
||||
foreach ($resetters as $resetter) {
|
||||
$resetterClass = $app->make($resetter);
|
||||
if (!$resetterClass instanceof ResetterInterface) {
|
||||
throw new RuntimeException("{$resetter} must implement " . ResetterInterface::class);
|
||||
}
|
||||
$this->resetters[$resetter] = $resetterClass;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset Application.
|
||||
*
|
||||
* @param Container $app
|
||||
*/
|
||||
protected function resetApp(Container $app)
|
||||
{
|
||||
foreach ($this->resetters as $resetter) {
|
||||
$resetter->handle($app, $this);
|
||||
}
|
||||
}
|
||||
|
||||
protected function compatibleVarDumper()
|
||||
{
|
||||
if (class_exists(VarDumper::class)) {
|
||||
$this->app->middleware->add(ResetVarDumper::class);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user