mirror of
https://github.com/friendica/friendica
synced 2025-02-08 04:58: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'));
|
$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();
|
$app->processEjabberd();
|
||||||
|
|
|
@ -19,6 +19,5 @@ require dirname(__DIR__) . '/vendor/autoload.php';
|
||||||
|
|
||||||
$dice = (new Dice())->addRules(require(dirname(__DIR__) . '/static/dependencies.config.php'));
|
$dice = (new Dice())->addRules(require(dirname(__DIR__) . '/static/dependencies.config.php'));
|
||||||
|
|
||||||
$app = \Friendica\App::fromDice($dice);
|
$container = \Friendica\Core\Container::fromDice($dice);
|
||||||
|
\Friendica\Core\Console::create($container, $_SERVER['argv'] ?? [])->execute();
|
||||||
$app->processConsole($_SERVER['argv'] ?? []);
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
* 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'));
|
$dice = (new Dice())->addRules(require(dirname(__DIR__) . '/static/dependencies.config.php'));
|
||||||
|
|
||||||
$app = \Friendica\App::fromDice($dice);
|
|
||||||
|
|
||||||
$argv = $_SERVER['argv'] ?? [];
|
$argv = $_SERVER['argv'] ?? [];
|
||||||
array_splice($argv, 1, 0, "daemon");
|
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
|
# create cronjob - activate if you have enough memory in you dev VM
|
||||||
# cronjob runs as www-data user
|
# cronjob runs as www-data user
|
||||||
echo ">>> Installing cronjob"
|
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
|
# friendica needs write access to /tmp
|
||||||
chmod 777 /tmp
|
chmod 777 /tmp
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
* 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;
|
use Dice\Dice;
|
||||||
|
@ -23,9 +23,8 @@ require dirname(__DIR__) . '/vendor/autoload.php';
|
||||||
|
|
||||||
$dice = (new Dice())->addRules(require(dirname(__DIR__) . '/static/dependencies.config.php'));
|
$dice = (new Dice())->addRules(require(dirname(__DIR__) . '/static/dependencies.config.php'));
|
||||||
|
|
||||||
$app = \Friendica\App::fromDice($dice);
|
|
||||||
|
|
||||||
$argv = $_SERVER['argv'] ?? [];
|
$argv = $_SERVER['argv'] ?? [];
|
||||||
array_splice($argv, 1, 0, "jetstream");
|
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
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
*
|
*
|
||||||
* Starts the background processing
|
* Starts the background processing
|
||||||
|
*
|
||||||
|
* @deprecated 2025.02 use bin/console.php worker instead
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (php_sapi_name() !== 'cli') {
|
if (php_sapi_name() !== 'cli') {
|
||||||
|
@ -16,9 +18,6 @@ if (php_sapi_name() !== 'cli') {
|
||||||
|
|
||||||
use Dice\Dice;
|
use Dice\Dice;
|
||||||
|
|
||||||
// Get options
|
|
||||||
$options = getopt('sn', ['spawn', 'no_cron']);
|
|
||||||
|
|
||||||
// Ensure that worker.php is executed from the base path of the installation
|
// Ensure that worker.php is executed from the base path of the installation
|
||||||
chdir(dirname(__DIR__));
|
chdir(dirname(__DIR__));
|
||||||
|
|
||||||
|
@ -26,6 +25,8 @@ require dirname(__DIR__) . '/vendor/autoload.php';
|
||||||
|
|
||||||
$dice = (new Dice())->addRules(require(dirname(__DIR__) . '/static/dependencies.config.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.
|
Set up a cron job or scheduled task to run the worker once every 5-10 minutes in order to perform background processing.
|
||||||
Example:
|
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.
|
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
|
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:
|
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".
|
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.
|
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
|
#### 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:
|
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:
|
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.
|
After a server restart or any other failure, the daemon needs to be restarted.
|
||||||
This could be achieved by a cronjob.
|
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 \
|
> */10 * * * * cd /var/www/friendica/friendica/ && sudo -u www-data /usr/bin/php \
|
||||||
> -d suhosin.executor.func.blacklist=none \
|
> -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
|
> This worked well for simple test cases, but the friendica-cron still failed
|
||||||
> with a fatal error:
|
> 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',
|
> (attacker 'REMOTE_ADDR not set', file '/var/www/friendica/friendica/boot.php',
|
||||||
> line 1341)
|
> 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
|
> These scripts themselves also use `proc_open` and fail, because they are NOT
|
||||||
> called with `-d suhosin.executor.func.blacklist=none`.
|
> 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.
|
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.
|
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'.
|
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.
|
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.
|
||||||
|
|
|
@ -55,9 +55,9 @@ You should see an output like this:
|
||||||
|
|
||||||
Finally, you may also want to optimise your database with the following command: ``mysqloptimize -p friendica-db``
|
Finally, you may also want to optimise your database with the following command: ``mysqloptimize -p friendica-db``
|
||||||
|
|
||||||
### Going offline
|
### Going offline
|
||||||
Stop background tasks and put your server in maintenance mode.
|
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."``
|
2. Put your server into maintenance mode: ``bin/console maintenance 1 "We are currently upgrading our system and will be back soon."``
|
||||||
|
|
||||||
## Dumping DB
|
## Dumping DB
|
||||||
|
@ -73,12 +73,12 @@ Import your database on your new server: ``mysql -p friendica_db < your-friendic
|
||||||
|
|
||||||
### Configuration file
|
### Configuration file
|
||||||
Copy your old server's configuration file to ``config/local.config.php``.
|
Copy your old server's configuration file to ``config/local.config.php``.
|
||||||
Ensure the newly created database credentials are identical to the setting in the configuration file; otherwise update them accordingly.
|
Ensure the newly created database credentials are identical to the setting in the configuration file; otherwise update them accordingly.
|
||||||
|
|
||||||
### Cron job for worker
|
### Cron job for worker
|
||||||
Set up the required daily cron job.
|
Set up the required daily cron job.
|
||||||
Run ``crontab -e`` and add the following line according to your system specification
|
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
|
### DNS settings
|
||||||
Adjust your DNS records by pointing them to your new server.
|
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.
|
Erstelle einen Cron job oder einen regelmäßigen Task, um den Poller alle 5-10 Minuten im Hintergrund ablaufen zu lassen.
|
||||||
Beispiel:
|
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.
|
Ä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
|
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.
|
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.
|
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.
|
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.
|
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.
|
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.
|
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'));
|
$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);
|
$app->processRequest($request, $start_time);
|
||||||
|
|
|
@ -6,4 +6,4 @@ Description=Friendica Worker
|
||||||
User=http
|
User=http
|
||||||
#Adapt the path in the following line to your system, use 'which php' to find php path,
|
#Adapt the path in the following line to your system, use 'which php' to find php path,
|
||||||
#provide the absolute path for worker.php
|
#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\Capabilities\ICanHandleRequests;
|
||||||
use Friendica\Content\Nav;
|
use Friendica\Content\Nav;
|
||||||
use Friendica\Core\Config\Factory\Config;
|
use Friendica\Core\Config\Factory\Config;
|
||||||
|
use Friendica\Core\Container;
|
||||||
use Friendica\Core\Renderer;
|
use Friendica\Core\Renderer;
|
||||||
use Friendica\Core\Session\Capability\IHandleUserSessions;
|
use Friendica\Core\Session\Capability\IHandleUserSessions;
|
||||||
use Friendica\Core\Worker\Repository\Process as ProcessRepository;
|
|
||||||
use Friendica\Database\Definition\DbaDefinition;
|
use Friendica\Database\Definition\DbaDefinition;
|
||||||
use Friendica\Database\Definition\ViewDefinition;
|
use Friendica\Database\Definition\ViewDefinition;
|
||||||
use Friendica\Module\Maintenance;
|
use Friendica\Module\Maintenance;
|
||||||
|
@ -31,7 +31,6 @@ use Friendica\Core\Logger\Capability\LogChannel;
|
||||||
use Friendica\Core\PConfig\Capability\IManagePersonalConfigValues;
|
use Friendica\Core\PConfig\Capability\IManagePersonalConfigValues;
|
||||||
use Friendica\Core\System;
|
use Friendica\Core\System;
|
||||||
use Friendica\Core\Update;
|
use Friendica\Core\Update;
|
||||||
use Friendica\Core\Worker;
|
|
||||||
use Friendica\Module\Special\HTTPException as ModuleHTTPException;
|
use Friendica\Module\Special\HTTPException as ModuleHTTPException;
|
||||||
use Friendica\Network\HTTPException;
|
use Friendica\Network\HTTPException;
|
||||||
use Friendica\Protocol\ATProtocol\DID;
|
use Friendica\Protocol\ATProtocol\DID;
|
||||||
|
@ -61,13 +60,13 @@ class App
|
||||||
const CODENAME = 'Interrupted Fern';
|
const CODENAME = 'Interrupted Fern';
|
||||||
const VERSION = '2025.02-dev';
|
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;
|
private $container;
|
||||||
|
|
||||||
|
@ -122,26 +121,20 @@ class App
|
||||||
*/
|
*/
|
||||||
private $appHelper;
|
private $appHelper;
|
||||||
|
|
||||||
private function __construct(Dice $container)
|
private function __construct(Container $container)
|
||||||
{
|
{
|
||||||
$this->container = $container;
|
$this->container = $container;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function processRequest(ServerRequestInterface $request, float $start_time): void
|
public function processRequest(ServerRequestInterface $request, float $start_time): void
|
||||||
{
|
{
|
||||||
$this->setupContainerForAddons();
|
$this->container->addRule(Mode::class, [
|
||||||
|
|
||||||
$this->setupContainerForLogger(LogChannel::DEFAULT);
|
|
||||||
|
|
||||||
$this->container = $this->container->addRule(Mode::class, [
|
|
||||||
'call' => [
|
'call' => [
|
||||||
['determineRunMode', [false, $request->getServerParams()], Dice::CHAIN_CALL],
|
['determineRunMode', [false, $request->getServerParams()], Dice::CHAIN_CALL],
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->setupLegacyServiceLocator();
|
$this->container->setup(LogChannel::APP, false);
|
||||||
|
|
||||||
$this->registerErrorHandler();
|
|
||||||
|
|
||||||
$this->requestId = $this->container->create(Request::class)->getRequestId();
|
$this->requestId = $this->container->create(Request::class)->getRequestId();
|
||||||
$this->auth = $this->container->create(Authentication::class);
|
$this->auth = $this->container->create(Authentication::class);
|
||||||
|
@ -177,13 +170,7 @@ class App
|
||||||
|
|
||||||
public function processEjabberd(): void
|
public function processEjabberd(): void
|
||||||
{
|
{
|
||||||
$this->setupContainerForAddons();
|
$this->container->setup(LogChannel::AUTH_JABBERED, false);
|
||||||
|
|
||||||
$this->setupContainerForLogger(LogChannel::AUTH_JABBERED);
|
|
||||||
|
|
||||||
$this->setupLegacyServiceLocator();
|
|
||||||
|
|
||||||
$this->registerErrorHandler();
|
|
||||||
|
|
||||||
/** @var BasePath */
|
/** @var BasePath */
|
||||||
$basePath = $this->container->create(BasePath::class);
|
$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
|
private function registerTemplateEngine(): void
|
||||||
{
|
{
|
||||||
Renderer::registerTemplateEngine('Friendica\Render\FriendicaSmartyEngine');
|
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;
|
namespace Friendica\Console;
|
||||||
|
|
||||||
|
use Asika\SimpleConsole\CommandArgsException;
|
||||||
use Friendica\App\Mode;
|
use Friendica\App\Mode;
|
||||||
use Friendica\Core\Config\Capability\IManageConfigValues;
|
use Friendica\Core\Config\Capability\IManageConfigValues;
|
||||||
use Asika\SimpleConsole\Console;
|
|
||||||
use Friendica\Core\KeyValueStorage\Capability\IManageKeyValuePairs;
|
use Friendica\Core\KeyValueStorage\Capability\IManageKeyValuePairs;
|
||||||
|
use Friendica\Core\Logger\Capability\LogChannel;
|
||||||
use Friendica\Core\System;
|
use Friendica\Core\System;
|
||||||
use Friendica\Core\Update;
|
use Friendica\Core\Update;
|
||||||
use Friendica\Core\Worker;
|
use Friendica\Core\Worker;
|
||||||
|
@ -26,8 +27,10 @@ use RuntimeException;
|
||||||
/**
|
/**
|
||||||
* Console command for interacting with the daemon
|
* 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 Mode $mode;
|
||||||
private IManageConfigValues $config;
|
private IManageConfigValues $config;
|
||||||
private IManageKeyValuePairs $keyValue;
|
private IManageKeyValuePairs $keyValue;
|
||||||
|
@ -90,9 +93,7 @@ HELP;
|
||||||
|
|
||||||
protected function doExecute()
|
protected function doExecute()
|
||||||
{
|
{
|
||||||
if ($this->executable !== 'bin/console.php') {
|
$this->checkDeprecated('daemon');
|
||||||
$this->out(sprintf("'%s' is deprecated and will removed. Please use 'bin/console.php daemon' instead", $this->executable));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->mode->isInstall()) {
|
if ($this->mode->isInstall()) {
|
||||||
throw new RuntimeException("Friendica isn't properly installed yet");
|
throw new RuntimeException("Friendica isn't properly installed yet");
|
||||||
|
@ -120,7 +121,7 @@ HELP;
|
||||||
$foreground = $this->getOption(['f', 'foreground']) ?? false;
|
$foreground = $this->getOption(['f', 'foreground']) ?? false;
|
||||||
|
|
||||||
if (empty($daemonMode)) {
|
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);
|
$this->daemon->init($pidfile);
|
||||||
|
|
|
@ -12,9 +12,9 @@ namespace Friendica\Console;
|
||||||
use Friendica\App\Mode;
|
use Friendica\App\Mode;
|
||||||
use Friendica\Core\Addon;
|
use Friendica\Core\Addon;
|
||||||
use Friendica\Core\Config\Capability\IManageConfigValues;
|
use Friendica\Core\Config\Capability\IManageConfigValues;
|
||||||
use Asika\SimpleConsole\Console;
|
|
||||||
use Friendica\Core\Hook;
|
use Friendica\Core\Hook;
|
||||||
use Friendica\Core\KeyValueStorage\Capability\IManageKeyValuePairs;
|
use Friendica\Core\KeyValueStorage\Capability\IManageKeyValuePairs;
|
||||||
|
use Friendica\Core\Logger\Capability\LogChannel;
|
||||||
use Friendica\Protocol\ATProtocol\Jetstream;
|
use Friendica\Protocol\ATProtocol\Jetstream;
|
||||||
use Friendica\System\Daemon as SysDaemon;
|
use Friendica\System\Daemon as SysDaemon;
|
||||||
use RuntimeException;
|
use RuntimeException;
|
||||||
|
@ -22,8 +22,10 @@ use RuntimeException;
|
||||||
/**
|
/**
|
||||||
* Console command for interacting with the daemon
|
* 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 Mode $mode;
|
||||||
private IManageConfigValues $config;
|
private IManageConfigValues $config;
|
||||||
private IManageKeyValuePairs $keyValue;
|
private IManageKeyValuePairs $keyValue;
|
||||||
|
@ -77,9 +79,7 @@ HELP;
|
||||||
|
|
||||||
protected function doExecute()
|
protected function doExecute()
|
||||||
{
|
{
|
||||||
if ($this->executable !== 'bin/console.php') {
|
$this->checkDeprecated('jetstream');
|
||||||
$this->out(sprintf("'%s' is deprecated and will removed. Please use 'bin/console.php jetstream' instead", $this->executable));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->mode->isInstall()) {
|
if ($this->mode->isInstall()) {
|
||||||
throw new RuntimeException("Friendica isn't properly installed yet");
|
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;
|
namespace Friendica\Core;
|
||||||
|
|
||||||
use Dice\Dice;
|
|
||||||
use Friendica;
|
use Friendica;
|
||||||
use Friendica\App;
|
use Friendica\App;
|
||||||
|
use Friendica\Core\Logger\Capability\LogChannel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Description of Console
|
* Description of Console
|
||||||
*/
|
*/
|
||||||
class Console extends \Asika\SimpleConsole\Console
|
class Console extends \Asika\SimpleConsole\Console
|
||||||
{
|
{
|
||||||
// Disables the default help handling
|
/** @var string The default executable for a console call */
|
||||||
protected $helpOptions = [];
|
private const CONSOLE_EXECUTABLE = 'bin/console.php';
|
||||||
protected $customHelpOptions = ['h', 'help', '?'];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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()
|
protected function getHelp()
|
||||||
{
|
{
|
||||||
|
@ -39,6 +50,7 @@ Commands:
|
||||||
createdoxygen Generate Doxygen headers
|
createdoxygen Generate Doxygen headers
|
||||||
daemon Interact with the Friendica daemon
|
daemon Interact with the Friendica daemon
|
||||||
jetstream Interact with the Jetstream daemon
|
jetstream Interact with the Jetstream daemon
|
||||||
|
worker Start worker process
|
||||||
dbstructure Do database updates
|
dbstructure Do database updates
|
||||||
docbloxerrorchecker Check the file tree for DocBlox errors
|
docbloxerrorchecker Check the file tree for DocBlox errors
|
||||||
extract Generate translation string file for the Friendica project (deprecated)
|
extract Generate translation string file for the Friendica project (deprecated)
|
||||||
|
@ -68,7 +80,7 @@ HELP;
|
||||||
return $help;
|
return $help;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected $subConsoles = [
|
protected array $subConsoles = [
|
||||||
'addon' => Friendica\Console\Addon::class,
|
'addon' => Friendica\Console\Addon::class,
|
||||||
'archivecontact' => Friendica\Console\ArchiveContact::class,
|
'archivecontact' => Friendica\Console\ArchiveContact::class,
|
||||||
'autoinstall' => Friendica\Console\AutomaticInstallation::class,
|
'autoinstall' => Friendica\Console\AutomaticInstallation::class,
|
||||||
|
@ -79,6 +91,7 @@ HELP;
|
||||||
'createdoxygen' => Friendica\Console\CreateDoxygen::class,
|
'createdoxygen' => Friendica\Console\CreateDoxygen::class,
|
||||||
'daemon' => Friendica\Console\Daemon::class,
|
'daemon' => Friendica\Console\Daemon::class,
|
||||||
'jetstream' => Friendica\Console\JetstreamDaemon::class,
|
'jetstream' => Friendica\Console\JetstreamDaemon::class,
|
||||||
|
'worker' => Friendica\Console\Worker::class,
|
||||||
'docbloxerrorchecker' => Friendica\Console\DocBloxErrorChecker::class,
|
'docbloxerrorchecker' => Friendica\Console\DocBloxErrorChecker::class,
|
||||||
'dbstructure' => Friendica\Console\DatabaseStructure::class,
|
'dbstructure' => Friendica\Console\DatabaseStructure::class,
|
||||||
'extract' => Friendica\Console\Extract::class,
|
'extract' => Friendica\Console\Extract::class,
|
||||||
|
@ -104,14 +117,18 @@ HELP;
|
||||||
/**
|
/**
|
||||||
* CliInput Friendica constructor.
|
* CliInput Friendica constructor.
|
||||||
*
|
*
|
||||||
* @param Dice $dice The DI library
|
* @param Container $container The Friendica container
|
||||||
* @param array $argv
|
|
||||||
*/
|
*/
|
||||||
public function __construct(Dice $dice, array $argv = null)
|
public function __construct(Container $container, array $argv = null)
|
||||||
{
|
{
|
||||||
parent::__construct($argv);
|
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
|
protected function doExecute(): int
|
||||||
|
@ -170,8 +187,14 @@ HELP;
|
||||||
|
|
||||||
$className = $this->subConsoles[$command];
|
$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 */
|
/** @var Console $subconsole */
|
||||||
$subconsole = $this->dice->create($className, [$subargs]);
|
$subconsole = $this->container->create($className, [$subargs]);
|
||||||
|
|
||||||
foreach ($this->options as $name => $value) {
|
foreach ($this->options as $name => $value) {
|
||||||
$subconsole->setOption($name, $value);
|
$subconsole->setOption($name, $value);
|
||||||
|
@ -179,5 +202,4 @@ HELP;
|
||||||
|
|
||||||
return $subconsole;
|
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'
|
* Executes a child process with 'proc_open'
|
||||||
*
|
*
|
||||||
* @param string $command The command to execute
|
* @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')) {
|
if (!function_exists('proc_open')) {
|
||||||
$this->logger->warning('"proc_open" not available - quitting');
|
$this->logger->warning('"proc_open" not available - quitting');
|
||||||
|
@ -175,7 +176,11 @@ class System
|
||||||
|
|
||||||
$cmdline = $this->config->get('config', 'php_path', 'php') . ' ' . escapeshellarg($command);
|
$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) {
|
if (!is_null($value) && is_bool($value) && !$value) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -225,7 +230,7 @@ class System
|
||||||
$trace = array_slice($trace, 2 + $offset);
|
$trace = array_slice($trace, 2 + $offset);
|
||||||
|
|
||||||
$callstack = [];
|
$callstack = [];
|
||||||
$previous = ['class' => '', 'function' => '', 'database' => false];
|
$previous = ['class' => '', 'function' => '', 'database' => false];
|
||||||
|
|
||||||
// The ignore list contains all functions that are only wrapper functions
|
// The ignore list contains all functions that are only wrapper functions
|
||||||
$ignore = ['call_user_func_array'];
|
$ignore = ['call_user_func_array'];
|
||||||
|
@ -245,15 +250,15 @@ class System
|
||||||
// Don't show multiple calls from the Database classes to show the essential parts of the callstack
|
// Don't show multiple calls from the Database classes to show the essential parts of the callstack
|
||||||
$func['database'] = in_array($func['class'], ['Friendica\Database\DBA', 'Friendica\Database\Database']);
|
$func['database'] = in_array($func['class'], ['Friendica\Database\DBA', 'Friendica\Database\Database']);
|
||||||
if ($full || !$previous['database'] || !$func['database']) {
|
if ($full || !$previous['database'] || !$func['database']) {
|
||||||
$classparts = explode("\\", $func['class']);
|
$classparts = explode("\\", $func['class']);
|
||||||
$callstack[] = array_pop($classparts).'::'.$func['function'] . (isset($func['line']) ? ' (' . $func['line'] . ')' : '');
|
$callstack[] = array_pop($classparts).'::'.$func['function'] . (isset($func['line']) ? ' (' . $func['line'] . ')' : '');
|
||||||
$previous = $func;
|
$previous = $func;
|
||||||
}
|
}
|
||||||
} elseif (!in_array($func['function'], $ignore)) {
|
} elseif (!in_array($func['function'], $ignore)) {
|
||||||
$func['database'] = ($func['function'] == 'q');
|
$func['database'] = ($func['function'] == 'q');
|
||||||
$callstack[] = $func['function'] . (isset($func['line']) ? ' (' . $func['line'] . ')' : '');
|
$callstack[] = $func['function'] . (isset($func['line']) ? ' (' . $func['line'] . ')' : '');
|
||||||
$func['class'] = '';
|
$func['class'] = '';
|
||||||
$previous = $func;
|
$previous = $func;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,10 +277,13 @@ class System
|
||||||
*/
|
*/
|
||||||
public static function echoResponse(ResponseInterface $response)
|
public static function echoResponse(ResponseInterface $response)
|
||||||
{
|
{
|
||||||
header(sprintf("HTTP/%s %s %s",
|
header(
|
||||||
|
sprintf(
|
||||||
|
"HTTP/%s %s %s",
|
||||||
$response->getProtocolVersion(),
|
$response->getProtocolVersion(),
|
||||||
$response->getStatusCode(),
|
$response->getStatusCode(),
|
||||||
$response->getReasonPhrase())
|
$response->getReasonPhrase()
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
foreach ($response->getHeaders() as $key => $header) {
|
foreach ($response->getHeaders() as $key => $header) {
|
||||||
|
@ -696,7 +704,7 @@ class System
|
||||||
|
|
||||||
if (DI::config()->get('system', 'tosdisplay')) {
|
if (DI::config()->get('system', 'tosdisplay')) {
|
||||||
$rulelist = DI::config()->get('system', 'tosrules') ?: DI::config()->get('system', 'tostext');
|
$rulelist = DI::config()->get('system', 'tosrules') ?: DI::config()->get('system', 'tostext');
|
||||||
$msg = BBCode::toPlaintext($rulelist, false);
|
$msg = BBCode::toPlaintext($rulelist, false);
|
||||||
foreach (explode("\n", trim($msg)) as $line) {
|
foreach (explode("\n", trim($msg)) as $line) {
|
||||||
$line = trim($line);
|
$line = trim($line);
|
||||||
if ($line) {
|
if ($line) {
|
||||||
|
|
|
@ -45,11 +45,11 @@ class Worker
|
||||||
const LAST_CHECK = 'worker::check';
|
const LAST_CHECK = 'worker::check';
|
||||||
|
|
||||||
private static $up_start;
|
private static $up_start;
|
||||||
private static $db_duration = 0;
|
private static $db_duration = 0;
|
||||||
private static $db_duration_count = 0;
|
private static $db_duration_count = 0;
|
||||||
private static $db_duration_write = 0;
|
private static $db_duration_write = 0;
|
||||||
private static $db_duration_stat = 0;
|
private static $db_duration_stat = 0;
|
||||||
private static $lock_duration = 0;
|
private static $lock_duration = 0;
|
||||||
private static $last_update;
|
private static $last_update;
|
||||||
private static $state;
|
private static $state;
|
||||||
/** @var Process */
|
/** @var Process */
|
||||||
|
@ -93,7 +93,7 @@ class Worker
|
||||||
Worker\Cron::run();
|
Worker\Cron::run();
|
||||||
}
|
}
|
||||||
|
|
||||||
$last_check = $starttime = time();
|
$last_check = $starttime = time();
|
||||||
self::$state = self::STATE_STARTUP;
|
self::$state = self::STATE_STARTUP;
|
||||||
|
|
||||||
// We fetch the next queue entry that is about to be executed
|
// We fetch the next queue entry that is about to be executed
|
||||||
|
@ -116,7 +116,7 @@ class Worker
|
||||||
self::findWorkerProcesses();
|
self::findWorkerProcesses();
|
||||||
DI::lock()->release(self::LOCK_PROCESS);
|
DI::lock()->release(self::LOCK_PROCESS);
|
||||||
self::$state = self::STATE_REFETCH;
|
self::$state = self::STATE_REFETCH;
|
||||||
$refetched = true;
|
$refetched = true;
|
||||||
} else {
|
} else {
|
||||||
self::$state = self::STATE_SHORT_LOOP;
|
self::$state = self::STATE_SHORT_LOOP;
|
||||||
}
|
}
|
||||||
|
@ -127,7 +127,7 @@ class Worker
|
||||||
self::$state = self::STATE_LONG_LOOP;
|
self::$state = self::STATE_LONG_LOOP;
|
||||||
|
|
||||||
if (DI::lock()->acquire(self::LOCK_WORKER, 0)) {
|
if (DI::lock()->acquire(self::LOCK_WORKER, 0)) {
|
||||||
// Count active workers and compare them with a maximum value that depends on the load
|
// Count active workers and compare them with a maximum value that depends on the load
|
||||||
if (self::tooMuchWorkers()) {
|
if (self::tooMuchWorkers()) {
|
||||||
Logger::info('Active worker limit reached, quitting.');
|
Logger::info('Active worker limit reached, quitting.');
|
||||||
DI::lock()->release(self::LOCK_WORKER);
|
DI::lock()->release(self::LOCK_WORKER);
|
||||||
|
@ -209,7 +209,7 @@ class Worker
|
||||||
*/
|
*/
|
||||||
public static function entriesExists(): bool
|
public static function entriesExists(): bool
|
||||||
{
|
{
|
||||||
$stamp = (float)microtime(true);
|
$stamp = (float)microtime(true);
|
||||||
$exists = DBA::exists('workerqueue', ["NOT `done` AND `pid` = 0 AND `next_try` < ?", DateTimeFormat::utcNow()]);
|
$exists = DBA::exists('workerqueue', ["NOT `done` AND `pid` = 0 AND `next_try` < ?", DateTimeFormat::utcNow()]);
|
||||||
self::$db_duration += (microtime(true) - $stamp);
|
self::$db_duration += (microtime(true) - $stamp);
|
||||||
return $exists;
|
return $exists;
|
||||||
|
@ -253,8 +253,8 @@ class Worker
|
||||||
*/
|
*/
|
||||||
private static function highestPriority(): int
|
private static function highestPriority(): int
|
||||||
{
|
{
|
||||||
$stamp = (float)microtime(true);
|
$stamp = (float)microtime(true);
|
||||||
$condition = ["`pid` = 0 AND NOT `done` AND `next_try` < ?", DateTimeFormat::utcNow()];
|
$condition = ["`pid` = 0 AND NOT `done` AND `next_try` < ?", DateTimeFormat::utcNow()];
|
||||||
$workerqueue = DBA::selectFirst('workerqueue', ['priority'], $condition, ['order' => ['priority']]);
|
$workerqueue = DBA::selectFirst('workerqueue', ['priority'], $condition, ['order' => ['priority']]);
|
||||||
self::$db_duration += (microtime(true) - $stamp);
|
self::$db_duration += (microtime(true) - $stamp);
|
||||||
if (DBA::isResult($workerqueue)) {
|
if (DBA::isResult($workerqueue)) {
|
||||||
|
@ -359,7 +359,7 @@ class Worker
|
||||||
self::$last_update = strtotime($queue['executed']);
|
self::$last_update = strtotime($queue['executed']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$age = (time() - self::$last_update) / 60;
|
$age = (time() - self::$last_update) / 60;
|
||||||
self::$last_update = time();
|
self::$last_update = time();
|
||||||
|
|
||||||
if ($age > 1) {
|
if ($age > 1) {
|
||||||
|
@ -373,7 +373,7 @@ class Worker
|
||||||
|
|
||||||
self::execFunction($queue, $include, $argv, true);
|
self::execFunction($queue, $include, $argv, true);
|
||||||
|
|
||||||
$stamp = (float)microtime(true);
|
$stamp = (float)microtime(true);
|
||||||
$condition = ["`id` = ? AND `next_try` < ?", $queue['id'], DateTimeFormat::utcNow()];
|
$condition = ["`id` = ? AND `next_try` < ?", $queue['id'], DateTimeFormat::utcNow()];
|
||||||
if (DBA::update('workerqueue', ['done' => true], $condition)) {
|
if (DBA::update('workerqueue', ['done' => true], $condition)) {
|
||||||
DI::keyValue()->set('last_worker_execution', DateTimeFormat::utcNow());
|
DI::keyValue()->set('last_worker_execution', DateTimeFormat::utcNow());
|
||||||
|
@ -403,7 +403,7 @@ class Worker
|
||||||
self::$last_update = strtotime($queue['executed']);
|
self::$last_update = strtotime($queue['executed']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$age = (time() - self::$last_update) / 60;
|
$age = (time() - self::$last_update) / 60;
|
||||||
self::$last_update = time();
|
self::$last_update = time();
|
||||||
|
|
||||||
if ($age > 1) {
|
if ($age > 1) {
|
||||||
|
@ -595,21 +595,21 @@ class Worker
|
||||||
|
|
||||||
self::coolDown();
|
self::coolDown();
|
||||||
|
|
||||||
self::$up_start = microtime(true);
|
self::$up_start = microtime(true);
|
||||||
self::$db_duration = 0;
|
self::$db_duration = 0;
|
||||||
self::$db_duration_count = 0;
|
self::$db_duration_count = 0;
|
||||||
self::$db_duration_stat = 0;
|
self::$db_duration_stat = 0;
|
||||||
self::$db_duration_write = 0;
|
self::$db_duration_write = 0;
|
||||||
self::$lock_duration = 0;
|
self::$lock_duration = 0;
|
||||||
|
|
||||||
if ($duration > 3600) {
|
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) {
|
} 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) {
|
} 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) {
|
} 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)]);
|
Logger::info('Process done.', ['function' => $funcname, 'priority' => $queue['priority'], 'retrial' => $queue['retrial'], 'id' => $queue['id'], 'duration' => round($duration, 3)]);
|
||||||
|
@ -639,7 +639,7 @@ class Worker
|
||||||
}
|
}
|
||||||
// Or it can be granted. This overrides the system variable
|
// Or it can be granted. This overrides the system variable
|
||||||
$stamp = (float)microtime(true);
|
$stamp = (float)microtime(true);
|
||||||
$r = DBA::p('SHOW GRANTS');
|
$r = DBA::p('SHOW GRANTS');
|
||||||
self::$db_duration += (microtime(true) - $stamp);
|
self::$db_duration += (microtime(true) - $stamp);
|
||||||
while ($grants = DBA::fetch($r)) {
|
while ($grants = DBA::fetch($r)) {
|
||||||
$grant = array_pop($grants);
|
$grant = array_pop($grants);
|
||||||
|
@ -655,7 +655,7 @@ class Worker
|
||||||
$stamp = (float)microtime(true);
|
$stamp = (float)microtime(true);
|
||||||
$used = 0;
|
$used = 0;
|
||||||
$sleep = 0;
|
$sleep = 0;
|
||||||
$data = DBA::p("SHOW PROCESSLIST");
|
$data = DBA::p("SHOW PROCESSLIST");
|
||||||
while ($row = DBA::fetch($data)) {
|
while ($row = DBA::fetch($data)) {
|
||||||
if ($row['Command'] != 'Sleep') {
|
if ($row['Command'] != 'Sleep') {
|
||||||
++$used;
|
++$used;
|
||||||
|
@ -734,13 +734,13 @@ class Worker
|
||||||
* With exponent 1, you could have 20 max queues at idle and 13 at 37% of $maxsysload.
|
* With exponent 1, you could have 20 max queues at idle and 13 at 37% of $maxsysload.
|
||||||
*/
|
*/
|
||||||
$exponent = intval(DI::config()->get('system', 'worker_load_exponent', 3));
|
$exponent = intval(DI::config()->get('system', 'worker_load_exponent', 3));
|
||||||
$slope = pow(max(0, $maxsysload - $load) / $maxsysload, $exponent);
|
$slope = pow(max(0, $maxsysload - $load) / $maxsysload, $exponent);
|
||||||
$queues = intval(ceil($slope * $maxqueues));
|
$queues = intval(ceil($slope * $maxqueues));
|
||||||
|
|
||||||
$processlist = '';
|
$processlist = '';
|
||||||
|
|
||||||
if (DI::config()->get('system', 'worker_jpm')) {
|
if (DI::config()->get('system', 'worker_jpm')) {
|
||||||
$intervals = explode(',', DI::config()->get('system', 'worker_jpm_range'));
|
$intervals = explode(',', DI::config()->get('system', 'worker_jpm_range'));
|
||||||
$jobs_per_minute = [];
|
$jobs_per_minute = [];
|
||||||
foreach ($intervals as $interval) {
|
foreach ($intervals as $interval) {
|
||||||
if ($interval == 0) {
|
if ($interval == 0) {
|
||||||
|
@ -750,7 +750,7 @@ class Worker
|
||||||
}
|
}
|
||||||
|
|
||||||
$stamp = (float)microtime(true);
|
$stamp = (float)microtime(true);
|
||||||
$jobs = DBA::count('workerqueue', ["`done` AND `executed` > ?", DateTimeFormat::utc('now - ' . $interval . ' minute')]);
|
$jobs = DBA::count('workerqueue', ["`done` AND `executed` > ?", DateTimeFormat::utc('now - ' . $interval . ' minute')]);
|
||||||
self::$db_duration += (microtime(true) - $stamp);
|
self::$db_duration += (microtime(true) - $stamp);
|
||||||
self::$db_duration_stat += (microtime(true) - $stamp);
|
self::$db_duration_stat += (microtime(true) - $stamp);
|
||||||
$jobs_per_minute[$interval] = number_format($jobs / $interval, 0);
|
$jobs_per_minute[$interval] = number_format($jobs / $interval, 0);
|
||||||
|
@ -769,11 +769,11 @@ class Worker
|
||||||
$waiting_processes = 0;
|
$waiting_processes = 0;
|
||||||
// Now adding all processes with workerqueue entries
|
// Now adding all processes with workerqueue entries
|
||||||
$stamp = (float)microtime(true);
|
$stamp = (float)microtime(true);
|
||||||
$jobs = DBA::p("SELECT COUNT(*) AS `entries`, `priority` FROM `workerqueue` WHERE NOT `done` GROUP BY `priority`");
|
$jobs = DBA::p("SELECT COUNT(*) AS `entries`, `priority` FROM `workerqueue` WHERE NOT `done` GROUP BY `priority`");
|
||||||
self::$db_duration += (microtime(true) - $stamp);
|
self::$db_duration += (microtime(true) - $stamp);
|
||||||
self::$db_duration_stat += (microtime(true) - $stamp);
|
self::$db_duration_stat += (microtime(true) - $stamp);
|
||||||
while ($entry = DBA::fetch($jobs)) {
|
while ($entry = DBA::fetch($jobs)) {
|
||||||
$stamp = (float)microtime(true);
|
$stamp = (float)microtime(true);
|
||||||
$running = DBA::count('workerqueue-view', ['priority' => $entry['priority']]);
|
$running = DBA::count('workerqueue-view', ['priority' => $entry['priority']]);
|
||||||
self::$db_duration += (microtime(true) - $stamp);
|
self::$db_duration += (microtime(true) - $stamp);
|
||||||
self::$db_duration_stat += (microtime(true) - $stamp);
|
self::$db_duration_stat += (microtime(true) - $stamp);
|
||||||
|
@ -783,9 +783,9 @@ class Worker
|
||||||
}
|
}
|
||||||
DBA::close($jobs);
|
DBA::close($jobs);
|
||||||
} else {
|
} else {
|
||||||
$waiting_processes = self::totalEntries();
|
$waiting_processes = self::totalEntries();
|
||||||
$stamp = (float)microtime(true);
|
$stamp = (float)microtime(true);
|
||||||
$jobs = DBA::p("SELECT COUNT(*) AS `running`, `priority` FROM `workerqueue-view` GROUP BY `priority` ORDER BY `priority`");
|
$jobs = DBA::p("SELECT COUNT(*) AS `running`, `priority` FROM `workerqueue-view` GROUP BY `priority` ORDER BY `priority`");
|
||||||
self::$db_duration += (microtime(true) - $stamp);
|
self::$db_duration += (microtime(true) - $stamp);
|
||||||
self::$db_duration_stat += (microtime(true) - $stamp);
|
self::$db_duration_stat += (microtime(true) - $stamp);
|
||||||
|
|
||||||
|
@ -871,7 +871,7 @@ class Worker
|
||||||
*/
|
*/
|
||||||
private static function getWorkerPIDList(): array
|
private static function getWorkerPIDList(): array
|
||||||
{
|
{
|
||||||
$ids = [];
|
$ids = [];
|
||||||
$stamp = (float)microtime(true);
|
$stamp = (float)microtime(true);
|
||||||
|
|
||||||
$queues = DBA::p("SELECT `process`.`pid`, COUNT(`workerqueue`.`pid`) AS `entries` FROM `process`
|
$queues = DBA::p("SELECT `process`.`pid`, COUNT(`workerqueue`.`pid`) AS `entries` FROM `process`
|
||||||
|
@ -896,7 +896,7 @@ class Worker
|
||||||
private static function getWaitingJobForPID()
|
private static function getWaitingJobForPID()
|
||||||
{
|
{
|
||||||
$stamp = (float)microtime(true);
|
$stamp = (float)microtime(true);
|
||||||
$r = DBA::select('workerqueue', [], ['pid' => getmypid(), 'done' => false]);
|
$r = DBA::select('workerqueue', [], ['pid' => getmypid(), 'done' => false]);
|
||||||
self::$db_duration += (microtime(true) - $stamp);
|
self::$db_duration += (microtime(true) - $stamp);
|
||||||
if (DBA::isResult($r)) {
|
if (DBA::isResult($r)) {
|
||||||
return DBA::toArray($r);
|
return DBA::toArray($r);
|
||||||
|
@ -920,10 +920,10 @@ class Worker
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
$ids = [];
|
$ids = [];
|
||||||
$stamp = (float)microtime(true);
|
$stamp = (float)microtime(true);
|
||||||
$condition = ["`priority` = ? AND `pid` = 0 AND NOT `done` AND `next_try` < ?", $priority, DateTimeFormat::utcNow()];
|
$condition = ["`priority` = ? AND `pid` = 0 AND NOT `done` AND `next_try` < ?", $priority, DateTimeFormat::utcNow()];
|
||||||
$tasks = DBA::select('workerqueue', ['id', 'command', 'parameter'], $condition, ['limit' => $limit, 'order' => ['retrial', 'created']]);
|
$tasks = DBA::select('workerqueue', ['id', 'command', 'parameter'], $condition, ['limit' => $limit, 'order' => ['retrial', 'created']]);
|
||||||
self::$db_duration += (microtime(true) - $stamp);
|
self::$db_duration += (microtime(true) - $stamp);
|
||||||
while ($task = DBA::fetch($tasks)) {
|
while ($task = DBA::fetch($tasks)) {
|
||||||
$ids[] = $task['id'];
|
$ids[] = $task['id'];
|
||||||
|
@ -952,7 +952,7 @@ class Worker
|
||||||
*/
|
*/
|
||||||
private static function nextPriority()
|
private static function nextPriority()
|
||||||
{
|
{
|
||||||
$waiting = [];
|
$waiting = [];
|
||||||
$priorities = [self::PRIORITY_CRITICAL, self::PRIORITY_HIGH, self::PRIORITY_MEDIUM, self::PRIORITY_LOW, self::PRIORITY_NEGLIGIBLE];
|
$priorities = [self::PRIORITY_CRITICAL, self::PRIORITY_HIGH, self::PRIORITY_MEDIUM, self::PRIORITY_LOW, self::PRIORITY_NEGLIGIBLE];
|
||||||
foreach ($priorities as $priority) {
|
foreach ($priorities as $priority) {
|
||||||
$stamp = (float)microtime(true);
|
$stamp = (float)microtime(true);
|
||||||
|
@ -966,10 +966,10 @@ class Worker
|
||||||
return self::PRIORITY_CRITICAL;
|
return self::PRIORITY_CRITICAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
$running = [];
|
$running = [];
|
||||||
$running_total = 0;
|
$running_total = 0;
|
||||||
$stamp = (float)microtime(true);
|
$stamp = (float)microtime(true);
|
||||||
$processes = DBA::p("SELECT COUNT(DISTINCT(`pid`)) AS `running`, `priority` FROM `workerqueue-view` GROUP BY `priority`");
|
$processes = DBA::p("SELECT COUNT(DISTINCT(`pid`)) AS `running`, `priority` FROM `workerqueue-view` GROUP BY `priority`");
|
||||||
self::$db_duration += (microtime(true) - $stamp);
|
self::$db_duration += (microtime(true) - $stamp);
|
||||||
while ($process = DBA::fetch($processes)) {
|
while ($process = DBA::fetch($processes)) {
|
||||||
$running[$process['priority']] = $process['running'];
|
$running[$process['priority']] = $process['running'];
|
||||||
|
@ -984,9 +984,9 @@ class Worker
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$active = max(self::activeWorkers(), $running_total);
|
$active = max(self::activeWorkers(), $running_total);
|
||||||
$priorities = max(count($waiting), count($running));
|
$priorities = max(count($waiting), count($running));
|
||||||
$exponent = 2;
|
$exponent = 2;
|
||||||
|
|
||||||
$total = 0;
|
$total = 0;
|
||||||
for ($i = 1; $i <= $priorities; ++$i) {
|
for ($i = 1; $i <= $priorities; ++$i) {
|
||||||
|
@ -1037,7 +1037,7 @@ class Worker
|
||||||
}
|
}
|
||||||
$limit = $fetch_limit * count($pids);
|
$limit = $fetch_limit * count($pids);
|
||||||
} else {
|
} else {
|
||||||
$pids = [getmypid()];
|
$pids = [getmypid()];
|
||||||
$limit = $fetch_limit;
|
$limit = $fetch_limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1046,9 +1046,9 @@ class Worker
|
||||||
|
|
||||||
// If there is not enough results we check without priority limit
|
// If there is not enough results we check without priority limit
|
||||||
if ($limit > 0) {
|
if ($limit > 0) {
|
||||||
$stamp = (float)microtime(true);
|
$stamp = (float)microtime(true);
|
||||||
$condition = ["`pid` = 0 AND NOT `done` AND `next_try` < ?", DateTimeFormat::utcNow()];
|
$condition = ["`pid` = 0 AND NOT `done` AND `next_try` < ?", DateTimeFormat::utcNow()];
|
||||||
$tasks = DBA::select('workerqueue', ['id', 'command', 'parameter'], $condition, ['limit' => $limit, 'order' => ['priority', 'retrial', 'created']]);
|
$tasks = DBA::select('workerqueue', ['id', 'command', 'parameter'], $condition, ['limit' => $limit, 'order' => ['priority', 'retrial', 'created']]);
|
||||||
self::$db_duration += (microtime(true) - $stamp);
|
self::$db_duration += (microtime(true) - $stamp);
|
||||||
|
|
||||||
while ($task = DBA::fetch($tasks)) {
|
while ($task = DBA::fetch($tasks)) {
|
||||||
|
@ -1083,8 +1083,11 @@ class Worker
|
||||||
$stamp = (float)microtime(true);
|
$stamp = (float)microtime(true);
|
||||||
foreach ($worker as $worker_pid => $worker_ids) {
|
foreach ($worker as $worker_pid => $worker_ids) {
|
||||||
Logger::info('Set queue entry', ['pid' => $worker_pid, 'ids' => $worker_ids]);
|
Logger::info('Set queue entry', ['pid' => $worker_pid, 'ids' => $worker_ids]);
|
||||||
DBA::update('workerqueue', ['executed' => DateTimeFormat::utcNow(), 'pid' => $worker_pid],
|
DBA::update(
|
||||||
['id' => $worker_ids, 'done' => false, 'pid' => 0]);
|
'workerqueue',
|
||||||
|
['executed' => DateTimeFormat::utcNow(), 'pid' => $worker_pid],
|
||||||
|
['id' => $worker_ids, 'done' => false, 'pid' => 0]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
self::$db_duration += (microtime(true) - $stamp);
|
self::$db_duration += (microtime(true) - $stamp);
|
||||||
self::$db_duration_write += (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')) {
|
if (Worker\Daemon::isMode() && DI::config()->get('system', 'worker_fork')) {
|
||||||
self::forkProcess($do_cron);
|
self::forkProcess($do_cron);
|
||||||
} else {
|
} 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()) {
|
if (Worker\Daemon::isMode()) {
|
||||||
Worker\IPC::SetJobState(false);
|
Worker\IPC::SetJobState(false);
|
||||||
|
@ -1246,9 +1249,9 @@ class Worker
|
||||||
|
|
||||||
$priority = self::PRIORITY_MEDIUM;
|
$priority = self::PRIORITY_MEDIUM;
|
||||||
// Don't fork from frontend tasks by default
|
// Don't fork from frontend tasks by default
|
||||||
$dont_fork = DI::config()->get('system', 'worker_dont_fork', false) || !DI::mode()->isBackend();
|
$dont_fork = DI::config()->get('system', 'worker_dont_fork', false) || !DI::mode()->isBackend();
|
||||||
$created = DateTimeFormat::utcNow();
|
$created = DateTimeFormat::utcNow();
|
||||||
$delayed = DBA::NULL_DATETIME;
|
$delayed = DBA::NULL_DATETIME;
|
||||||
$force_priority = false;
|
$force_priority = false;
|
||||||
|
|
||||||
$run_parameter = array_shift($args);
|
$run_parameter = array_shift($args);
|
||||||
|
@ -1275,10 +1278,10 @@ class Worker
|
||||||
throw new \InvalidArgumentException('Priority number or task parameter array expected as first argument');
|
throw new \InvalidArgumentException('Priority number or task parameter array expected as first argument');
|
||||||
}
|
}
|
||||||
|
|
||||||
$command = array_shift($args);
|
$command = array_shift($args);
|
||||||
$parameters = json_encode($args);
|
$parameters = json_encode($args);
|
||||||
$queue = DBA::selectFirst('workerqueue', ['id', 'priority'], ['command' => $command, 'parameter' => $parameters, 'done' => false]);
|
$queue = DBA::selectFirst('workerqueue', ['id', 'priority'], ['command' => $command, 'parameter' => $parameters, 'done' => false]);
|
||||||
$added = 0;
|
$added = 0;
|
||||||
|
|
||||||
if (!is_int($priority) || !in_array($priority, self::PRIORITIES)) {
|
if (!is_int($priority) || !in_array($priority, self::PRIORITIES)) {
|
||||||
Logger::warning('Invalid priority', ['priority' => $priority, 'command' => $command]);
|
Logger::warning('Invalid priority', ['priority' => $priority, 'command' => $command]);
|
||||||
|
@ -1292,7 +1295,7 @@ class Worker
|
||||||
|
|
||||||
if (empty($queue)) {
|
if (empty($queue)) {
|
||||||
if (!DBA::insert('workerqueue', ['command' => $command, 'parameter' => $parameters, 'created' => $created,
|
if (!DBA::insert('workerqueue', ['command' => $command, 'parameter' => $parameters, 'created' => $created,
|
||||||
'priority' => $priority, 'next_try' => $delayed])) {
|
'priority' => $priority, 'next_try' => $delayed])) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
$added = DBA::lastInsertId();
|
$added = DBA::lastInsertId();
|
||||||
|
@ -1354,11 +1357,11 @@ class Worker
|
||||||
*/
|
*/
|
||||||
private static function getNextRetrial(array $queue, int $max_level): int
|
private static function getNextRetrial(array $queue, int $max_level): int
|
||||||
{
|
{
|
||||||
$created = strtotime($queue['created']);
|
$created = strtotime($queue['created']);
|
||||||
$retrial_time = time() - $created;
|
$retrial_time = time() - $created;
|
||||||
|
|
||||||
$new_retrial = $queue['retrial'] + 1;
|
$new_retrial = $queue['retrial'] + 1;
|
||||||
$total = 0;
|
$total = 0;
|
||||||
for ($retrial = 0; $retrial <= $max_level + 1; ++$retrial) {
|
for ($retrial = 0; $retrial <= $max_level + 1; ++$retrial) {
|
||||||
$delay = (($retrial + 3) ** 4) + (rand(1, 30) * ($retrial + 1));
|
$delay = (($retrial + 3) ** 4) + (rand(1, 30) * ($retrial + 1));
|
||||||
$total += $delay;
|
$total += $delay;
|
||||||
|
@ -1396,7 +1399,7 @@ class Worker
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$id = $queue['id'];
|
$id = $queue['id'];
|
||||||
$priority = $queue['priority'];
|
$priority = $queue['priority'];
|
||||||
|
|
||||||
$max_level = DI::config()->get('system', 'worker_defer_limit');
|
$max_level = DI::config()->get('system', 'worker_defer_limit');
|
||||||
|
@ -1414,7 +1417,7 @@ class Worker
|
||||||
|
|
||||||
// Calculate the delay until the next trial
|
// Calculate the delay until the next trial
|
||||||
$delay = (($new_retrial + 2) ** 4) + (rand(1, 30) * ($new_retrial));
|
$delay = (($new_retrial + 2) ** 4) + (rand(1, 30) * ($new_retrial));
|
||||||
$next = DateTimeFormat::utc('now + ' . $delay . ' seconds');
|
$next = DateTimeFormat::utc('now + ' . $delay . ' seconds');
|
||||||
|
|
||||||
if (($priority < self::PRIORITY_MEDIUM) && ($new_retrial > 3)) {
|
if (($priority < self::PRIORITY_MEDIUM) && ($new_retrial > 3)) {
|
||||||
$priority = self::PRIORITY_MEDIUM;
|
$priority = self::PRIORITY_MEDIUM;
|
||||||
|
@ -1426,7 +1429,7 @@ class Worker
|
||||||
|
|
||||||
Logger::info('Deferred task', ['id' => $id, 'retrial' => $new_retrial, 'created' => $queue['created'], 'next_execution' => $next, 'old_prio' => $queue['priority'], 'new_prio' => $priority]);
|
Logger::info('Deferred task', ['id' => $id, 'retrial' => $new_retrial, 'created' => $queue['created'], 'next_execution' => $next, 'old_prio' => $queue['priority'], 'new_prio' => $priority]);
|
||||||
|
|
||||||
$stamp = (float)microtime(true);
|
$stamp = (float)microtime(true);
|
||||||
$fields = ['retrial' => $new_retrial, 'next_try' => $next, 'executed' => DBA::NULL_DATETIME, 'pid' => 0, 'priority' => $priority];
|
$fields = ['retrial' => $new_retrial, 'next_try' => $next, 'executed' => DBA::NULL_DATETIME, 'pid' => 0, 'priority' => $priority];
|
||||||
DBA::update('workerqueue', $fields, ['id' => $id]);
|
DBA::update('workerqueue', $fields, ['id' => $id]);
|
||||||
self::$db_duration += (microtime(true) - $stamp);
|
self::$db_duration += (microtime(true) - $stamp);
|
||||||
|
@ -1445,7 +1448,7 @@ class Worker
|
||||||
{
|
{
|
||||||
// Calculate the seconds of the start and end of the maintenance window
|
// Calculate the seconds of the start and end of the maintenance window
|
||||||
$start = strtotime(DI::config()->get('system', 'maintenance_start')) % 86400;
|
$start = strtotime(DI::config()->get('system', 'maintenance_start')) % 86400;
|
||||||
$end = strtotime(DI::config()->get('system', 'maintenance_end')) % 86400;
|
$end = strtotime(DI::config()->get('system', 'maintenance_end')) % 86400;
|
||||||
|
|
||||||
Logger::info('Maintenance window', ['start' => date('H:i:s', $start), 'end' => date('H:i:s', $end)]);
|
Logger::info('Maintenance window', ['start' => date('H:i:s', $start), 'end' => date('H:i:s', $end)]);
|
||||||
|
|
||||||
|
|
|
@ -115,7 +115,7 @@ class Daemon
|
||||||
private static function spawn()
|
private static function spawn()
|
||||||
{
|
{
|
||||||
Logger::notice('Starting new daemon process');
|
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');
|
Logger::notice('New daemon process started');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,22 +5,22 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace Friendica\Test\Unit;
|
namespace Friendica\Test\Unit;
|
||||||
|
|
||||||
use Dice\Dice;
|
|
||||||
use Friendica\App;
|
use Friendica\App;
|
||||||
|
use Friendica\Core\Container;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
class AppTest extends TestCase
|
class AppTest extends TestCase
|
||||||
{
|
{
|
||||||
public function testFromDiceReturnsApp(): void
|
public function testFromContainerReturnsApp(): void
|
||||||
{
|
{
|
||||||
$dice = $this->createMock(Dice::class);
|
$container = $this->createMock(Container::class);
|
||||||
$dice->expects($this->never())->method('create');
|
$container->expects($this->never())->method('create');
|
||||||
|
|
||||||
$app = App::fromDice($dice);
|
$app = App::fromContainer($container);
|
||||||
|
|
||||||
$this->assertInstanceOf(App::class, $app);
|
$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