Merge pull request #14659 from nupplaphil/feat/worker_console

Move 'bin/worker.php' to 'bin/console.php worker'
This commit is contained in:
Hypolite Petovan 2025-01-06 14:42:00 -05:00 committed by GitHub
commit c2eae676bf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
25 changed files with 486 additions and 249 deletions

View file

@ -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();

View file

@ -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();

View file

@ -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();

View file

@ -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

View file

@ -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();

View file

@ -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();

View file

@ -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, youll 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`.
>

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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);

View file

@ -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 &

View file

@ -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');

View 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));
}
}
}

View file

@ -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);

View file

@ -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
View 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);
}
}

View file

@ -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
View 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');
}
}

View file

@ -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) {

View file

@ -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);

View file

@ -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');
}
}

View file

@ -9,18 +9,18 @@ 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);
}

View 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']]);
}
}