Skip to content

Commit 84735b6

Browse files
committed
JsonResultSetUtils: Query results in bulk..
..if there's no limit imposed. PDO runs queries in buffered mode by default. Fetching without a limit needlessly increases the risk to require more memory than available.
1 parent 0240cc4 commit 84735b6

File tree

1 file changed

+54
-5
lines changed

1 file changed

+54
-5
lines changed

library/Icingadb/Data/JsonResultSetUtils.php

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,17 +67,66 @@ public static function stream(Query $query): void
6767
$query->setResultSetClass(__CLASS__);
6868
}
6969

70+
if ($query->hasLimit()) {
71+
// Custom limits should still apply
72+
$query->peekAhead(false);
73+
$offset = $query->getOffset();
74+
} else {
75+
$query->limit(1000);
76+
$query->peekAhead();
77+
$offset = 0;
78+
}
79+
7080
echo '[';
71-
foreach ($query->execute()->disableCache() as $i => $object) {
72-
if ($i > 0) {
73-
echo ",\n";
81+
82+
do {
83+
$query->offset($offset);
84+
$result = $query->execute()->disableCache();
85+
foreach ($result as $i => $object) {
86+
if ($i > 0 || $offset !== 0) {
87+
echo ",\n";
88+
}
89+
90+
echo Json::sanitize($object);
91+
92+
self::giveMeMoreTime();
7493
}
7594

76-
echo Json::sanitize($object);
77-
}
95+
$offset += 1000;
96+
} while ($result->hasMore());
7897

7998
echo ']';
8099

81100
exit;
82101
}
102+
103+
/**
104+
* Grant the caller more time to work with
105+
*
106+
* This resets the execution time before it runs out. The advantage of this, compared with no execution time
107+
* limit at all, is that only the caller can bypass the limit. Any other (faulty) code will still be stopped.
108+
*
109+
* @internal Don't use outside of {@see JsonResultSet::stream()} or {@see CsvResultSet::stream()}
110+
*
111+
* @return void
112+
*/
113+
public static function giveMeMoreTime()
114+
{
115+
$spent = getrusage();
116+
if ($spent !== false) {
117+
$maxExecutionTime = ini_get('max_execution_time');
118+
if (! $maxExecutionTime || ! is_numeric($maxExecutionTime)) {
119+
$maxExecutionTime = 30;
120+
} else {
121+
$maxExecutionTime = (int) $maxExecutionTime;
122+
}
123+
124+
if ($maxExecutionTime > 0) {
125+
$timeRemaining = $maxExecutionTime - $spent['ru_utime.tv_sec'] % $maxExecutionTime;
126+
if ($timeRemaining <= 5) {
127+
set_time_limit($maxExecutionTime);
128+
}
129+
}
130+
}
131+
}
83132
}

0 commit comments

Comments
 (0)