3 * @copyright Copyright (C) 2010-2022, the Friendica project
5 * @license GNU AGPL version 3 or any later version
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as
9 * published by the Free Software Foundation, either version 3 of the
10 * License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 namespace Friendica\Core\Worker\Repository;
24 use Friendica\BaseRepository;
25 use Friendica\Core\Worker\Exception\ProcessPersistenceException;
26 use Friendica\Database\Database;
27 use Friendica\Util\DateTimeFormat;
28 use Friendica\Core\Worker\Factory;
29 use Friendica\Core\Worker\Entity;
30 use Psr\Log\LoggerInterface;
33 * functions for interacting with a process
35 class Process extends BaseRepository
37 const NODE_ENV = 'NODE_ENV';
39 protected static $table_name = 'process';
41 /** @var Factory\Process */
47 public function __construct(Database $database, LoggerInterface $logger, Factory\Process $factory, array $server)
49 parent::__construct($database, $logger, $factory);
51 $this->currentHost = $factory->determineHost($server[self::NODE_ENV] ?? null);
55 * Starts and Returns the process for a given PID at the current host
58 * @param string $command
60 * @return Entity\Process
62 public function create(int $pid, string $command): Entity\Process
64 // Cleanup inactive process
65 $this->deleteInactive();
68 $this->db->transaction();
70 if (!$this->db->exists(static::$table_name, ['pid' => $pid, 'hostname' => $this->currentHost])) {
71 if (!$this->db->insert(static::$table_name, [
73 'command' => $command,
74 'hostname' => $this->currentHost,
75 'created' => DateTimeFormat::utcNow()
77 throw new ProcessPersistenceException(sprintf('The process with PID %s already exists.', $pid));
81 $result = $this->_selectOne(['pid' => $pid, 'hostname' => $this->currentHost]);
86 } catch (\Exception $exception) {
87 throw new ProcessPersistenceException(sprintf('Cannot save process with PID %s.', $pid), $exception);
91 public function delete(Entity\Process $process)
94 if (!$this->db->delete(static::$table_name, [
95 'pid' => $process->pid,
96 'hostname' => $this->currentHost,
98 throw new ProcessPersistenceException(sprintf('The process with PID %s doesn\'t exists.', $process->pi));
100 } catch (\Exception $exception) {
101 throw new ProcessPersistenceException(sprintf('Cannot delete process with PID %s.', $process->pid), $exception);
106 * Clean the process table of inactive physical processes
108 private function deleteInactive()
110 $this->db->transaction();
113 $processes = $this->db->select(static::$table_name, ['pid'], ['hostname' => $this->currentHost]);
114 while ($process = $this->db->fetch($processes)) {
115 if (!posix_kill($process['pid'], 0)) {
116 $this->db->delete(static::$table_name, ['pid' => $process['pid']]);
119 $this->db->close($processes);
121 } catch (\Exception $exception) {
122 $this->db->rollback();
123 throw new ProcessPersistenceException('Cannot delete inactive process', $exception);
128 * Returns the number of processes with a given command
130 * @param string $command
132 * @return int Number of processes
134 * @throws ProcessPersistenceException
136 public function countCommand(string $command): int
139 return $this->count(['command' => strtolower($command)]);
140 } catch (\Exception $exception) {
141 throw new ProcessPersistenceException('Cannot count ', $exception);