WIP: add insights

This commit is contained in:
Irfan 2021-09-11 03:39:49 +05:00
parent 21535a403a
commit f161bcb486
11 changed files with 377 additions and 18 deletions

View File

@ -61,7 +61,5 @@ class Kernel extends ConsoleKernel
// Update common indexes daily
$schedule->command('indexer:common')
->daily();
}
}

View File

@ -0,0 +1,155 @@
<?php
namespace App\Http\Controllers\V4DB;
use App\Http\Resources\V4\InsightsCollection;
use App\Http\Resources\V4\TrendsCollection;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Facades\DB;
use MongoDB\BSON\Regex;
class InsightsController extends Controller
{
public function main(Request $request)
{
if (!env('INSIGHTS')) {
return response()->json([
'status' => 403,
'type' => 'InsightsRuntimeException',
'message' => 'Insights service is disabled',
'error' => null
], 403);
}
$maxResultsPerPage = (int) env('MAX_RESULTS_PER_PAGE', 25);
$page = $request->get('page') ?? 1;
$limit = $request->get('limit') ?? $maxResultsPerPage;
$limit = (int) $limit;
if ($limit <= 0) {
$limit = 1;
}
if ($limit > $maxResultsPerPage) {
$limit = $maxResultsPerPage;
}
$results = DB::table('insights')
->where('timestamp', '>', time() - env('INSIGHTS_MAX_STORE_TIME', 172800) )
->orderBy('timestamp', 'desc')
->paginate(
$limit,
['*'],
null,
$page
);
return new InsightsCollection(
$results
);
}
const TRENDS = [
'anime',
'manga',
'people',
'characters',
];
public function trends(Request $request)
{
if (!env('INSIGHTS')) {
return response()->json([
'status' => 403,
'type' => 'InsightsRuntimeException',
'message' => 'Insights service is disabled',
'error' => null
], 403);
}
$maxResultsPerPage = (int) env('MAX_RESULTS_PER_PAGE', 25);
$page = $request->get('page') ?? 1;
$limit = $request->get('limit') ?? $maxResultsPerPage;
$trend = $request->get('trend') ?? null;
$limit = (int) $limit;
if ($limit <= 0) {
$limit = 1;
}
if ($limit > $maxResultsPerPage) {
$limit = $maxResultsPerPage;
}
if (is_null($trend) || !in_array($trend, self::TRENDS)) {
return response()->json([
'status' => 400,
'type' => 'BadRequestException',
'message' => 'Trend value is invalid',
'error' => null
], 400);
}
// $results = DB::table('insights')
// ->where('url', 'regexp',"/\/v(\d)\/{$trend}\/(\d+).*/i")
// ->where('timestamp', '>', time() - env('INSIGHTS_MAX_STORE_TIME', 172800) )
// ->orderBy('timestamp', 'desc')
// ->paginate(
// $limit,
// ['*'],
// null,
// $page
// );
$results = DB::table('insights')
// ->where('url', 'regexp',"/\/v(\d)\/{$trend}\/(\d+).*/i")
->where('timestamp', '>', time() - env('INSIGHTS_MAX_STORE_TIME', 172800) )
->orderBy('timestamp', 'desc')
->raw(fn($collection) => $collection->aggregate([
[
'$group' => [
'_id' => [
'url' => '$url',
'timestamp' => '$timestamp'
],
'urlCount' => [ '$sum' => 1 ]
]
],
[
'$group' => [
'_id' => '$_id.url',
'count' => [ '$sum' => '$urlCount' ]
]
],
[
'$sort' => [ 'count' => -1 ]
],
['$skip' => ($page - 1) * $maxResultsPerPage],
['$limit' => $maxResultsPerPage],
]));
// ->raw(fn($collection) => $collection->aggregate([
// [
// '$group' => [
// '_id' => '$_id',
// 'url' => ['$first' => '$url'],
// 'count' => [ '$sum' => 1 ]
// ]
// ]
// ]));
return new TrendsCollection(
new LengthAwarePaginator(
$results, DB::table('insights')->count(), $maxResultsPerPage, $page
)
);
}
}

View File

@ -2,24 +2,12 @@
namespace App\Http\Controllers\V4DB;
use App\Anime;
use App\Http\HttpHelper;
use App\Http\HttpResponse;
use App\Http\QueryBuilder\SearchQueryBuilderAnime;
use App\Http\QueryBuilder\SearchQueryBuilderMagazine;
use App\Http\Resources\V4\AnimeCollection;
use App\Http\Resources\V4\MagazineCollection;
use App\Http\Resources\V4\MangaCollection;
use App\Http\Resources\V4\NewsResource;
use App\Magazine;
use App\Manga;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Jenssegers\Mongodb\Eloquent\Builder;
use Jikan\Request\Anime\AnimeNewsRequest;
use Jikan\Request\Magazine\MagazineRequest;
use Jikan\Request\Magazine\MagazinesRequest;
use MongoDB\BSON\UTCDateTime;
class MagazineController extends Controller
{

View File

@ -5,11 +5,9 @@ namespace App\Http\Controllers\V4DB;
use App\Anime;
use App\Http\QueryBuilder\SearchQueryBuilderProducer;
use App\Http\Resources\V4\AnimeCollection;
use App\Http\Resources\V4\MagazineCollection;
use App\Http\Resources\V4\ProducerCollection;
use App\Producer;
use Illuminate\Http\Request;
use Jikan\Request\Producer\ProducersRequest;
class ProducerController extends Controller
{

View File

@ -0,0 +1,52 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
/**
* Class Insights
* @package App\Http\Middleware
*/
class Insights
{
/**
* @param Request $request
* @param Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
return $next($request);
}
/**
* @param Request $request
* @param $response
* @return void
*/
public function terminate(Request $request, $response)
{
if (isset($response->original['error'])) {
return;
}
// @todo scaling: implement as scheduled event if needed
// Delete requests older than INSIGHTS_MAX_STORE
DB::table('insights')
->where('timestamp', '<', time() - env('INSIGHTS_MAX_STORE_TIME', 172800) )
->delete();
DB::table('insights')
->insert([
'timestamp' => time(),
'url' => $request->getRequestUri(),
'type' =>
]);
}
}

View File

@ -0,0 +1,55 @@
<?php
namespace App\Http\Resources\V4;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\ResourceCollection;
use Illuminate\Pagination\LengthAwarePaginator;
class InsightsCollection extends ResourceCollection
{
/**
* The resource that this resource collects.
*
* @var string
*/
public $collects = 'App\Http\Resources\V4\InsightsResource';
private $pagination;
public function __construct(LengthAwarePaginator $resource)
{
$this->pagination = [
'last_visible_page' => $resource->lastPage(),
'has_next_page' => $resource->hasMorePages()
];
$this->collection = $resource->getCollection();
parent::__construct($resource);
}
/**
* Transform the resource collection into an array.
*
* @param Request $request
* @return array
*/
public function toArray($request)
{
return [
'pagination' => $this->pagination,
'data' => $this->collection
];
}
public function withResponse($request, $response)
{
$jsonResponse = json_decode($response->getContent(), true);
unset($jsonResponse['links'],$jsonResponse['meta']);
$response->setContent(json_encode($jsonResponse));
}
}

View File

@ -0,0 +1,17 @@
<?php
namespace App\Http\Resources\V4;
use Illuminate\Http\Resources\Json\JsonResource;
class InsightsResource extends JsonResource
{
public function toArray($request)
{
return [
'timestamp' => $this['timestamp'],
'url' => $this['url'],
];
}
}

View File

@ -0,0 +1,55 @@
<?php
namespace App\Http\Resources\V4;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\ResourceCollection;
use Illuminate\Pagination\LengthAwarePaginator;
class TrendsCollection extends ResourceCollection
{
/**
* The resource that this resource collects.
*
* @var string
*/
public $collects = 'App\Http\Resources\V4\TrendsResource';
private $pagination;
public function __construct(LengthAwarePaginator $resource)
{
$this->pagination = [
'last_visible_page' => $resource->lastPage(),
'has_next_page' => $resource->hasMorePages()
];
$this->collection = $resource->getCollection();
parent::__construct($resource);
}
/**
* Transform the resource collection into an array.
*
* @param Request $request
* @return array
*/
public function toArray($request)
{
return [
'pagination' => $this->pagination,
'data' => $this->collection
];
}
public function withResponse($request, $response)
{
$jsonResponse = json_decode($response->getContent(), true);
unset($jsonResponse['links'],$jsonResponse['meta']);
$response->setContent(json_encode($jsonResponse));
}
}

View File

@ -0,0 +1,17 @@
<?php
namespace App\Http\Resources\V4;
use Illuminate\Http\Resources\Json\JsonResource;
class TrendsResource extends JsonResource
{
public function toArray($request)
{
return [
'url' => $this['_id'],
'count' => $this['count'],
];
}
}

View File

@ -70,6 +70,14 @@ $app->singleton(
|
*/
$globalMiddleware = [];
if (env('INSIGHTS', false)) {
$globalMiddleware[] = \App\Http\Middleware\Insights::class;
}
$app->middleware($globalMiddleware);
$app->routeMiddleware([
// 'slave-auth' => App\Http\Middleware\SlaveAuthentication::class,
// 'meta' => App\Http\Middleware\Meta::class,
@ -77,7 +85,7 @@ $app->routeMiddleware([
// 'throttle' => App\Http\Middleware\Throttle::class,
// 'etag' => \App\Http\Middleware\EtagMiddleware::class,
'microcaching' => \App\Http\Middleware\MicroCaching::class,
'source-health-monitor' => SourceHeartbeatMonitor::class
'source-health-monitor' => SourceHeartbeatMonitor::class,
]);
/*
@ -145,7 +153,7 @@ $commonMiddleware = [
// 'cache-resolver',
// 'throttle'
'source-health-monitor',
'microcaching'
'microcaching',
];

View File

@ -501,4 +501,20 @@ $router->group(
'uses' => 'RandomController@users',
]);
}
);
$router->group(
[
'prefix' => 'insights'
],
function() use ($router) {
$router->get('/', [
'uses' => 'InsightsController@main'
]);
$router->get('/trends', [
'uses' => 'InsightsController@trends'
]);
}
);