Skip to content

Commit

Permalink
added incremental indexer
Browse files Browse the repository at this point in the history
  • Loading branch information
pushrbx committed Nov 4, 2024
1 parent 970ff8a commit e0cc444
Show file tree
Hide file tree
Showing 4 changed files with 191 additions and 1 deletion.
183 changes: 183 additions & 0 deletions app/Console/Commands/Indexer/IncrementalIndexer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
<?php

namespace App\Console\Commands\Indexer;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;

class IncrementalIndexer extends Command
{
/**
* @var bool
*/
private bool $cancelled = false;

/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'indexer:incremental {mediaType*}
{--delay=3 : Set a delay between requests}
{--resume : Resume from the last position}
{--failed : Run only entries that failed to index last time}';

protected function promptForMissingArgumentsUsing(): array

Check warning on line 26 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L26

Added line #L26 was not covered by tests
{
return [
'mediaType' => ['The media type to index.', 'Valid values: anime, manga, character, people']
];

Check warning on line 30 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L28-L30

Added lines #L28 - L30 were not covered by tests
}

public function handle(): int

Check warning on line 33 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L33

Added line #L33 was not covered by tests
{
$validator = Validator::make(
[
'mediaType' => $this->argument('mediaType'),
'delay' => $this->option('delay'),
'resume' => $this->option('resume') ?? false,
'failed' => $this->option('failed') ?? false
],
[
'mediaType' => 'required|in:anime,manga,character,people',
'delay' => 'integer|min:1',
'resume' => 'bool|prohibited_with:failed',
'failed' => 'bool|prohibited_with:resume'
]
);

Check warning on line 48 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L35-L48

Added lines #L35 - L48 were not covered by tests

if ($validator->fails()) {
$this->error($validator->errors()->toJson());
return 1;

Check warning on line 52 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L50-L52

Added lines #L50 - L52 were not covered by tests
}

$this->trap(SIGTERM, fn () => $this->cancelled = true);

Check warning on line 55 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L55

Added line #L55 was not covered by tests

$resume = $this->option('resume') ?? false;
$onlyFailed = $this->option('failed') ?? false;
$existingIdsHash = "";
$existingIdsRaw = "";

Check warning on line 60 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L57-L60

Added lines #L57 - L60 were not covered by tests
/**
* @var $mediaTypes array
*/
$mediaTypes = $this->argument("mediaType");

Check warning on line 64 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L64

Added line #L64 was not covered by tests

foreach ($mediaTypes as $mediaType)

Check warning on line 66 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L66

Added line #L66 was not covered by tests
{
$idsToFetch = [];
$failedIds = [];
$success = [];

Check warning on line 70 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L68-L70

Added lines #L68 - L70 were not covered by tests

if ($onlyFailed && Storage::exists("indexer/incremental/{$mediaType}_failed.json"))

Check warning on line 72 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L72

Added line #L72 was not covered by tests
{
$idsToFetch["sfw"] = json_decode(Storage::get("indexer/incremental/{$mediaType}_failed.json"));

Check warning on line 74 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L74

Added line #L74 was not covered by tests
}
else
{
if (Storage::exists("indexer/incremental/$mediaType.json"))

Check warning on line 78 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L78

Added line #L78 was not covered by tests
{
$existingIdsRaw = Storage::get("indexer/incremental/$mediaType.json");
$existingIdsHash = sha1($existingIdsRaw);

Check warning on line 81 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L80-L81

Added lines #L80 - L81 were not covered by tests
}

if ($this->cancelled)

Check warning on line 84 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L84

Added line #L84 was not covered by tests
{
return 127;

Check warning on line 86 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L86

Added line #L86 was not covered by tests
}

$newIdsRaw = file_get_contents("https://raw.githubusercontent.com/purarue/mal-id-cache/master/cache/${mediaType}_cache.json");
$newIdsHash = sha1($newIdsRaw);

Check warning on line 90 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L89-L90

Added lines #L89 - L90 were not covered by tests

/** @noinspection PhpConditionAlreadyCheckedInspection */
if ($this->cancelled)

Check warning on line 93 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L93

Added line #L93 was not covered by tests
{
return 127;

Check warning on line 95 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L95

Added line #L95 was not covered by tests
}

if ($newIdsHash !== $existingIdsHash)

Check warning on line 98 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L98

Added line #L98 was not covered by tests
{
$newIds = json_decode($newIdsRaw, true);
$existingIds = json_decode($existingIdsRaw, true);

Check warning on line 101 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L100-L101

Added lines #L100 - L101 were not covered by tests

if (is_null($existingIds) || count($existingIds) === 0)

Check warning on line 103 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L103

Added line #L103 was not covered by tests
{
$idsToFetch = $newIds;

Check warning on line 105 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L105

Added line #L105 was not covered by tests
}
else
{
foreach (["sfw", "nsfw"] as $t)

Check warning on line 109 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L109

Added line #L109 was not covered by tests
{
$idsToFetch[$t] = array_diff($existingIds[$t], $newIds[$t]);

Check warning on line 111 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L111

Added line #L111 was not covered by tests
}
}

Storage::put("indexer/incremental/$mediaType.json.tmp", $newIdsRaw);

Check warning on line 115 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L115

Added line #L115 was not covered by tests
}
}

$idCount = count($idsToFetch);
if ($idCount > 0)

Check warning on line 120 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L119-L120

Added lines #L119 - L120 were not covered by tests
{
$index = 0;
if ($resume && Storage::exists("indexer/incremental/{$mediaType}_resume.save"))

Check warning on line 123 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L122-L123

Added lines #L122 - L123 were not covered by tests
{
$index = (int)Storage::get("indexer/incremental/{$mediaType}_resume.save");
$this->info("Resuming from index: $index");

Check warning on line 126 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L125-L126

Added lines #L125 - L126 were not covered by tests
}

if ($index > 0 && !isset($this->ids[$index])) {
$index = 0;
$this->warn('Invalid index; set back to 0');

Check warning on line 131 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L129-L131

Added lines #L129 - L131 were not covered by tests
}

Storage::put("indexer/incremental/{$mediaType}_resume.save", 0);

Check warning on line 134 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L134

Added line #L134 was not covered by tests

$this->info("$idCount $mediaType entries available");
$ids = array_merge($idsToFetch['sfw'], $idsToFetch['nsfw']);
for ($i = $index; $i <= ($idCount - 1); $i++)

Check warning on line 138 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L136-L138

Added lines #L136 - L138 were not covered by tests
{
if ($this->cancelled)

Check warning on line 140 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L140

Added line #L140 was not covered by tests
{
return 127;

Check warning on line 142 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L142

Added line #L142 was not covered by tests
}

$id = $ids[$index];

Check warning on line 145 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L145

Added line #L145 was not covered by tests

$url = env('APP_URL') . "/v4/anime/$id";
$this->info("Indexing/Updating " . ($i + 1) . "/$idCount $url [MAL ID: $id]");

Check warning on line 148 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L147-L148

Added lines #L147 - L148 were not covered by tests

try
{
$response = json_decode(file_get_contents($url), true);
if (isset($response['error']) && $response['status'] != 404)

Check warning on line 153 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L152-L153

Added lines #L152 - L153 were not covered by tests
{
$this->error("[SKIPPED] Failed to fetch $url - {$response['error']}");

Check warning on line 155 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L155

Added line #L155 was not covered by tests
}
}
catch (\Exception)

Check warning on line 158 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L158

Added line #L158 was not covered by tests
{
$this->warn("[SKIPPED] Failed to fetch $url");
$failedIds[] = $id;
Storage::put("indexer/incremental/$mediaType.failed", json_encode($failedIds));

Check warning on line 162 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L160-L162

Added lines #L160 - L162 were not covered by tests
}

$success[] = $id;
Storage::put("indexer/incremental/{$mediaType}_resume.save", $index);

Check warning on line 166 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L165-L166

Added lines #L165 - L166 were not covered by tests
}

Storage::delete("indexer/incremental/{$mediaType}_resume.save");
$this->info("--- Indexing of $mediaType is complete.");
$this->info(count($success) . ' entries indexed or updated.');
if (count($failedIds) > 0)

Check warning on line 172 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L169-L172

Added lines #L169 - L172 were not covered by tests
{
$this->info(count($failedIds) . ' entries failed to index or update. Re-run with --failed to requeue failed entries only.');

Check warning on line 174 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L174

Added line #L174 was not covered by tests
}
// finalize the latest state
Storage::move("indexer/incremental/$mediaType.json.tmp", "indexer/incremental/$mediaType.json");

Check warning on line 177 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L177

Added line #L177 was not covered by tests
}
}

return 0;

Check warning on line 181 in app/Console/Commands/Indexer/IncrementalIndexer.php

View check run for this annotation

Codecov / codecov/patch

app/Console/Commands/Indexer/IncrementalIndexer.php#L181

Added line #L181 was not covered by tests
}
}
3 changes: 2 additions & 1 deletion app/Console/Kernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ class Kernel extends ConsoleKernel
Indexer\GenreIndexer::class,
Indexer\ProducersIndexer::class,
Indexer\AnimeSweepIndexer::class,
Indexer\MangaSweepIndexer::class
Indexer\MangaSweepIndexer::class,
Indexer\IncrementalIndexer::class
];

/**
Expand Down
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"php": "^8.1",
"ext-json": "*",
"ext-mongodb": "*",
"ext-pcntl": "*",
"amphp/http-client": "^4.6",
"danielmewes/php-rql": "dev-master",
"darkaonline/swagger-lume": "^9.0",
Expand Down
5 changes: 5 additions & 0 deletions container-setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ display_help() {
echo "stop Stop Jikan API"
echo "validate-prereqs Validate pre-reqs installed (docker, docker-compose)"
echo "execute-indexers Execute the indexers, which will scrape and index data from MAL. (Notice: This can take days)"
echo "index-incrementally Executes the incremental indexers for each media type. (anime, manga, character, people)"
echo ""
}

Expand Down Expand Up @@ -168,6 +169,10 @@ case "$1" in
$DOCKER_COMPOSE_CMD -p "$DOCKER_COMPOSE_PROJECT_NAME" exec jikan_rest php /app/artisan indexer:producers
echo "Indexing done!"
;;
"index-incrementally")
echo "Indexing..."
$DOCKER_COMPOSE_CMD -p "$DOCKER_COMPOSE_PROJECT_NAME" exec jikan_rest php /app/artisan indexer:incremental anime manga character people
echo "Indexing done!"
*)
echo "No command specified, displaying help"
display_help
Expand Down

0 comments on commit e0cc444

Please sign in to comment.