summaryrefslogtreecommitdiffstats
path: root/vendor/gipfl/simple-daemon/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-14 13:23:16 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-14 13:23:16 +0000
commit3e97c51418e6d27e9a81906f347fcb7c78e27d4f (patch)
treeee596ce1bc9840661386f96f9b8d1f919a106317 /vendor/gipfl/simple-daemon/src
parentInitial commit. (diff)
downloadicingaweb2-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.php156
-rw-r--r--vendor/gipfl/simple-daemon/src/DaemonState.php172
-rw-r--r--vendor/gipfl/simple-daemon/src/DaemonTask.php20
-rw-r--r--vendor/gipfl/simple-daemon/src/SystemdAwareTask.php13
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);
+}