1
0
mirror of https://github.com/flarum/core.git synced 2025-08-06 08:27:42 +02:00

perf(statistics): split timed data into per-model XHR requests (#3601)

* chore: kill off timeset offset from statistics extension

* perf: split timed data into per-model requests
This commit is contained in:
David Wheatley
2022-08-16 18:30:24 +01:00
committed by GitHub
parent 5637fe8041
commit 352a50e3ad
2 changed files with 85 additions and 89 deletions

View File

@@ -10,7 +10,6 @@
namespace Flarum\Statistics\Api\Controller;
use DateTime;
use DateTimeZone;
use Flarum\Discussion\Discussion;
use Flarum\Http\RequestUtil;
use Flarum\Post\Post;
@@ -24,6 +23,7 @@ use Laminas\Diactoros\Response\JsonResponse;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Tobscure\JsonApi\Exception\InvalidParameterException;
class ShowStatisticsData implements RequestHandlerInterface
{
@@ -70,20 +70,22 @@ class ShowStatisticsData implements RequestHandlerInterface
$actor->assertAdmin();
$reportingPeriod = Arr::get($request->getQueryParams(), 'period');
$model = Arr::get($request->getQueryParams(), 'model');
return new JsonResponse($this->getResponse($reportingPeriod));
return new JsonResponse($this->getResponse($model, $reportingPeriod));
}
private function getResponse(?string $period): array
private function getResponse(?string $model, ?string $period): array
{
if ($period === 'lifetime') {
return $this->getLifetimeStatistics();
}
return array_merge(
$this->getTimedStatistics(),
['timezoneOffset' => $this->getUserTimezone()->getOffset(new DateTime)]
);
if (! Arr::exists($this->entities, $model)) {
throw new InvalidParameterException();
}
return $this->getTimedStatistics($model);
}
private function getLifetimeStatistics()
@@ -95,61 +97,35 @@ class ShowStatisticsData implements RequestHandlerInterface
});
}
private function getTimedStatistics()
private function getTimedStatistics(string $model)
{
return $this->cache->remember('flarum-subscriptions.timed_stats', self::$lifetimeStatsCacheTtl, function () {
return array_map(function ($entity) {
return $this->getTimedCounts($entity[0], $entity[1]);
}, $this->entities);
return $this->cache->remember("flarum-subscriptions.timed_stats.$model", self::$lifetimeStatsCacheTtl, function () use ($model) {
return $this->getTimedCounts($this->entities[$model][0], $this->entities[$model][1]);
});
}
private function getTimedCounts(Builder $query, $column)
{
// Calculate the offset between the server timezone (which is used for
// dates stored in the database) and the user's timezone (set via the
// settings table). We will use this to make sure we aggregate the
// daily/hourly statistics according to the user's timezone.
$offset = $this->getTimezoneOffset();
$results = $query
->selectRaw(
'DATE_FORMAT(
@date := DATE_ADD('.$column.', INTERVAL ? SECOND), -- convert to user timezone
@date := '.$column.',
IF(@date > ?, \'%Y-%m-%d %H:00:00\', \'%Y-%m-%d\') -- if within the last 24 hours, group by hour
) as time_group',
[$offset, new DateTime('-25 hours')]
[new DateTime('-25 hours')]
)
->selectRaw('COUNT(id) as count')
->where($column, '>', new DateTime('-365 days'))
->groupBy('time_group')
->pluck('count', 'time_group');
// Now that we have the aggregated statistics, convert each time group
// into a UNIX timestamp.
$userTimezone = $this->getUserTimezone();
$timed = [];
$results->each(function ($count, $time) use (&$timed, $userTimezone) {
$time = new DateTime($time, $userTimezone);
$results->each(function ($count, $time) use (&$timed) {
$time = new DateTime($time);
$timed[$time->getTimestamp()] = (int) $count;
});
return $timed;
}
private function getTimezoneOffset()
{
$now = new DateTime;
$dataTimezone = new DateTimeZone(date_default_timezone_get());
return $this->getUserTimezone()->getOffset($now) - $dataTimezone->getOffset($now);
}
private function getUserTimezone()
{
return new DateTimeZone($this->settings->get('flarum-statistics.timezone', date_default_timezone_get()));
}
}