mirror of
https://github.com/Icinga/icingadb-web.git
synced 2026-05-28 04:36:06 -04:00
Merge pull request #567 from Icinga/handle-redis-errors-gracefully
Handle redis errors gracefully
This commit is contained in:
commit
40d66ab804
7 changed files with 94 additions and 6 deletions
|
|
@ -59,7 +59,7 @@ class HostgroupController extends Controller
|
|||
$paginationControl = $this->createPaginationControl($hosts);
|
||||
$viewModeSwitcher = $this->createViewModeSwitcher($paginationControl, $limitControl);
|
||||
|
||||
$hostList = (new HostList($hosts))
|
||||
$hostList = (new HostList($hosts->execute()))
|
||||
->setViewMode($viewModeSwitcher->getViewMode());
|
||||
|
||||
yield $this->export($hosts);
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ class ServicegroupController extends Controller
|
|||
$paginationControl = $this->createPaginationControl($services);
|
||||
$viewModeSwitcher = $this->createViewModeSwitcher($paginationControl, $limitControl);
|
||||
|
||||
$serviceList = (new ServiceList($services))
|
||||
$serviceList = (new ServiceList($services->execute()))
|
||||
->setViewMode($viewModeSwitcher->getViewMode());
|
||||
|
||||
yield $this->export($services);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
namespace Icinga\Module\Icingadb\Redis;
|
||||
|
||||
use Exception;
|
||||
use Generator;
|
||||
use Icinga\Application\Benchmark;
|
||||
use Icinga\Module\Icingadb\Common\IcingaRedis;
|
||||
|
|
@ -12,6 +13,7 @@ use Icinga\Module\Icingadb\Model\Service;
|
|||
use ipl\Orm\Query;
|
||||
use ipl\Orm\Resolver;
|
||||
use ipl\Orm\ResultSet;
|
||||
use Predis\Client;
|
||||
use RuntimeException;
|
||||
|
||||
class VolatileStateResults extends ResultSet
|
||||
|
|
@ -19,6 +21,9 @@ class VolatileStateResults extends ResultSet
|
|||
/** @var Resolver */
|
||||
private $resolver;
|
||||
|
||||
/** @var Client */
|
||||
private $redis;
|
||||
|
||||
/** @var bool Whether Redis updates were applied */
|
||||
private $updatesApplied = false;
|
||||
|
||||
|
|
@ -27,12 +32,28 @@ class VolatileStateResults extends ResultSet
|
|||
$self = parent::fromQuery($query);
|
||||
$self->resolver = $query->getResolver();
|
||||
|
||||
try {
|
||||
$self->redis = IcingaRedis::instance()->getConnection();
|
||||
} catch (Exception $e) {
|
||||
// The error has already been logged
|
||||
}
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether Redis is unavailable
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isRedisUnavailable(): bool
|
||||
{
|
||||
return $this->redis === null;
|
||||
}
|
||||
|
||||
public function current()
|
||||
{
|
||||
if (! $this->updatesApplied && ! $this->isCacheDisabled) {
|
||||
if ($this->redis && ! $this->updatesApplied && ! $this->isCacheDisabled) {
|
||||
$this->rewind();
|
||||
}
|
||||
|
||||
|
|
@ -41,7 +62,7 @@ class VolatileStateResults extends ResultSet
|
|||
|
||||
public function key(): int
|
||||
{
|
||||
if (! $this->updatesApplied && ! $this->isCacheDisabled) {
|
||||
if ($this->redis && ! $this->updatesApplied && ! $this->isCacheDisabled) {
|
||||
$this->rewind();
|
||||
}
|
||||
|
||||
|
|
@ -50,7 +71,7 @@ class VolatileStateResults extends ResultSet
|
|||
|
||||
public function rewind(): void
|
||||
{
|
||||
if (! $this->updatesApplied && ! $this->isCacheDisabled) {
|
||||
if ($this->redis && ! $this->updatesApplied && ! $this->isCacheDisabled) {
|
||||
$this->updatesApplied = true;
|
||||
$this->advance();
|
||||
|
||||
|
|
@ -126,7 +147,7 @@ class VolatileStateResults extends ResultSet
|
|||
|
||||
protected function fetchStates(string $key, array $ids, array $keys): Generator
|
||||
{
|
||||
$results = IcingaRedis::instance()->getConnection()->hmget($key, $ids);
|
||||
$results = $this->redis->hmget($key, $ids);
|
||||
foreach ($results as $i => $json) {
|
||||
if ($json !== null) {
|
||||
$data = json_decode($json, true);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,9 @@ namespace Icinga\Module\Icingadb\Widget\ItemList;
|
|||
use Icinga\Module\Icingadb\Common\BaseItemList;
|
||||
use Icinga\Module\Icingadb\Common\NoSubjectLink;
|
||||
use Icinga\Module\Icingadb\Common\ViewMode;
|
||||
use Icinga\Module\Icingadb\Redis\VolatileStateResults;
|
||||
use Icinga\Module\Icingadb\Widget\Notice;
|
||||
use ipl\Html\HtmlDocument;
|
||||
|
||||
abstract class StateList extends BaseItemList
|
||||
{
|
||||
|
|
@ -18,5 +21,11 @@ abstract class StateList extends BaseItemList
|
|||
$this->addAttributes(['class' => $this->getViewMode()]);
|
||||
|
||||
parent::assemble();
|
||||
|
||||
if ($this->data instanceof VolatileStateResults && $this->data->isRedisUnavailable()) {
|
||||
$this->prependWrapper((new HtmlDocument())->addHtml(new Notice(
|
||||
t('Icinga Redis is currently unavailable. The shown information might be outdated.')
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
31
library/Icingadb/Widget/Notice.php
Normal file
31
library/Icingadb/Widget/Notice.php
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
/* Icinga DB Web | (c) 2022 Icinga GmbH | GPLv2 */
|
||||
|
||||
namespace Icinga\Module\Icingadb\Widget;
|
||||
|
||||
use ipl\Html\BaseHtmlElement;
|
||||
use ipl\Html\HtmlElement;
|
||||
use ipl\Web\Widget\Icon;
|
||||
|
||||
class Notice extends BaseHtmlElement
|
||||
{
|
||||
/** @var mixed */
|
||||
protected $content;
|
||||
|
||||
protected $tag = 'p';
|
||||
|
||||
protected $defaultAttributes = ['class' => 'notice'];
|
||||
|
||||
public function __construct($content)
|
||||
{
|
||||
$this->content = $content;
|
||||
}
|
||||
|
||||
protected function assemble()
|
||||
{
|
||||
$this->addHtml(new Icon('triangle-exclamation'));
|
||||
$this->addHtml((new HtmlElement('span'))->add($this->content));
|
||||
$this->addHtml(new Icon('triangle-exclamation'));
|
||||
}
|
||||
}
|
||||
|
|
@ -185,6 +185,10 @@ div.show-more {
|
|||
.show-more {
|
||||
margin-top: .25em;
|
||||
}
|
||||
|
||||
.notice {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.content > h2:first-child,
|
||||
|
|
|
|||
23
public/css/widget/notice.less
Normal file
23
public/css/widget/notice.less
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
// Style
|
||||
|
||||
.notice {
|
||||
@margin: 1em / 1.25;
|
||||
@padding: .75em / 1.25;
|
||||
|
||||
.rounded-corners();
|
||||
padding: @padding;
|
||||
color: @text-color-on-icinga-blue;
|
||||
background-color: @state-warning;
|
||||
font-weight: bold;
|
||||
font-size: 1.25em;
|
||||
|
||||
// Layout
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
justify-content: space-between;
|
||||
margin: 0 @margin @margin @margin;
|
||||
|
||||
> span {
|
||||
.text-ellipsis();
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue