Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved Resource and Cache Updater #248

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from
97 changes: 42 additions & 55 deletions app/Http/Controllers/V4DB/AnimeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
use App\Http\Resources\V4\CommonResource;
use App\Http\Resources\V4\ForumResource;
use App\Http\Resources\V4\NewsResource;
use App\Jobs\UpdateResource;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Facades\DB;
Expand Down Expand Up @@ -98,11 +99,11 @@ public function full(Request $request, int $id)
if ($results->isEmpty()) {
$meta = [
'createdAt' => new UTCDateTime(),
'modifiedAt' => new UTCDateTime(),
'updated_at' => new UTCDateTime(),
'request_hash' => $this->fingerprint
];
}
$meta['modifiedAt'] = new UTCDateTime();
$meta['updated_at'] = new UTCDateTime();

$response = $meta + $response;

Expand Down Expand Up @@ -172,64 +173,50 @@ public function main(Request $request, int $id)
->where('mal_id', $id)
->get();

if (
$results->isEmpty()
|| $this->isExpired($request, $results)
) {
if ($results->isEmpty()) {
$response = Anime::scrape($id);

if (HttpHelper::hasError($response)) {
return HttpResponse::notFound($request);
}

if ($results->isEmpty()) {
$meta = [
'createdAt' => new UTCDateTime(),
'modifiedAt' => new UTCDateTime(),
'request_hash' => $this->fingerprint
];
}
$meta['modifiedAt'] = new UTCDateTime();

$response = $meta + $response;

if ($results->isEmpty()) {
Anime::query()
->insert($response);
}

if ($this->isExpired($request, $results)) {
Anime::query()
->where('mal_id', $id)
->update($response);
}

$results = Anime::query()
->where('mal_id', $id)
->get();
Anime::query()
->insert(
irfan-dahir marked this conversation as resolved.
Show resolved Hide resolved
[
'created_at' => new UTCDateTime(),
'updated_at' => new UTCDateTime(),
'request_hash' => $this->fingerprint
] + $response
);
}

if ($results->isEmpty()) {
return HttpResponse::notFound($request);
if ($this->isExpired($request, $results)) {
dispatch(new UpdateResource(
Anime::class, $id, $this->fingerprint
));
}

$response = (new \App\Http\Resources\V4\AnimeResource(
$results->first()
))->response();
$results = Anime::query()
->where('mal_id', $id)
->get();

return $this->prepareResponse(
$response,
$results,
$request
);
return $results->isEmpty()
? HttpResponse::notFound($request)
: $this->prepareResponse(
(new \App\Http\Resources\V4\AnimeResource(
$results->first()
))->response(),
$results,
$request
);
}

/**
* @OA\Get(
* path="/anime/{id}/characters",
* operationId="getAnimeCharacters",
* tags={"anime"},
*
*
* @OA\Parameter(
* name="id",
* in="path",
Expand Down Expand Up @@ -289,7 +276,7 @@ public function characters(Request $request, int $id)
* required=true,
* @OA\Schema(type="integer")
* ),
*
*
* @OA\Response(
* response="200",
* description="Returns anime staff resource",
Expand Down Expand Up @@ -465,14 +452,14 @@ public function episodes(Request $request, int $id)
* path="/anime/{id}/episodes/{episode}",
* operationId="getAnimeEpisodeById",
* tags={"anime"},
*
*
* @OA\Parameter(
* name="id",
* in="path",
* required=true,
* @OA\Schema(type="integer")
* ),
*
*
* @OA\Parameter(
* name="episode",
* in="path",
Expand Down Expand Up @@ -529,7 +516,7 @@ public function episode(Request $request, int $id, int $episodeId)
* path="/anime/{id}/news",
* operationId="getAnimeNews",
* tags={"anime"},
*
*
* @OA\Parameter(
* name="id",
* in="path",
Expand Down Expand Up @@ -597,14 +584,14 @@ public function news(Request $request, int $id)
* path="/anime/{id}/forum",
* operationId="getAnimeForum",
* tags={"anime"},
*
*
* @OA\Parameter(
* name="id",
* in="path",
* required=true,
* @OA\Schema(type="integer")
* ),
*
*
* @OA\Parameter(
* name="filter",
* in="query",
Expand Down Expand Up @@ -664,7 +651,7 @@ public function forum(Request $request, int $id)
* path="/anime/{id}/videos",
* operationId="getAnimeVideos",
* tags={"anime"},
*
*
* @OA\Parameter(
* name="id",
* in="path",
Expand Down Expand Up @@ -717,7 +704,7 @@ public function videos(Request $request, int $id)
* path="/anime/{id}/pictures",
* operationId="getAnimePictures",
* tags={"anime"},
*
*
* @OA\Parameter(
* name="id",
* in="path",
Expand All @@ -738,7 +725,7 @@ public function videos(Request $request, int $id)
* description="Error: Bad request. When required parameters were not supplied.",
* ),
* )
*
*
*/
public function pictures(Request $request, int $id)
{
Expand Down Expand Up @@ -772,7 +759,7 @@ public function pictures(Request $request, int $id)
* path="/anime/{id}/statistics",
* operationId="getAnimeStatistics",
* tags={"anime"},
*
*
* @OA\Parameter(
* name="id",
* in="path",
Expand Down Expand Up @@ -825,7 +812,7 @@ public function stats(Request $request, int $id)
* path="/anime/{id}/moreinfo",
* operationId="getAnimeMoreInfo",
* tags={"anime"},
*
*
* @OA\Parameter(
* name="id",
* in="path",
Expand Down Expand Up @@ -878,7 +865,7 @@ public function moreInfo(Request $request, int $id)
* path="/anime/{id}/recommendations",
* operationId="getAnimeRecommendations",
* tags={"anime"},
*
*
* @OA\Parameter(
* name="id",
* in="path",
Expand Down Expand Up @@ -931,7 +918,7 @@ public function recommendations(Request $request, int $id)
* path="/anime/{id}/userupdates",
* operationId="getAnimeUserUpdates",
* tags={"anime"},
*
*
* @OA\Parameter(
* name="id",
* in="path",
Expand Down
10 changes: 5 additions & 5 deletions app/Http/Controllers/V4DB/Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ public function __construct(Request $request, MalClient $jikan)
$this->fingerprint = HttpHelper::resolveRequestFingerprint($request);
}

protected function isExpired($request, $results) : bool
protected function isExpired($request, $results) : bool
{
$lastModified = $this->getLastModified($results);

Expand Down Expand Up @@ -118,11 +118,11 @@ protected function getTtl($results, $request)
protected function getLastModified($results) : ?int
{
if (is_array($results->first())) {
return (int) $results->first()['modifiedAt']->toDateTime()->format('U');
return (int) $results->first()['updated_at']->toDateTime()->format('U');
}

if (is_object($results->first())) {
return (int) $results->first()->modifiedAt->toDateTime()->format('U');
return (int) $results->first()->updated_at->toDateTime()->format('U');
}

return null;
Expand Down Expand Up @@ -168,13 +168,13 @@ protected function updateCache($request, $results, $response)
if ($results->isEmpty()) {
$meta = [
'createdAt' => new UTCDateTime(),
'modifiedAt' => new UTCDateTime(),
'updated_at' => new UTCDateTime(),
'request_hash' => $this->fingerprint
];
}

// Update `modifiedAt` meta
$meta['modifiedAt'] = new UTCDateTime();
$meta['updated_at'] = new UTCDateTime();
// join meta data with response
$response = $meta + $response;

Expand Down
115 changes: 115 additions & 0 deletions app/Jobs/UpdateResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
<?php

namespace App\Jobs;

use Carbon\Carbon;
use DateTime;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Queue\Middleware\ThrottlesExceptions;
use MongoDB\BSON\UTCDateTime;

/**
*
*/
class UpdateResource extends Job implements ShouldBeUnique
{
/**
* @var string
*/
public string $resource;

/**
* @var int
*/
public int $malId;

/**
* @var string
*/
public string $fingerprint;

/**
* @var int
*/
public int $uniqueFor = 3600;

/**
* @var int
*/
public int $maxExceptions = 5;

/**
* @var int
*/
public int $timeout = 30;

/**
* @var int
*/
public int $tries = 3;

/**
* @return int
*/
public function uniqueId()
{
return $this->malId;
}

/**
* Create a new job instance.
*
* @return void
*/
public function __construct(
string $resource,
int $malId,
string $fingerprint
)
{
$this->resource = $resource;
$this->malId = $malId;
$this->fingerprint = $fingerprint;
}

/**
* Execute the job.
*
* @return void
*/
public function handle(): void
{
$instance = new $this->resource;

// @todo handle exceptions
$response = $instance::scrape($this->malId);

$response = ['updated_at' => new UTCDateTime()]
+ $response;

$instance::query()
->where('mal_id', $this->malId)
->update($response);
}

/**
* @return array
*/
public function middleware() : array
{
return [
(new ThrottlesExceptions(5, 10))
->backoff(60)
->by("$this->resource:$this->malId")
];
}

/**
* @return DateTime
*/
public function retryUntil() : DateTime
{
return Carbon::now()
->addMinutes(10);
}
}
Loading