Queue support (#1773)

Implementation of clean queue handling, by default sync is used
This commit is contained in:
Daniël Klabbers 2019-08-19 21:44:06 +02:00 committed by Daniël Klabbers
parent 17dfb58590
commit 7f9588af62
6 changed files with 297 additions and 0 deletions

View File

@ -36,6 +36,8 @@
"illuminate/filesystem": "5.7.*",
"illuminate/hashing": "5.7.*",
"illuminate/mail": "5.7.*",
"illuminate/notifications": "5.7.*",
"illuminate/queue": "5.7.*",
"illuminate/session": "5.7.*",
"illuminate/support": "5.7.*",
"illuminate/validation": "5.7.*",

View File

@ -24,6 +24,7 @@ use Flarum\Locale\LocaleServiceProvider;
use Flarum\Mail\MailServiceProvider;
use Flarum\Notification\NotificationServiceProvider;
use Flarum\Post\PostServiceProvider;
use Flarum\Queue\QueueServiceProvider;
use Flarum\Search\SearchServiceProvider;
use Flarum\Settings\SettingsServiceProvider;
use Flarum\Update\UpdateServiceProvider;
@ -127,6 +128,7 @@ class InstalledSite implements SiteInterface
$laravel->register(MigrationServiceProvider::class);
$laravel->register(NotificationServiceProvider::class);
$laravel->register(PostServiceProvider::class);
$laravel->register(QueueServiceProvider::class);
$laravel->register(SearchServiceProvider::class);
$laravel->register(SessionServiceProvider::class);
$laravel->register(SettingsServiceProvider::class);
@ -178,6 +180,9 @@ class InstalledSite implements SiteInterface
]
]
],
'queue' => [
'default' => 'sync'
],
'session' => [
'lifetime' => 120,
'files' => $this->paths['storage'].'/sessions',

View File

@ -0,0 +1,64 @@
<?php
/*
* This file is part of Flarum.
*
* (c) Toby Zerner <toby.zerner@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Flarum\Queue;
use Exception;
use Illuminate\Contracts\Debug\ExceptionHandler as ExceptionHandling;
use Psr\Log\LoggerInterface;
class ExceptionHandler implements ExceptionHandling
{
/**
* @var LoggerInterface
*/
private $logger;
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}
/**
* Report or log an exception.
*
* @param \Exception $e
* @return void
*/
public function report(Exception $e)
{
$this->logger->error((string) $e);
}
/**
* Render an exception into an HTTP response.
*
* @param \Illuminate\Http\Request $request
* @param \Exception $e
* @return \Symfony\Component\HttpFoundation\Response
*/
public function render($request, Exception $e)
{
// TODO: Implement render() method.
}
/**
* Render an exception to the console.
*
* @param \Symfony\Component\Console\Output\OutputInterface $output
* @param \Exception $e
* @return void
*/
public function renderForConsole($output, Exception $e)
{
// TODO: Implement renderForConsole() method.
}
}

View File

@ -0,0 +1,63 @@
<?php
/*
* This file is part of Flarum.
*
* (c) Toby Zerner <toby.zerner@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Flarum\Queue;
use Illuminate\Contracts\Queue\Factory;
use Illuminate\Queue\QueueManager;
/**
* A hacky workaround to avoid injecting an entire QueueManager (which we don't
* want to build) into Laravel's queue worker class.
*
* Laravel 6.0 will clean this up; once we upgrade, we can remove this hack and
* directly inject the factory.
*/
class HackyManagerForWorker extends QueueManager implements Factory
{
/**
* @var Factory
*/
private $factory;
/**
* HackyManagerForWorker constructor.
*
* Needs a real connection factory to delegate to.
*
* @param Factory $factory
*/
public function __construct(Factory $factory)
{
$this->factory = $factory;
}
/**
* Resolve a queue connection instance.
*
* @param string $name
* @return \Illuminate\Contracts\Queue\Queue
*/
public function connection($name = null)
{
return $this->factory->connection($name);
}
/**
* Determine if the application is in maintenance mode.
*
* @return bool
*/
public function isDownForMaintenance()
{
return false;
}
}

View File

@ -0,0 +1,57 @@
<?php
/*
* This file is part of Flarum.
*
* (c) Toby Zerner <toby.zerner@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Flarum\Queue;
use Illuminate\Contracts\Queue\Factory;
class QueueFactory implements Factory
{
/**
* @var callable
*/
private $factory;
/**
* The cached queue instance.
*
* @var \Illuminate\Contracts\Queue\Queue
*/
private $queue;
/**
* QueueFactory constructor.
*
* Expects a callback that will be called to instantiate the queue adapter,
* once requested by the application.
*
* @param callable $factory
*/
public function __construct(callable $factory)
{
$this->factory = $factory;
}
/**
* Resolve a queue connection instance.
*
* @param string $name
* @return \Illuminate\Contracts\Queue\Queue
*/
public function connection($name = null)
{
if (is_null($this->queue)) {
$this->queue = ($this->factory)();
}
return $this->queue;
}
}

View File

@ -0,0 +1,106 @@
<?php
/*
* This file is part of Flarum.
*
* (c) Toby Zerner <toby.zerner@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Flarum\Queue;
use Flarum\Console\Event\Configuring;
use Flarum\Foundation\AbstractServiceProvider;
use Illuminate\Contracts\Debug\ExceptionHandler as ExceptionHandling;
use Illuminate\Contracts\Queue\Factory;
use Illuminate\Queue\Connectors\ConnectorInterface;
use Illuminate\Queue\Console as Commands;
use Illuminate\Queue\Failed\NullFailedJobProvider;
use Illuminate\Queue\Listener;
use Illuminate\Queue\SyncQueue;
use Illuminate\Queue\Worker;
class QueueServiceProvider extends AbstractServiceProvider
{
protected $commands = [
Commands\FlushFailedCommand::class,
Commands\ForgetFailedCommand::class,
Commands\ListenCommand::class,
Commands\ListFailedCommand::class,
Commands\RestartCommand::class,
Commands\RetryCommand::class,
Commands\WorkCommand::class,
];
public function register()
{
// Register a simple connection factory that always returns the same
// connection, as that is enough for our purposes.
$this->app->singleton(Factory::class, function () {
return new QueueFactory(function () {
return $this->app->make('flarum.queue.connection');
});
});
// Extensions can override this binding if they want to make Flarum use
// a different queuing backend.
$this->app->singleton('flarum.queue.connection', function ($app) {
$queue = new SyncQueue;
$queue->setContainer($app);
return $queue;
});
$this->app->singleton(ExceptionHandling::class, function ($app) {
return new ExceptionHandler($app['log']);
});
$this->app->singleton(Worker::class, function ($app) {
return new Worker(
new HackyManagerForWorker($app[Factory::class]),
$app['events'],
$app[ExceptionHandling::class]
);
});
$this->app->singleton(Listener::class, function ($app) {
return new Listener($app->basePath());
});
$this->app->singleton('cache', function ($app) {
return new class($app) {
public function __construct($app)
{
$this->app = $app;
}
public function driver()
{
return $this->app['cache.store'];
}
};
});
$this->app->singleton('queue.failer', function () {
return new NullFailedJobProvider();
});
$this->app->alias(ConnectorInterface::class, 'queue.connection');
$this->app->alias(Factory::class, 'queue');
$this->app->alias(Worker::class, 'queue.worker');
$this->app->alias(Listener::class, 'queue.listener');
$this->registerCommands();
}
protected function registerCommands()
{
$this->app['events']->listen(Configuring::class, function (Configuring $event) {
foreach ($this->commands as $command) {
$event->addCommand($command);
}
});
}
}