IcingaObjectsHandler: new REST API handler for...
...list of objects
This commit is contained in:
parent
b364165110
commit
408ff7639c
|
@ -0,0 +1,139 @@
|
|||
<?php
|
||||
|
||||
namespace Icinga\Module\Director\RestApi;
|
||||
|
||||
use Exception;
|
||||
use Icinga\Application\Benchmark;
|
||||
use Icinga\Exception\ProgrammingError;
|
||||
use Icinga\Module\Director\Db\Cache\PrefetchCache;
|
||||
use Icinga\Module\Director\Objects\IcingaObject;
|
||||
use Icinga\Module\Director\Web\Table\ObjectsTable;
|
||||
use Zend_Db_Select as ZfSelect;
|
||||
|
||||
class IcingaObjectsHandler extends RequestHandler
|
||||
{
|
||||
/** @var ObjectsTable */
|
||||
protected $table;
|
||||
|
||||
public function processApiRequest()
|
||||
{
|
||||
try {
|
||||
$this->streamJsonResult();
|
||||
} catch (Exception $e) {
|
||||
// NONO
|
||||
$this->sendJsonError($e->getTraceAsString());
|
||||
}
|
||||
}
|
||||
|
||||
public function setTable(ObjectsTable $table)
|
||||
{
|
||||
$this->table = $table;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ObjectsTable
|
||||
* @throws ProgrammingError
|
||||
*/
|
||||
protected function getTable()
|
||||
{
|
||||
if ($this->table === null) {
|
||||
throw new ProgrammingError('Table is required');
|
||||
}
|
||||
|
||||
return $this->table;
|
||||
}
|
||||
|
||||
protected function streamJsonResult()
|
||||
{
|
||||
$connection = $this->db;
|
||||
Benchmark::measure('aha');
|
||||
$db = $connection->getDbAdapter();
|
||||
$table = $this->getTable();
|
||||
$query = $table
|
||||
->getQuery()
|
||||
->reset(ZfSelect::COLUMNS)
|
||||
->columns('*')
|
||||
->reset(ZfSelect::LIMIT_COUNT)
|
||||
->reset(ZfSelect::LIMIT_OFFSET);
|
||||
|
||||
echo '{ "objects": [ ';
|
||||
$cnt = 0;
|
||||
$objects = [];
|
||||
|
||||
$dummy = IcingaObject::createByType($table->getType(), [], $connection);
|
||||
$dummy->prefetchAllRelatedTypes();
|
||||
|
||||
Benchmark::measure('Prefetching');
|
||||
PrefetchCache::initialize($this->db);
|
||||
Benchmark::measure('Ready to query');
|
||||
$stmt = $db->query($query);
|
||||
$this->response->sendHeaders();
|
||||
if (! ob_get_level()) {
|
||||
ob_start();
|
||||
}
|
||||
$params = $this->request->getUrl()->getParams();
|
||||
$resolved = (bool) $params->get('resolved', false);
|
||||
$withNull = ! $params->shift('withNull');
|
||||
$properties = $params->shift('properties');
|
||||
if (strlen($properties)) {
|
||||
$properties = preg_split('/\s*,\s*/', $properties, -1, PREG_SPLIT_NO_EMPTY);
|
||||
} else {
|
||||
$properties = null;
|
||||
}
|
||||
|
||||
$first = true;
|
||||
$flushes = 0;
|
||||
while ($row = $stmt->fetch()) {
|
||||
/** @var IcingaObject $object */
|
||||
if ($first) {
|
||||
Benchmark::measure('First row');
|
||||
}
|
||||
$object = $dummy::fromDbRow($row, $connection);
|
||||
$objects[] = json_encode($object->toPlainObject(
|
||||
$resolved,
|
||||
$withNull,
|
||||
$properties
|
||||
), JSON_PRETTY_PRINT);
|
||||
if ($first) {
|
||||
Benchmark::measure('Got first row');
|
||||
$first = false;
|
||||
}
|
||||
$cnt++;
|
||||
if ($cnt === 100) {
|
||||
if ($flushes > 0) {
|
||||
echo ', ';
|
||||
}
|
||||
echo implode(', ', $objects);
|
||||
$cnt = 0;
|
||||
$objects = [];
|
||||
$flushes++;
|
||||
ob_end_flush();
|
||||
ob_start();
|
||||
}
|
||||
}
|
||||
|
||||
if ($cnt > 0) {
|
||||
if ($flushes > 0) {
|
||||
echo ', ';
|
||||
}
|
||||
echo implode(', ', $objects);
|
||||
}
|
||||
|
||||
if ($params->get('benchmark')) {
|
||||
echo "],\n";
|
||||
Benchmark::measure('All done');
|
||||
echo '"benchmark_string": ' . json_encode(Benchmark::renderToText());
|
||||
} else {
|
||||
echo '] ';
|
||||
}
|
||||
|
||||
echo "}\n";
|
||||
if (ob_get_level()) {
|
||||
ob_end_flush();
|
||||
}
|
||||
|
||||
// TODO: can we improve this?
|
||||
exit;
|
||||
}
|
||||
}
|
|
@ -2,15 +2,13 @@
|
|||
|
||||
namespace Icinga\Module\Director\Web\Controller;
|
||||
|
||||
use Icinga\Application\Benchmark;
|
||||
use Icinga\Application\Icinga;
|
||||
use Icinga\Data\Filter\FilterChain;
|
||||
use Icinga\Data\Filter\FilterExpression;
|
||||
use Icinga\Exception\NotFoundError;
|
||||
use Icinga\Data\Filter\Filter;
|
||||
use Icinga\Module\Director\Db\Cache\PrefetchCache;
|
||||
use Icinga\Module\Director\Forms\IcingaMultiEditForm;
|
||||
use Icinga\Module\Director\Objects\IcingaObject;
|
||||
use Icinga\Module\Director\RestApi\IcingaObjectsHandler;
|
||||
use Icinga\Module\Director\Web\ActionBar\ObjectsActionBar;
|
||||
use Icinga\Module\Director\Web\ActionBar\TemplateActionBar;
|
||||
use Icinga\Module\Director\Web\Table\ApplyRulesTable;
|
||||
|
@ -20,7 +18,6 @@ use Icinga\Module\Director\Web\Table\TemplatesTable;
|
|||
use Icinga\Module\Director\Web\Tabs\ObjectsTabs;
|
||||
use Icinga\Module\Director\Web\Tree\TemplateTreeRenderer;
|
||||
use ipl\Html\Link;
|
||||
use Zend_Db_Select as ZfSelect;
|
||||
|
||||
abstract class ObjectsController extends ActionController
|
||||
{
|
||||
|
@ -50,15 +47,19 @@ abstract class ObjectsController extends ActionController
|
|||
return $this;
|
||||
}
|
||||
|
||||
protected function apiRequestHandler()
|
||||
{
|
||||
return (new IcingaObjectsHandler(
|
||||
$this->getRequest(),
|
||||
$this->getResponse(),
|
||||
$this->db()
|
||||
))->setTable($this->getTable());
|
||||
}
|
||||
|
||||
public function indexAction()
|
||||
{
|
||||
if ($this->getRequest()->isApiRequest()) {
|
||||
try {
|
||||
$this->streamJsonResult();
|
||||
} catch (\Exception $e) {
|
||||
echo $e->getTraceAsString();
|
||||
exit;
|
||||
}
|
||||
$this->apiRequestHandler()->dispatch();
|
||||
return;
|
||||
}
|
||||
$type = $this->getType();
|
||||
|
@ -77,85 +78,6 @@ abstract class ObjectsController extends ActionController
|
|||
$this->table->renderTo($this);
|
||||
}
|
||||
|
||||
protected function streamJsonResult()
|
||||
{
|
||||
$connection = $this->db();
|
||||
Benchmark::measure('aha');
|
||||
$db = $connection->getDbAdapter();
|
||||
$query = $this->getTable()
|
||||
->getQuery()
|
||||
->reset(ZfSelect::COLUMNS)
|
||||
->columns('*')
|
||||
->reset(ZfSelect::LIMIT_COUNT)
|
||||
->reset(ZfSelect::LIMIT_OFFSET);
|
||||
|
||||
echo '{ "objects": [ ';
|
||||
$cnt = 0;
|
||||
$objects = [];
|
||||
|
||||
$dummy = IcingaObject::createByType($this->getType(), [], $connection);
|
||||
$dummy->prefetchAllRelatedTypes();
|
||||
|
||||
Benchmark::measure('Prefetching');
|
||||
PrefetchCache::initialize($this->db());
|
||||
Benchmark::measure('Ready to query');
|
||||
$stmt = $db->query($query);
|
||||
$this->getResponse()->sendHeaders();
|
||||
if (! ob_get_level()) {
|
||||
ob_start();
|
||||
}
|
||||
$resolved = (bool) $this->params->get('resolved', false);
|
||||
$first = true;
|
||||
$flushes = 0;
|
||||
while ($row = $stmt->fetch()) {
|
||||
/** @var IcingaObject $object */
|
||||
if ($first) {
|
||||
Benchmark::measure('First row');
|
||||
}
|
||||
$object = $dummy::fromDbRow($row, $connection);
|
||||
$objects[] = json_encode($object->toPlainObject($resolved, true), JSON_PRETTY_PRINT);
|
||||
if ($first) {
|
||||
Benchmark::measure('Got first row');
|
||||
$first = false;
|
||||
}
|
||||
$cnt++;
|
||||
if ($cnt === 100) {
|
||||
if ($flushes > 0) {
|
||||
echo ', ';
|
||||
}
|
||||
echo implode(', ', $objects);
|
||||
$cnt = 0;
|
||||
$objects = [];
|
||||
$flushes++;
|
||||
ob_end_flush();
|
||||
ob_start();
|
||||
}
|
||||
}
|
||||
|
||||
if ($cnt > 0) {
|
||||
if ($flushes > 0) {
|
||||
echo ', ';
|
||||
}
|
||||
echo implode(', ', $objects);
|
||||
}
|
||||
|
||||
if ($this->params->get('benchmark')) {
|
||||
echo "],\n";
|
||||
Benchmark::measure('All done');
|
||||
echo '"benchmark_string": ' . json_encode(Benchmark::renderToText());
|
||||
} else {
|
||||
echo '] ';
|
||||
}
|
||||
|
||||
echo "}\n";
|
||||
if (ob_get_level()) {
|
||||
ob_end_flush();
|
||||
}
|
||||
|
||||
// TODO: can we improve this?
|
||||
exit;
|
||||
}
|
||||
|
||||
protected function getTable()
|
||||
{
|
||||
return ObjectsTable::create($this->getType(), $this->db())
|
||||
|
|
Loading…
Reference in New Issue