mirror of
https://github.com/friendica/friendica
synced 2025-02-08 04:18:51 +00:00
Merge pull request #14659 from nupplaphil/feat/worker_console
Move 'bin/worker.php' to 'bin/console.php worker'
This commit is contained in:
commit
c2eae676bf
25 changed files with 486 additions and 249 deletions
|
@ -52,6 +52,7 @@ require dirname(__FILE__, 2) . '/vendor/autoload.php';
|
|||
|
||||
$dice = (new Dice())->addRules(require(dirname(__FILE__, 2) . '/static/dependencies.config.php'));
|
||||
|
||||
$app = \Friendica\App::fromDice($dice);
|
||||
$container = \Friendica\Core\Container::fromDice($dice);
|
||||
$app = \Friendica\App::fromContainer($container);
|
||||
|
||||
$app->processEjabberd();
|
||||
|
|
|
@ -19,6 +19,5 @@ require dirname(__DIR__) . '/vendor/autoload.php';
|
|||
|
||||
$dice = (new Dice())->addRules(require(dirname(__DIR__) . '/static/dependencies.config.php'));
|
||||
|
||||
$app = \Friendica\App::fromDice($dice);
|
||||
|
||||
$app->processConsole($_SERVER['argv'] ?? []);
|
||||
$container = \Friendica\Core\Container::fromDice($dice);
|
||||
\Friendica\Core\Console::create($container, $_SERVER['argv'] ?? [])->execute();
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*
|
||||
* @deprecated 2025.01 use bin/console.php daemon instead
|
||||
* @deprecated 2025.02 use bin/console.php daemon instead
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -28,9 +28,8 @@ require dirname(__DIR__) . '/vendor/autoload.php';
|
|||
|
||||
$dice = (new Dice())->addRules(require(dirname(__DIR__) . '/static/dependencies.config.php'));
|
||||
|
||||
$app = \Friendica\App::fromDice($dice);
|
||||
|
||||
$argv = $_SERVER['argv'] ?? [];
|
||||
array_splice($argv, 1, 0, "daemon");
|
||||
|
||||
$app->processConsole($argv);
|
||||
$container = \Friendica\Core\Container::fromDice($dice);
|
||||
\Friendica\Core\Console::create($container, $argv)->execute();
|
||||
|
|
|
@ -129,7 +129,7 @@ bin/console user password "$USER_NICK" "$USER_PASSW"
|
|||
# create cronjob - activate if you have enough memory in you dev VM
|
||||
# cronjob runs as www-data user
|
||||
echo ">>> Installing cronjob"
|
||||
echo "*/10 * * * * www-data cd /vagrant; /usr/bin/php bin/worker.php" >> /etc/cron.d/friendica
|
||||
echo "*/10 * * * * www-data cd /vagrant; /usr/bin/php bin/console.php worker" >> /etc/cron.d/friendica
|
||||
|
||||
# friendica needs write access to /tmp
|
||||
chmod 777 /tmp
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*
|
||||
* @deprecated 2025.01 use bin/console.php jetstream instead
|
||||
* @deprecated 2025.02 use bin/console.php jetstream instead
|
||||
*/
|
||||
|
||||
use Dice\Dice;
|
||||
|
@ -23,9 +23,8 @@ require dirname(__DIR__) . '/vendor/autoload.php';
|
|||
|
||||
$dice = (new Dice())->addRules(require(dirname(__DIR__) . '/static/dependencies.config.php'));
|
||||
|
||||
$app = \Friendica\App::fromDice($dice);
|
||||
|
||||
$argv = $_SERVER['argv'] ?? [];
|
||||
array_splice($argv, 1, 0, "jetstream");
|
||||
|
||||
$app->processConsole($argv);
|
||||
$container = \Friendica\Core\Container::fromDice($dice);
|
||||
\Friendica\Core\Console::create($container, $argv)->execute();
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*
|
||||
* Starts the background processing
|
||||
*
|
||||
* @deprecated 2025.02 use bin/console.php worker instead
|
||||
*/
|
||||
|
||||
if (php_sapi_name() !== 'cli') {
|
||||
|
@ -16,9 +18,6 @@ if (php_sapi_name() !== 'cli') {
|
|||
|
||||
use Dice\Dice;
|
||||
|
||||
// Get options
|
||||
$options = getopt('sn', ['spawn', 'no_cron']);
|
||||
|
||||
// Ensure that worker.php is executed from the base path of the installation
|
||||
chdir(dirname(__DIR__));
|
||||
|
||||
|
@ -26,6 +25,8 @@ require dirname(__DIR__) . '/vendor/autoload.php';
|
|||
|
||||
$dice = (new Dice())->addRules(require(dirname(__DIR__) . '/static/dependencies.config.php'));
|
||||
|
||||
$app = \Friendica\App::fromDice($dice);
|
||||
$argv = $_SERVER['argv'] ?? [];
|
||||
array_splice($argv, 1, 0, "worker");
|
||||
|
||||
$app->processWorker($options ?: []);
|
||||
$container = \Friendica\Core\Container::fromDice($dice);
|
||||
\Friendica\Core\Console::create($container, $argv)->execute();
|
||||
|
|
|
@ -268,7 +268,7 @@ You might wish to delete/rename `config/local.config.php` to another name and dr
|
|||
Set up a cron job or scheduled task to run the worker once every 5-10 minutes in order to perform background processing.
|
||||
Example:
|
||||
|
||||
cd /base/directory; /path/to/php bin/worker.php
|
||||
cd /base/directory; /path/to/php bin/console.php worker
|
||||
|
||||
Change "/base/directory", and "/path/to/php" as appropriate for your situation.
|
||||
|
||||
|
@ -277,7 +277,7 @@ Change "/base/directory", and "/path/to/php" as appropriate for your situation.
|
|||
If you are using a Linux server, run "crontab -e" and add a line like the
|
||||
one shown, substituting for your unique paths and settings:
|
||||
|
||||
*/10 * * * * cd /home/myname/mywebsite; /usr/bin/php bin/worker.php
|
||||
*/10 * * * * cd /home/myname/mywebsite; /usr/bin/php bin/console.php worker
|
||||
|
||||
You can generally find the location of PHP by executing "which php".
|
||||
If you run into trouble with this section please contact your hosting provider for assistance.
|
||||
|
@ -290,11 +290,11 @@ Once you have installed Friendica and created an admin account as part of the pr
|
|||
#### worker alternative: daemon
|
||||
Otherwise, you’ll need to use the command line on your remote server and start the Friendica daemon (background task) using the following command:
|
||||
|
||||
cd /path/to/friendica; php bin/daemon.php start
|
||||
cd /path/to/friendica; php bin/console.php daemon start
|
||||
|
||||
Once started, you can check the daemon status using the following command:
|
||||
|
||||
cd /path/to/friendica; php bin/daemon.php status
|
||||
cd /path/to/friendica; php bin/console.php daemon status
|
||||
|
||||
After a server restart or any other failure, the daemon needs to be restarted.
|
||||
This could be achieved by a cronjob.
|
||||
|
@ -426,7 +426,7 @@ provided by one of our members.
|
|||
>
|
||||
> */10 * * * * cd /var/www/friendica/friendica/ && sudo -u www-data /usr/bin/php \
|
||||
> -d suhosin.executor.func.blacklist=none \
|
||||
> -d suhosin.executor.eval.blacklist=none -f bin/worker.php
|
||||
> -d suhosin.executor.eval.blacklist=none -f bin/console.php
|
||||
>
|
||||
> This worked well for simple test cases, but the friendica-cron still failed
|
||||
> with a fatal error:
|
||||
|
@ -435,7 +435,7 @@ provided by one of our members.
|
|||
> (attacker 'REMOTE_ADDR not set', file '/var/www/friendica/friendica/boot.php',
|
||||
> line 1341)
|
||||
>
|
||||
> After a while I noticed, that `bin/worker.php` calls further PHP script via `proc_open`.
|
||||
> After a while I noticed, that `bin/console.php worker` calls further PHP script via `proc_open`.
|
||||
> These scripts themselves also use `proc_open` and fail, because they are NOT
|
||||
> called with `-d suhosin.executor.func.blacklist=none`.
|
||||
>
|
||||
|
|
|
@ -28,7 +28,7 @@ Jetstream is a service that connects to the Bluesky firehose.
|
|||
With Jetstream, messages arrive in real time rather than having to be polled.
|
||||
It also enables real-time processing of blocks or tracking activities performed by the user via the Bluesky website or application.
|
||||
|
||||
To enable Jetstream processing, run `bin/jetstream.php' from the command line.
|
||||
To enable Jetstream processing, run `bin/console.php jetstream' from the command line.
|
||||
You will need to define the process id file in local.config.php in the 'jetstream' section using the key 'pidfile'.
|
||||
|
||||
To keep track of the messages processed and the drift (the time difference between the date of the message and the date the system processed that message), some fields are added to the statistics endpoint.
|
|
@ -57,7 +57,7 @@ Finally, you may also want to optimise your database with the following command:
|
|||
|
||||
### Going offline
|
||||
Stop background tasks and put your server in maintenance mode.
|
||||
1. If you had set up a worker cron job like this ``*/10 * * * * cd /var/www/friendica; /usr/bin/php bin/worker.php`` run ``crontab -e`` and comment out this line. Alternatively if you deploy a worker daemon, disable this instead.
|
||||
1. If you had set up a worker cron job like this ``*/10 * * * * cd /var/www/friendica; /usr/bin/php bin/console.php worker`` run ``crontab -e`` and comment out this line. Alternatively if you deploy a worker daemon, disable this instead.
|
||||
2. Put your server into maintenance mode: ``bin/console maintenance 1 "We are currently upgrading our system and will be back soon."``
|
||||
|
||||
## Dumping DB
|
||||
|
@ -78,7 +78,7 @@ Ensure the newly created database credentials are identical to the setting in th
|
|||
### Cron job for worker
|
||||
Set up the required daily cron job.
|
||||
Run ``crontab -e`` and add the following line according to your system specification
|
||||
``*/10 * * * * cd /var/www/friendica; /usr/bin/php bin/worker.php``
|
||||
``*/10 * * * * cd /var/www/friendica; /usr/bin/php bin/console.php worker``
|
||||
|
||||
### DNS settings
|
||||
Adjust your DNS records by pointing them to your new server.
|
||||
|
|
|
@ -210,13 +210,13 @@ Gehe in den Friendica-Hauptordner und führe den Kommandozeilen Befehl aus:
|
|||
Erstelle einen Cron job oder einen regelmäßigen Task, um den Poller alle 5-10 Minuten im Hintergrund ablaufen zu lassen.
|
||||
Beispiel:
|
||||
|
||||
cd /base/directory; /path/to/php bin/worker.php
|
||||
cd /base/directory; /path/to/php bin/console.php worker
|
||||
|
||||
Ändere "/base/directory" und "/path/to/php" auf deine Systemvorgaben.
|
||||
|
||||
Wenn du einen Linux-Server nutzt, benutze den Befehl "crontab -e" und ergänze eine Zeile wie die Folgende; angepasst an dein System
|
||||
|
||||
`*/10 * * * * cd /home/myname/mywebsite; /usr/bin/php bin/worker.php`
|
||||
`*/10 * * * * cd /home/myname/mywebsite; /usr/bin/php bin/console.php worker`
|
||||
|
||||
Du kannst den PHP-Pfad finden, indem du den Befehl „which php“ ausführst.
|
||||
Wenn du Schwierigkeiten mit diesem Schritt hast, kannst du deinen Hosting-Anbieter kontaktieren.
|
||||
|
|
|
@ -27,7 +27,7 @@ Jetstream ist ein Dienst, der sich mit dem Bluesky-Firehose verbindet.
|
|||
Mit Jetstream kommen die Nachrichten in Echtzeit an und müssen nicht erst abgefragt werden.
|
||||
Es ermöglicht auch die Echtzeitverarbeitung von Blöcken oder Tracking-Aktivitäten, die über die Bluesky-Website oder -Anwendung durchgeführt werden.
|
||||
|
||||
Um die Jetstream-Verarbeitung zu aktivieren, führe `bin/jetstream.php' über die Befehlszeile aus.
|
||||
Um die Jetstream-Verarbeitung zu aktivieren, führe `bin/console.php daemon' über die Befehlszeile aus.
|
||||
Du musst vorher die Prozess-ID-Datei in local.config.php im Abschnitt „jetstream“ mit dem Schlüssel „pidfile“ definieren.
|
||||
|
||||
Um die verarbeiteten Nachrichten und die Drift (die Zeitdifferenz zwischen dem Datum der Nachricht und dem Datum, an dem das System diese Nachricht verarbeitet hat) zu verfolgen, wurden dem Statistik-Endpunkt einige Felder hinzugefügt.
|
||||
|
|
|
@ -19,6 +19,7 @@ $request = \GuzzleHttp\Psr7\ServerRequest::fromGlobals();
|
|||
|
||||
$dice = (new Dice())->addRules(require(__DIR__ . '/static/dependencies.config.php'));
|
||||
|
||||
$app = \Friendica\App::fromDice($dice);
|
||||
$container = \Friendica\Core\Container::fromDice($dice);
|
||||
$app = \Friendica\App::fromContainer($container);
|
||||
|
||||
$app->processRequest($request, $start_time);
|
||||
|
|
|
@ -6,4 +6,4 @@ Description=Friendica Worker
|
|||
User=http
|
||||
#Adapt the path in the following line to your system, use 'which php' to find php path,
|
||||
#provide the absolute path for worker.php
|
||||
ExecStart=/usr/bin/php /www/path/bin/worker.php &
|
||||
ExecStart=/usr/bin/php /www/path/bin/console.php worker &
|
||||
|
|
118
src/App.php
118
src/App.php
|
@ -18,9 +18,9 @@ use Friendica\Capabilities\ICanCreateResponses;
|
|||
use Friendica\Capabilities\ICanHandleRequests;
|
||||
use Friendica\Content\Nav;
|
||||
use Friendica\Core\Config\Factory\Config;
|
||||
use Friendica\Core\Container;
|
||||
use Friendica\Core\Renderer;
|
||||
use Friendica\Core\Session\Capability\IHandleUserSessions;
|
||||
use Friendica\Core\Worker\Repository\Process as ProcessRepository;
|
||||
use Friendica\Database\Definition\DbaDefinition;
|
||||
use Friendica\Database\Definition\ViewDefinition;
|
||||
use Friendica\Module\Maintenance;
|
||||
|
@ -31,7 +31,6 @@ use Friendica\Core\Logger\Capability\LogChannel;
|
|||
use Friendica\Core\PConfig\Capability\IManagePersonalConfigValues;
|
||||
use Friendica\Core\System;
|
||||
use Friendica\Core\Update;
|
||||
use Friendica\Core\Worker;
|
||||
use Friendica\Module\Special\HTTPException as ModuleHTTPException;
|
||||
use Friendica\Network\HTTPException;
|
||||
use Friendica\Protocol\ATProtocol\DID;
|
||||
|
@ -61,13 +60,13 @@ class App
|
|||
const CODENAME = 'Interrupted Fern';
|
||||
const VERSION = '2025.02-dev';
|
||||
|
||||
public static function fromDice(Dice $dice): self
|
||||
public static function fromContainer(Container $container): self
|
||||
{
|
||||
return new self($dice);
|
||||
return new self($container);
|
||||
}
|
||||
|
||||
/**
|
||||
* @var Dice
|
||||
* @var Container
|
||||
*/
|
||||
private $container;
|
||||
|
||||
|
@ -122,26 +121,20 @@ class App
|
|||
*/
|
||||
private $appHelper;
|
||||
|
||||
private function __construct(Dice $container)
|
||||
private function __construct(Container $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
public function processRequest(ServerRequestInterface $request, float $start_time): void
|
||||
{
|
||||
$this->setupContainerForAddons();
|
||||
|
||||
$this->setupContainerForLogger(LogChannel::DEFAULT);
|
||||
|
||||
$this->container = $this->container->addRule(Mode::class, [
|
||||
$this->container->addRule(Mode::class, [
|
||||
'call' => [
|
||||
['determineRunMode', [false, $request->getServerParams()], Dice::CHAIN_CALL],
|
||||
],
|
||||
]);
|
||||
|
||||
$this->setupLegacyServiceLocator();
|
||||
|
||||
$this->registerErrorHandler();
|
||||
$this->container->setup(LogChannel::APP, false);
|
||||
|
||||
$this->requestId = $this->container->create(Request::class)->getRequestId();
|
||||
$this->auth = $this->container->create(Authentication::class);
|
||||
|
@ -177,13 +170,7 @@ class App
|
|||
|
||||
public function processEjabberd(): void
|
||||
{
|
||||
$this->setupContainerForAddons();
|
||||
|
||||
$this->setupContainerForLogger(LogChannel::AUTH_JABBERED);
|
||||
|
||||
$this->setupLegacyServiceLocator();
|
||||
|
||||
$this->registerErrorHandler();
|
||||
$this->container->setup(LogChannel::AUTH_JABBERED, false);
|
||||
|
||||
/** @var BasePath */
|
||||
$basePath = $this->container->create(BasePath::class);
|
||||
|
@ -200,95 +187,6 @@ class App
|
|||
}
|
||||
}
|
||||
|
||||
public function processConsole(array $argv): void
|
||||
{
|
||||
$this->setupContainerForAddons();
|
||||
|
||||
$this->setupContainerForLogger(LogChannel::CONSOLE);
|
||||
|
||||
$this->setupLegacyServiceLocator();
|
||||
|
||||
$this->registerErrorHandler();
|
||||
|
||||
$this->registerTemplateEngine();
|
||||
|
||||
(new \Friendica\Core\Console($this->container, $argv))->execute();
|
||||
}
|
||||
|
||||
public function processWorker(array $options): void
|
||||
{
|
||||
$this->setupContainerForAddons();
|
||||
|
||||
$this->setupContainerForLogger(LogChannel::WORKER);
|
||||
|
||||
$this->setupLegacyServiceLocator();
|
||||
|
||||
$this->registerErrorHandler();
|
||||
|
||||
$this->registerTemplateEngine();
|
||||
|
||||
/** @var Mode */
|
||||
$mode = $this->container->create(Mode::class);
|
||||
|
||||
$mode->setExecutor(Mode::WORKER);
|
||||
|
||||
/** @var BasePath */
|
||||
$basePath = $this->container->create(BasePath::class);
|
||||
|
||||
// Check the database structure and possibly fixes it
|
||||
Update::check($basePath->getPath(), true);
|
||||
|
||||
// Quit when in maintenance
|
||||
if (!$mode->has(Mode::MAINTENANCEDISABLED)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$spawn = array_key_exists('s', $options) || array_key_exists('spawn', $options);
|
||||
|
||||
if ($spawn) {
|
||||
Worker::spawnWorker();
|
||||
exit();
|
||||
}
|
||||
|
||||
$run_cron = !array_key_exists('n', $options) && !array_key_exists('no_cron', $options);
|
||||
|
||||
/** @var ProcessRepository */
|
||||
$processRepository = $this->container->create(ProcessRepository::class);
|
||||
|
||||
$process = $processRepository->create(getmypid(), 'worker.php');
|
||||
|
||||
Worker::processQueue($run_cron, $process);
|
||||
|
||||
Worker::unclaimProcess($process);
|
||||
|
||||
$processRepository->delete($process);
|
||||
}
|
||||
|
||||
private function setupContainerForAddons(): void
|
||||
{
|
||||
/** @var \Friendica\Core\Addon\Capability\ICanLoadAddons $addonLoader */
|
||||
$addonLoader = $this->container->create(\Friendica\Core\Addon\Capability\ICanLoadAddons::class);
|
||||
|
||||
$this->container = $this->container->addRules($addonLoader->getActiveAddonConfig('dependencies'));
|
||||
}
|
||||
|
||||
private function setupContainerForLogger(string $logChannel): void
|
||||
{
|
||||
$this->container = $this->container->addRule(LoggerInterface::class, [
|
||||
'constructParams' => [$logChannel],
|
||||
]);
|
||||
}
|
||||
|
||||
private function setupLegacyServiceLocator(): void
|
||||
{
|
||||
DI::init($this->container);
|
||||
}
|
||||
|
||||
private function registerErrorHandler(): void
|
||||
{
|
||||
\Friendica\Core\Logger\Handler\ErrorHandler::register($this->container->create(LoggerInterface::class));
|
||||
}
|
||||
|
||||
private function registerTemplateEngine(): void
|
||||
{
|
||||
Renderer::registerTemplateEngine('Friendica\Render\FriendicaSmartyEngine');
|
||||
|
|
39
src/Console/AbstractConsole.php
Normal file
39
src/Console/AbstractConsole.php
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
// Copyright (C) 2010-2024, the Friendica project
|
||||
// SPDX-FileCopyrightText: 2010-2024 the Friendica project
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Friendica\Console;
|
||||
|
||||
use Asika\SimpleConsole\Console;
|
||||
use Friendica\Core\Console as CoreConsole;
|
||||
use Friendica\Core\Logger\Capability\LogChannel;
|
||||
|
||||
/**
|
||||
* Abstract Console class for common settings
|
||||
*/
|
||||
abstract class AbstractConsole extends Console
|
||||
{
|
||||
/**
|
||||
* Overwrite this const in case you want to switch the LogChannel for this console command
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public const LOG_CHANNEL = LogChannel::CONSOLE;
|
||||
|
||||
/**
|
||||
* Checks, if the Console command was executed outside `bin/console.php` and prints the correct execution
|
||||
*
|
||||
* @param string $command the current command
|
||||
*/
|
||||
protected function checkDeprecated(string $command): void
|
||||
{
|
||||
if (substr($this->executable, -strlen(CoreConsole::getDefaultExecutable())) === CoreConsole::getDefaultExecutable()) {
|
||||
$this->out(sprintf("'%s' is deprecated and will removed. Please use 'bin/console.php %s' instead", $this->executable, $command));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,10 +9,11 @@ declare(strict_types=1);
|
|||
|
||||
namespace Friendica\Console;
|
||||
|
||||
use Asika\SimpleConsole\CommandArgsException;
|
||||
use Friendica\App\Mode;
|
||||
use Friendica\Core\Config\Capability\IManageConfigValues;
|
||||
use Asika\SimpleConsole\Console;
|
||||
use Friendica\Core\KeyValueStorage\Capability\IManageKeyValuePairs;
|
||||
use Friendica\Core\Logger\Capability\LogChannel;
|
||||
use Friendica\Core\System;
|
||||
use Friendica\Core\Update;
|
||||
use Friendica\Core\Worker;
|
||||
|
@ -26,8 +27,10 @@ use RuntimeException;
|
|||
/**
|
||||
* Console command for interacting with the daemon
|
||||
*/
|
||||
final class Daemon extends Console
|
||||
final class Daemon extends AbstractConsole
|
||||
{
|
||||
public const LOG_CHANNEL = LogChannel::DAEMON;
|
||||
|
||||
private Mode $mode;
|
||||
private IManageConfigValues $config;
|
||||
private IManageKeyValuePairs $keyValue;
|
||||
|
@ -90,9 +93,7 @@ HELP;
|
|||
|
||||
protected function doExecute()
|
||||
{
|
||||
if ($this->executable !== 'bin/console.php') {
|
||||
$this->out(sprintf("'%s' is deprecated and will removed. Please use 'bin/console.php daemon' instead", $this->executable));
|
||||
}
|
||||
$this->checkDeprecated('daemon');
|
||||
|
||||
if ($this->mode->isInstall()) {
|
||||
throw new RuntimeException("Friendica isn't properly installed yet");
|
||||
|
@ -120,7 +121,7 @@ HELP;
|
|||
$foreground = $this->getOption(['f', 'foreground']) ?? false;
|
||||
|
||||
if (empty($daemonMode)) {
|
||||
throw new RuntimeException("Please use either 'start', 'stop' or 'status'");
|
||||
throw new CommandArgsException("Please use either 'start', 'stop' or 'status'");
|
||||
}
|
||||
|
||||
$this->daemon->init($pidfile);
|
||||
|
|
|
@ -12,9 +12,9 @@ namespace Friendica\Console;
|
|||
use Friendica\App\Mode;
|
||||
use Friendica\Core\Addon;
|
||||
use Friendica\Core\Config\Capability\IManageConfigValues;
|
||||
use Asika\SimpleConsole\Console;
|
||||
use Friendica\Core\Hook;
|
||||
use Friendica\Core\KeyValueStorage\Capability\IManageKeyValuePairs;
|
||||
use Friendica\Core\Logger\Capability\LogChannel;
|
||||
use Friendica\Protocol\ATProtocol\Jetstream;
|
||||
use Friendica\System\Daemon as SysDaemon;
|
||||
use RuntimeException;
|
||||
|
@ -22,8 +22,10 @@ use RuntimeException;
|
|||
/**
|
||||
* Console command for interacting with the daemon
|
||||
*/
|
||||
final class JetstreamDaemon extends Console
|
||||
final class JetstreamDaemon extends AbstractConsole
|
||||
{
|
||||
public const LOG_CHANNEL = LogChannel::DAEMON;
|
||||
|
||||
private Mode $mode;
|
||||
private IManageConfigValues $config;
|
||||
private IManageKeyValuePairs $keyValue;
|
||||
|
@ -77,9 +79,7 @@ HELP;
|
|||
|
||||
protected function doExecute()
|
||||
{
|
||||
if ($this->executable !== 'bin/console.php') {
|
||||
$this->out(sprintf("'%s' is deprecated and will removed. Please use 'bin/console.php jetstream' instead", $this->executable));
|
||||
}
|
||||
$this->checkDeprecated('jetstream');
|
||||
|
||||
if ($this->mode->isInstall()) {
|
||||
throw new RuntimeException("Friendica isn't properly installed yet");
|
||||
|
|
100
src/Console/Worker.php
Normal file
100
src/Console/Worker.php
Normal file
|
@ -0,0 +1,100 @@
|
|||
<?php
|
||||
|
||||
// Copyright (C) 2010-2024, the Friendica project
|
||||
// SPDX-FileCopyrightText: 2010-2024 the Friendica project
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Friendica\Console;
|
||||
|
||||
use Friendica\App\Mode;
|
||||
use Friendica\Core\Logger\Capability\LogChannel;
|
||||
use Friendica\Core\Update;
|
||||
use Friendica\Core\Worker as CoreWorker;
|
||||
use Friendica\Core\Worker\Repository\Process as ProcessRepository;
|
||||
use Friendica\Util\BasePath;
|
||||
|
||||
/**
|
||||
* Console command for starting worker
|
||||
*/
|
||||
final class Worker extends AbstractConsole
|
||||
{
|
||||
public const LOG_CHANNEL = LogChannel::WORKER;
|
||||
|
||||
private Mode $mode;
|
||||
private BasePath $basePath;
|
||||
private ProcessRepository $processRepo;
|
||||
|
||||
/**
|
||||
* @param Mode $mode
|
||||
* @param BasePath $basePath
|
||||
* @param ProcessRepository $processRepo
|
||||
* @param array|null $argv
|
||||
*/
|
||||
public function __construct(Mode $mode, BasePath $basePath, ProcessRepository $processRepo, array $argv = null)
|
||||
{
|
||||
parent::__construct($argv);
|
||||
|
||||
$this->mode = $mode;
|
||||
$this->basePath = $basePath;
|
||||
$this->processRepo = $processRepo;
|
||||
}
|
||||
|
||||
protected function getHelp(): string
|
||||
{
|
||||
return <<<HELP
|
||||
Worker - Start a worker
|
||||
Synopsis
|
||||
bin/console worker [-h|--help|-?] [-v] [-n|--no_cron] [-s|--spawn]
|
||||
|
||||
Description
|
||||
Start a worker process
|
||||
|
||||
Options
|
||||
-h|--help|-? Show help information
|
||||
-v Show more debug information.
|
||||
-n|--no_cron Don't executes the Cronjob
|
||||
-s|--spawn Spawn an additional worker
|
||||
|
||||
Examples
|
||||
bin/console worker -n
|
||||
Starts the worker without executing other recurring tasks
|
||||
|
||||
bin/console worker -s
|
||||
Starts the worker and immediately spawn another worker process
|
||||
HELP;
|
||||
}
|
||||
|
||||
protected function doExecute()
|
||||
{
|
||||
$this->checkDeprecated('worker');
|
||||
|
||||
$this->mode->setExecutor(Mode::WORKER);
|
||||
|
||||
// Check the database structure and possibly fixes it
|
||||
Update::check($this->basePath->getPath(), true);
|
||||
|
||||
// Quit when in maintenance
|
||||
if (!$this->mode->has(Mode::MAINTENANCEDISABLED)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$spawn = $this->getOption(['s', 'spawn'], false);
|
||||
|
||||
if ($spawn) {
|
||||
CoreWorker::spawnWorker();
|
||||
exit();
|
||||
}
|
||||
|
||||
$run_cron = !$this->getOption(['n', 'no_cron'], false);
|
||||
|
||||
$process = $this->processRepo->create(getmypid(), 'worker.php');
|
||||
|
||||
CoreWorker::processQueue($run_cron, $process);
|
||||
CoreWorker::unclaimProcess($process);
|
||||
|
||||
$this->processRepo->delete($process);
|
||||
}
|
||||
}
|
|
@ -7,23 +7,34 @@
|
|||
|
||||
namespace Friendica\Core;
|
||||
|
||||
use Dice\Dice;
|
||||
use Friendica;
|
||||
use Friendica\App;
|
||||
use Friendica\Core\Logger\Capability\LogChannel;
|
||||
|
||||
/**
|
||||
* Description of Console
|
||||
*/
|
||||
class Console extends \Asika\SimpleConsole\Console
|
||||
{
|
||||
// Disables the default help handling
|
||||
protected $helpOptions = [];
|
||||
protected $customHelpOptions = ['h', 'help', '?'];
|
||||
/** @var string The default executable for a console call */
|
||||
private const CONSOLE_EXECUTABLE = 'bin/console.php';
|
||||
|
||||
/**
|
||||
* @var Dice The DI library
|
||||
* @return string The default executable for a console call
|
||||
*/
|
||||
protected $dice;
|
||||
public static function getDefaultExecutable(): string
|
||||
{
|
||||
return self::CONSOLE_EXECUTABLE;
|
||||
}
|
||||
|
||||
// Disables the default help handling
|
||||
protected $helpOptions = [];
|
||||
protected array $customHelpOptions = ['h', 'help', '?'];
|
||||
|
||||
/**
|
||||
* @var Container The Container
|
||||
*/
|
||||
protected Container $container;
|
||||
|
||||
protected function getHelp()
|
||||
{
|
||||
|
@ -39,6 +50,7 @@ Commands:
|
|||
createdoxygen Generate Doxygen headers
|
||||
daemon Interact with the Friendica daemon
|
||||
jetstream Interact with the Jetstream daemon
|
||||
worker Start worker process
|
||||
dbstructure Do database updates
|
||||
docbloxerrorchecker Check the file tree for DocBlox errors
|
||||
extract Generate translation string file for the Friendica project (deprecated)
|
||||
|
@ -68,7 +80,7 @@ HELP;
|
|||
return $help;
|
||||
}
|
||||
|
||||
protected $subConsoles = [
|
||||
protected array $subConsoles = [
|
||||
'addon' => Friendica\Console\Addon::class,
|
||||
'archivecontact' => Friendica\Console\ArchiveContact::class,
|
||||
'autoinstall' => Friendica\Console\AutomaticInstallation::class,
|
||||
|
@ -79,6 +91,7 @@ HELP;
|
|||
'createdoxygen' => Friendica\Console\CreateDoxygen::class,
|
||||
'daemon' => Friendica\Console\Daemon::class,
|
||||
'jetstream' => Friendica\Console\JetstreamDaemon::class,
|
||||
'worker' => Friendica\Console\Worker::class,
|
||||
'docbloxerrorchecker' => Friendica\Console\DocBloxErrorChecker::class,
|
||||
'dbstructure' => Friendica\Console\DatabaseStructure::class,
|
||||
'extract' => Friendica\Console\Extract::class,
|
||||
|
@ -104,14 +117,18 @@ HELP;
|
|||
/**
|
||||
* CliInput Friendica constructor.
|
||||
*
|
||||
* @param Dice $dice The DI library
|
||||
* @param array $argv
|
||||
* @param Container $container The Friendica container
|
||||
*/
|
||||
public function __construct(Dice $dice, array $argv = null)
|
||||
public function __construct(Container $container, array $argv = null)
|
||||
{
|
||||
parent::__construct($argv);
|
||||
|
||||
$this->dice = $dice;
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
public static function create(Container $container, array $argv = null): Console
|
||||
{
|
||||
return new self($container, $argv);
|
||||
}
|
||||
|
||||
protected function doExecute(): int
|
||||
|
@ -170,8 +187,14 @@ HELP;
|
|||
|
||||
$className = $this->subConsoles[$command];
|
||||
|
||||
if (is_subclass_of($className, Friendica\Console\AbstractConsole::class)) {
|
||||
$this->container->setup($className::LOG_CHANNEL);
|
||||
} else {
|
||||
$this->container->setup(LogChannel::CONSOLE);
|
||||
}
|
||||
|
||||
/** @var Console $subconsole */
|
||||
$subconsole = $this->dice->create($className, [$subargs]);
|
||||
$subconsole = $this->container->create($className, [$subargs]);
|
||||
|
||||
foreach ($this->options as $name => $value) {
|
||||
$subconsole->setOption($name, $value);
|
||||
|
@ -179,5 +202,4 @@ HELP;
|
|||
|
||||
return $subconsole;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
118
src/Core/Container.php
Normal file
118
src/Core/Container.php
Normal file
|
@ -0,0 +1,118 @@
|
|||
<?php
|
||||
|
||||
// Copyright (C) 2010-2024, the Friendica project
|
||||
// SPDX-FileCopyrightText: 2010-2024 the Friendica project
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Friendica\Core;
|
||||
|
||||
use Dice\Dice;
|
||||
use Friendica\Core\Addon\Capability\ICanLoadAddons;
|
||||
use Friendica\Core\Logger\Capability\LogChannel;
|
||||
use Friendica\Core\Logger\Handler\ErrorHandler;
|
||||
use Friendica\DI;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* Wrapper for the Dice class to make some basic setups
|
||||
*/
|
||||
class Container
|
||||
{
|
||||
private Dice $container;
|
||||
|
||||
protected function __construct(Dice $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance with Dice
|
||||
*
|
||||
* @param Dice $container
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public static function fromDice(Dice $container): self
|
||||
{
|
||||
return new self($container);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the container with the given parameters
|
||||
*
|
||||
* @param string $logChannel The Log Channel of this call
|
||||
* @param bool $withTemplateEngine true, if the template engine should be set too
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setup(string $logChannel = LogChannel::DEFAULT, bool $withTemplateEngine = true)
|
||||
{
|
||||
$this->setupContainerForAddons();
|
||||
$this->setupContainerForLogger($logChannel);
|
||||
$this->setupLegacyServiceLocator();
|
||||
$this->registerErrorHandler();
|
||||
|
||||
if ($withTemplateEngine) {
|
||||
$this->registerTemplateEngine();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a fully constructed object based on $name using $args and $share as constructor arguments if supplied
|
||||
* @param string $name name The name of the class to instantiate
|
||||
* @param array $args An array with any additional arguments to be passed into the constructor upon instantiation
|
||||
* @param array $share a list of defined in shareInstances for objects higher up the object graph, should only be used internally
|
||||
* @return object A fully constructed object based on the specified input arguments
|
||||
*
|
||||
* @see Dice::create()
|
||||
*/
|
||||
public function create(string $name, array $args = [], array $share = []): object
|
||||
{
|
||||
return $this->container->create($name, $args, $share);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a rule $rule to the class $name
|
||||
* @param string $name The name of the class to add the rule for
|
||||
* @param array $rule The container can be fully configured using rules provided by associative arrays. See {@link https://r.je/dice.html#example3} for a description of the rules.
|
||||
*
|
||||
* @see Dice::addRule()
|
||||
*/
|
||||
public function addRule(string $name, array $rule): void
|
||||
{
|
||||
$this->container = $this->container->addRule($name, $rule);
|
||||
}
|
||||
|
||||
private function setupContainerForAddons(): void
|
||||
{
|
||||
/** @var ICanLoadAddons $addonLoader */
|
||||
$addonLoader = $this->container->create(ICanLoadAddons::class);
|
||||
|
||||
$this->container = $this->container->addRules($addonLoader->getActiveAddonConfig('dependencies'));
|
||||
}
|
||||
|
||||
private function setupContainerForLogger(string $logChannel): void
|
||||
{
|
||||
$this->container = $this->container->addRule(LoggerInterface::class, [
|
||||
'constructParams' => [$logChannel],
|
||||
]);
|
||||
}
|
||||
|
||||
private function setupLegacyServiceLocator(): void
|
||||
{
|
||||
DI::init($this->container);
|
||||
}
|
||||
|
||||
private function registerErrorHandler(): void
|
||||
{
|
||||
ErrorHandler::register($this->container->create(LoggerInterface::class));
|
||||
}
|
||||
|
||||
private function registerTemplateEngine(): void
|
||||
{
|
||||
Renderer::registerTemplateEngine('Friendica\Render\FriendicaSmartyEngine');
|
||||
}
|
||||
}
|
|
@ -164,9 +164,10 @@ class System
|
|||
* Executes a child process with 'proc_open'
|
||||
*
|
||||
* @param string $command The command to execute
|
||||
* @param array $args Arguments to pass to the command ( [ 'key' => value, 'key2' => value2, ... ]
|
||||
* @param array $args Arguments to pass to the command ( ['arg1', 'arg2', ... ] )
|
||||
* @param array $options Options to pass to the command ( [ 'key' => value, 'key2' => value2, ... ]
|
||||
*/
|
||||
public function run(string $command, array $args)
|
||||
public function run(string $command, array $args = [], array $options = [])
|
||||
{
|
||||
if (!function_exists('proc_open')) {
|
||||
$this->logger->warning('"proc_open" not available - quitting');
|
||||
|
@ -175,7 +176,11 @@ class System
|
|||
|
||||
$cmdline = $this->config->get('config', 'php_path', 'php') . ' ' . escapeshellarg($command);
|
||||
|
||||
foreach ($args as $key => $value) {
|
||||
foreach ($args as $argumment) {
|
||||
$cmdline .= ' ' . $argumment;
|
||||
}
|
||||
|
||||
foreach ($options as $key => $value) {
|
||||
if (!is_null($value) && is_bool($value) && !$value) {
|
||||
continue;
|
||||
}
|
||||
|
@ -272,10 +277,13 @@ class System
|
|||
*/
|
||||
public static function echoResponse(ResponseInterface $response)
|
||||
{
|
||||
header(sprintf("HTTP/%s %s %s",
|
||||
header(
|
||||
sprintf(
|
||||
"HTTP/%s %s %s",
|
||||
$response->getProtocolVersion(),
|
||||
$response->getStatusCode(),
|
||||
$response->getReasonPhrase())
|
||||
$response->getReasonPhrase()
|
||||
)
|
||||
);
|
||||
|
||||
foreach ($response->getHeaders() as $key => $header) {
|
||||
|
|
|
@ -603,13 +603,13 @@ class Worker
|
|||
self::$lock_duration = 0;
|
||||
|
||||
if ($duration > 3600) {
|
||||
Logger::info('Longer than 1 hour.', ['priority' => $queue['priority'], 'id' => $queue['id'], 'duration' => round($duration/60, 3)]);
|
||||
Logger::info('Longer than 1 hour.', ['priority' => $queue['priority'], 'id' => $queue['id'], 'duration' => round($duration / 60, 3)]);
|
||||
} elseif ($duration > 600) {
|
||||
Logger::info('Longer than 10 minutes.', ['priority' => $queue['priority'], 'id' => $queue['id'], 'duration' => round($duration/60, 3)]);
|
||||
Logger::info('Longer than 10 minutes.', ['priority' => $queue['priority'], 'id' => $queue['id'], 'duration' => round($duration / 60, 3)]);
|
||||
} elseif ($duration > 300) {
|
||||
Logger::info('Longer than 5 minutes.', ['priority' => $queue['priority'], 'id' => $queue['id'], 'duration' => round($duration/60, 3)]);
|
||||
Logger::info('Longer than 5 minutes.', ['priority' => $queue['priority'], 'id' => $queue['id'], 'duration' => round($duration / 60, 3)]);
|
||||
} elseif ($duration > 120) {
|
||||
Logger::info('Longer than 2 minutes.', ['priority' => $queue['priority'], 'id' => $queue['id'], 'duration' => round($duration/60, 3)]);
|
||||
Logger::info('Longer than 2 minutes.', ['priority' => $queue['priority'], 'id' => $queue['id'], 'duration' => round($duration / 60, 3)]);
|
||||
}
|
||||
|
||||
Logger::info('Process done.', ['function' => $funcname, 'priority' => $queue['priority'], 'retrial' => $queue['retrial'], 'id' => $queue['id'], 'duration' => round($duration, 3)]);
|
||||
|
@ -1083,8 +1083,11 @@ class Worker
|
|||
$stamp = (float)microtime(true);
|
||||
foreach ($worker as $worker_pid => $worker_ids) {
|
||||
Logger::info('Set queue entry', ['pid' => $worker_pid, 'ids' => $worker_ids]);
|
||||
DBA::update('workerqueue', ['executed' => DateTimeFormat::utcNow(), 'pid' => $worker_pid],
|
||||
['id' => $worker_ids, 'done' => false, 'pid' => 0]);
|
||||
DBA::update(
|
||||
'workerqueue',
|
||||
['executed' => DateTimeFormat::utcNow(), 'pid' => $worker_pid],
|
||||
['id' => $worker_ids, 'done' => false, 'pid' => 0]
|
||||
);
|
||||
}
|
||||
self::$db_duration += (microtime(true) - $stamp);
|
||||
self::$db_duration_write += (microtime(true) - $stamp);
|
||||
|
@ -1207,7 +1210,7 @@ class Worker
|
|||
if (Worker\Daemon::isMode() && DI::config()->get('system', 'worker_fork')) {
|
||||
self::forkProcess($do_cron);
|
||||
} else {
|
||||
DI::system()->run('bin/worker.php', ['no_cron' => !$do_cron]);
|
||||
DI::system()->run('bin/console.php', ['worker'], ['no_cron' => !$do_cron]);
|
||||
}
|
||||
if (Worker\Daemon::isMode()) {
|
||||
Worker\IPC::SetJobState(false);
|
||||
|
|
|
@ -115,7 +115,7 @@ class Daemon
|
|||
private static function spawn()
|
||||
{
|
||||
Logger::notice('Starting new daemon process');
|
||||
DI::system()->run('bin/daemon.php', ['start']);
|
||||
DI::system()->run('bin/console.php', ['start']);
|
||||
Logger::notice('New daemon process started');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,22 +5,22 @@
|
|||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
declare(strict_types = 1);
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Friendica\Test\Unit;
|
||||
|
||||
use Dice\Dice;
|
||||
use Friendica\App;
|
||||
use Friendica\Core\Container;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class AppTest extends TestCase
|
||||
{
|
||||
public function testFromDiceReturnsApp(): void
|
||||
public function testFromContainerReturnsApp(): void
|
||||
{
|
||||
$dice = $this->createMock(Dice::class);
|
||||
$dice->expects($this->never())->method('create');
|
||||
$container = $this->createMock(Container::class);
|
||||
$container->expects($this->never())->method('create');
|
||||
|
||||
$app = App::fromDice($dice);
|
||||
$app = App::fromContainer($container);
|
||||
|
||||
$this->assertInstanceOf(App::class, $app);
|
||||
}
|
||||
|
|
48
tests/Unit/Core/ContainerTest.php
Normal file
48
tests/Unit/Core/ContainerTest.php
Normal file
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
// Copyright (C) 2010-2024, the Friendica project
|
||||
// SPDX-FileCopyrightText: 2010-2024 the Friendica project
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Core;
|
||||
|
||||
use Dice\Dice;
|
||||
use Friendica\Core\Container;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\Log\NullLogger;
|
||||
|
||||
class ContainerTest extends TestCase
|
||||
{
|
||||
public function testFromDiceReturnsContainer(): void
|
||||
{
|
||||
$dice = $this->createMock(Dice::class);
|
||||
$dice->expects($this->never())->method('create');
|
||||
|
||||
$container = Container::fromDice($dice);
|
||||
|
||||
$this->assertInstanceOf(Container::class, $container);
|
||||
}
|
||||
|
||||
public function testCreateFromContainer(): void
|
||||
{
|
||||
$dice = $this->createMock(Dice::class);
|
||||
$dice->expects($this->once())->method('create')->with(LoggerInterface::class)->willReturn(new NullLogger());
|
||||
|
||||
$container = Container::fromDice($dice);
|
||||
|
||||
$this->assertInstanceOf(NullLogger::class, $container->create(LoggerInterface::class));
|
||||
}
|
||||
|
||||
public function testAddRuleFromContainer(): void
|
||||
{
|
||||
$dice = $this->createMock(Dice::class);
|
||||
$dice->expects($this->once())->method('addRule')->with(LoggerInterface::class, ['constructParams' => ['console']])->willReturn($dice);
|
||||
|
||||
$container = Container::fromDice($dice);
|
||||
$container->addRule(LoggerInterface::class, ['constructParams' => ['console']]);
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue