diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-14 13:23:16 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-14 13:23:16 +0000 |
commit | 3e97c51418e6d27e9a81906f347fcb7c78e27d4f (patch) | |
tree | ee596ce1bc9840661386f96f9b8d1f919a106317 /vendor/gipfl/simple-daemon/src | |
parent | Initial commit. (diff) | |
download | icingaweb2-module-incubator-3e97c51418e6d27e9a81906f347fcb7c78e27d4f.tar.xz icingaweb2-module-incubator-3e97c51418e6d27e9a81906f347fcb7c78e27d4f.zip |
Adding upstream version 0.20.0.upstream/0.20.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/gipfl/simple-daemon/src')
-rw-r--r-- | vendor/gipfl/simple-daemon/src/Daemon.php | 156 | ||||
-rw-r--r-- | vendor/gipfl/simple-daemon/src/DaemonState.php | 172 | ||||
-rw-r--r-- | vendor/gipfl/simple-daemon/src/DaemonTask.php | 20 | ||||
-rw-r--r-- | vendor/gipfl/simple-daemon/src/SystemdAwareTask.php | 13 |
4 files changed, 361 insertions, 0 deletions
diff --git a/vendor/gipfl/simple-daemon/src/Daemon.php b/vendor/gipfl/simple-daemon/src/Daemon.php new file mode 100644 index 0000000..8d08871 --- /dev/null +++ b/vendor/gipfl/simple-daemon/src/Daemon.php @@ -0,0 +1,156 @@ +<?php + +namespace gipfl\SimpleDaemon; + +use Exception; +use gipfl\Cli\Process; +use gipfl\SystemD\NotifySystemD; +use Psr\Log\LoggerAwareInterface; +use Psr\Log\LoggerAwareTrait; +use Psr\Log\NullLogger; +use React\EventLoop\LoopInterface; +use React\Promise\Deferred; +use function React\Promise\resolve; +use function React\Promise\Timer\timeout; +use function sprintf; + +class Daemon implements LoggerAwareInterface +{ + use LoggerAwareTrait; + + /** @var LoopInterface */ + private $loop; + + /** @var NotifySystemD|boolean */ + protected $systemd; + + /** @var DaemonTask[] */ + protected $daemonTasks = []; + + /** @var bool */ + protected $tasksStarted = false; + + /** @var bool */ + protected $reloading = false; + + public function run(LoopInterface $loop) + { + if ($this->logger === null) { + $this->setLogger(new NullLogger()); + } + $this->loop = $loop; + $this->registerSignalHandlers(); + $this->systemd = NotifySystemD::ifRequired($loop); + $loop->futureTick(function () { + if ($this->systemd) { + $this->systemd->setReady(); + } + + $this->startTasks(); + }); + } + + public function attachTask(DaemonTask $task) + { + if ($task instanceof LoggerAwareInterface) { + $task->setLogger($this->logger ?: new NullLogger()); + } + + $this->daemonTasks[] = $task; + if ($this->tasksStarted) { + $this->startTask($task); + } + } + + protected function startTasks() + { + $this->tasksStarted = true; + foreach ($this->daemonTasks as $task) { + $this->startTask($task); + } + } + + protected function startTask(DaemonTask $task) + { + if ($this->systemd && $task instanceof SystemdAwareTask) { + $task->setSystemd($this->systemd); + } + + $task->start($this->loop); + } + + protected function stopTasks() + { + if (empty($this->daemonTasks)) { + return resolve(); + } + + $deferred = new Deferred(); + foreach ($this->daemonTasks as $id => $task) { + $task->stop()->always(function () use ($id, $deferred) { + unset($this->daemonTasks[$id]); + if (empty($this->daemonTasks)) { + $this->tasksStarted = false; + $this->loop->futureTick(function () use ($deferred) { + $deferred->resolve(); + }); + } + }); + } + + return $deferred->promise(); + } + + protected function registerSignalHandlers() + { + $func = function ($signal) use (&$func) { + $this->shutdownWithSignal($signal, $func); + }; + $funcReload = function () { + $this->reload(); + }; + $this->loop->addSignal(SIGHUP, $funcReload); + $this->loop->addSignal(SIGINT, $func); + $this->loop->addSignal(SIGTERM, $func); + } + + protected function shutdownWithSignal($signal, &$func) + { + $this->loop->removeSignal($signal, $func); + $this->shutdown(); + } + + public function reload() + { + if ($this->reloading) { + $this->logger->error('Ignoring reload request, reload is already in progress'); + return; + } + $this->reloading = true; + $this->logger->notice('Stopping tasks, going gown for reload now'); + if ($this->systemd) { + $this->systemd->setReloading('Reloading the main process'); + } + $this->stopTasks()->then(function () { + $this->logger->notice('Everything stopped, restarting'); + Process::restart(); + }); + } + + public function shutdown() + { + timeout($this->stopTasks(), 5, $this->loop)->then(function () { + $this->loop->stop(); + }, function (Exception $e) { + if ($this->logger) { + $this->logger->error(sprintf( + 'Failed to safely shutdown, stopping anyways: %s', + $e->getMessage() + )); + } + $this->loop->addTimer(0.1, function () { + $this->loop->stop(); + }); + }); + } +} diff --git a/vendor/gipfl/simple-daemon/src/DaemonState.php b/vendor/gipfl/simple-daemon/src/DaemonState.php new file mode 100644 index 0000000..923a546 --- /dev/null +++ b/vendor/gipfl/simple-daemon/src/DaemonState.php @@ -0,0 +1,172 @@ +<?php + +namespace gipfl\SimpleDaemon; + +use Evenement\EventEmitterInterface; +use Evenement\EventEmitterTrait; +use gipfl\Json\JsonSerialization; +use function implode; +use function strlen; + +class DaemonState implements JsonSerialization, EventEmitterInterface +{ + use EventEmitterTrait; + + const ON_CHANGE = 'change'; + + /** @var string */ + protected $processTitle; + + /** @var ?string */ + protected $state; + + /** @var ?string */ + protected $currentProcessTitle; + + /** @var ?string */ + protected $currentMessage; + + /** @var string[] */ + protected $componentStates = []; + + /** + * @return string + */ + public function getProcessTitle() + { + return $this->processTitle; + } + + /** + * @param string $processTitle + * @return DaemonState + */ + public function setProcessTitle($processTitle) + { + $this->processTitle = $processTitle; + $this->refreshMessage(); + return $this; + } + + /** + * @return string|null + */ + public function getState() + { + return $this->state; + } + + /** + * @param string|null $state + * @return DaemonState + */ + public function setState($state) + { + $this->state = $state; + $this->refreshMessage(); + + return $this; + } + + /** + * @return string|null + */ + public function getCurrentMessage() + { + return $this->currentMessage; + } + + /** + * @return string[] + */ + public function getComponentStates() + { + return $this->componentStates; + } + + /** + * @param string[] $componentStates + * @return DaemonState + */ + public function setComponentStates($componentStates) + { + $this->componentStates = $componentStates; + $this->refreshMessage(); + return $this; + } + + /** + * @param string $name + * @param string $stateMessage + * @return $this + */ + public function setComponentState($name, $stateMessage) + { + if ($stateMessage === null) { + unset($this->componentStates[$name]); + } else { + $this->componentStates[$name] = $stateMessage; + } + $this->refreshMessage(); + + return $this; + } + + public function getComponentState($name) + { + if (isset($this->componentStates[$name])) { + return $this->componentStates[$name]; + } + + return null; + } + + public static function fromSerialization($any) + { + $self = new static(); + if (isset($any->state)) { + $self->state = $any->state; + } + if (isset($any->currentMessage)) { + $self->currentMessage = $any->currentMessage; + } + if (isset($any->processTitle)) { + $self->processTitle = $any->processTitle; + } + if (isset($any->components)) { + $self->componentStates = $any->components; + } + + return $self; + } + + #[\ReturnTypeWillChange] + public function jsonSerialize() + { + return (object) [ + 'state' => $this->state, + 'currentMessage' => $this->currentMessage, + 'processTitle' => $this->processTitle, + 'components' => $this->componentStates + ]; + } + + protected function refreshMessage() + { + $messageParts = []; + $state = $this->getState(); + if ($state !== null && strlen($state)) { + $messageParts[] = $state; + } + foreach ($this->getComponentStates() as $component => $message) { + $messageParts[] = "$component: $message"; + } + + $message = implode(', ', $messageParts); + if ($message !== $this->currentMessage || $this->processTitle !== $this->currentProcessTitle) { + $this->currentMessage = $message; + $this->currentProcessTitle = $this->processTitle; + $this->emit(self::ON_CHANGE, [$this->currentProcessTitle, $this->currentMessage]); + } + } +} diff --git a/vendor/gipfl/simple-daemon/src/DaemonTask.php b/vendor/gipfl/simple-daemon/src/DaemonTask.php new file mode 100644 index 0000000..70fc71a --- /dev/null +++ b/vendor/gipfl/simple-daemon/src/DaemonTask.php @@ -0,0 +1,20 @@ +<?php + +namespace gipfl\SimpleDaemon; + +use React\EventLoop\LoopInterface; +use React\Promise\ExtendedPromiseInterface; + +interface DaemonTask +{ + /** + * @param LoopInterface $loop + * @return ExtendedPromiseInterface + */ + public function start(LoopInterface $loop); + + /** + * @return ExtendedPromiseInterface + */ + public function stop(); +} diff --git a/vendor/gipfl/simple-daemon/src/SystemdAwareTask.php b/vendor/gipfl/simple-daemon/src/SystemdAwareTask.php new file mode 100644 index 0000000..3901d46 --- /dev/null +++ b/vendor/gipfl/simple-daemon/src/SystemdAwareTask.php @@ -0,0 +1,13 @@ +<?php + +namespace gipfl\SimpleDaemon; + +use gipfl\SystemD\NotifySystemD; + +interface SystemdAwareTask +{ + /** + * @param NotifySystemD $systemd + */ + public function setSystemd(NotifySystemD $systemd); +} |