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:
@@ -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()));
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user