Merge pull request #4503 from Roardom/speed-up-grouped-search

(Update) Speed up torrent grouping
This commit is contained in:
HDVinnie
2025-03-04 21:34:27 -05:00
committed by GitHub
4 changed files with 121 additions and 77 deletions
+4 -1
View File
@@ -17,6 +17,7 @@ inet_pton
intdiv
intval
isset
krsort
ksort
ltrim
microtime
@@ -39,7 +40,9 @@ strtolower
strtotime
strtoupper
sys_getloadavg
uasort
usort
uniqid
unserialize
urldecode
usleep
usleep
+110 -69
View File
@@ -657,68 +657,104 @@ class TorrentSearch extends Component
)
)
->where($this->filters()->toSqlQueryBuilder())
->get()
->groupBy('meta')
->map(fn ($movieOrTv, $key) => match ($key) {
'movie' => $movieOrTv
->groupBy('tmdb')
->map(
function ($movie) {
$category_id = $movie->first()->category_id;
$movie = $this->groupByTypeAndSort($movie);
$movie->put('category_id', $category_id);
->get();
return $movie;
$groupedTorrents = [];
foreach ($torrents as &$torrent) {
// Memoizing and avoiding casts reduces runtime duration from 70ms to 40ms.
// If accessing laravel's attributes array directly, it's reduced to 11ms,
// but the attributes array is marked as protected so we can't access it.
$tmdb = $torrent->getAttributeValue('tmdb');
$type = $torrent->getRelationValue('type')->getAttributeValue('name');
switch ($torrent->getAttributeValue('meta')) {
case 'movie':
$groupedTorrents['movie'][$tmdb]['Movie'][$type][] = $torrent;
$groupedTorrents['movie'][$tmdb]['category_id'] = $torrent->getAttributeValue('category_id');
break;
case 'tv':
$episode = $torrent->getAttributeValue('episode_number');
$season = $torrent->getAttributeValue('season_number');
if ($season == 0) {
if ($episode == 0) {
$groupedTorrents['tv'][$tmdb]['Complete Pack'][$type][] = $torrent;
} else {
$groupedTorrents['tv'][$tmdb]['Specials']["Special {$episode}"][$type][] = $torrent;
}
),
'tv' => $movieOrTv
->groupBy([
fn ($torrent) => $torrent->tmdb,
])
->map(
function ($tv) {
$category_id = $tv->first()->category_id;
$tv = $tv
->groupBy(fn ($torrent) => $torrent->season_number === 0 ? ($torrent->episode_number === 0 ? 'Complete Pack' : 'Specials') : 'Seasons')
->map(fn ($packOrSpecialOrSeasons, $key) => match ($key) {
'Complete Pack' => $this->groupByTypeAndSort($packOrSpecialOrSeasons),
'Specials' => $packOrSpecialOrSeasons
->groupBy(fn ($torrent) => 'Special '.$torrent->episode_number)
->sortKeysDesc(SORT_NATURAL)
->map(fn ($episode) => $this->groupByTypeAndSort($episode)),
'Seasons' => $packOrSpecialOrSeasons
->groupBy(fn ($torrent) => 'Season '.$torrent->season_number)
->sortKeysDesc(SORT_NATURAL)
->map(
fn ($season) => $season
->groupBy(fn ($torrent) => $torrent->episode_number === 0 ? 'Season Pack' : 'Episodes')
->map(fn ($packOrEpisodes, $key) => match ($key) {
'Season Pack' => $this->groupByTypeAndSort($packOrEpisodes),
'Episodes' => $packOrEpisodes
->groupBy(fn ($torrent) => 'Episode '.$torrent->episode_number)
->sortKeysDesc(SORT_NATURAL)
->map(fn ($episode) => $this->groupByTypeAndSort($episode)),
default => abort(500, 'Group found that isn\'t one of: Season Pack, Episodes.'),
})
),
default => abort(500, 'Group found that isn\'t one of: Complete Pack, Specials, Seasons'),
});
$tv->put('category_id', $category_id);
return $tv;
} else {
if ($episode == 0) {
$groupedTorrents['tv'][$tmdb]['Seasons']["Season {$season}"]['Season Pack'][$type][] = $torrent;
} else {
$groupedTorrents['tv'][$tmdb]['Seasons']["Season {$season}"]['Episodes']["Episode {$episode}"][$type][] = $torrent;
}
),
default => abort(500, 'Group found that isn\'t one of: movie, tv'),
});
}
$medias = $groups->through(function ($group) use ($torrents, $movies, $tv) {
$groupedTorrents['tv'][$tmdb]['category_id'] = $torrent->getAttributeValue('category_id');
}
}
foreach ($groupedTorrents as $mediaType => &$workTorrents) {
switch ($mediaType) {
case 'movie':
foreach ($workTorrents as &$movieTorrents) {
$this->sortTorrentTypes($movieTorrents['Movie']);
}
break;
case 'tv':
foreach ($workTorrents as &$tvTorrents) {
foreach ($tvTorrents as $packOrSpecialOrSeasonsType => &$packOrSpecialOrSeasons) {
switch ($packOrSpecialOrSeasonsType) {
case 'Complete Pack':
$this->sortTorrentTypes($packOrSpecialOrSeasons);
break;
case 'Specials':
krsort($packOrSpecialOrSeasons, SORT_NATURAL);
foreach ($packOrSpecialOrSeasons as &$specialTorrents) {
$this->sortTorrentTypes($specialTorrents);
}
break;
case 'Seasons':
krsort($packOrSpecialOrSeasons, SORT_NATURAL);
foreach ($packOrSpecialOrSeasons as &$season) {
foreach ($season as $packOrEpisodesType => &$packOrEpisodes) {
switch ($packOrEpisodesType) {
case 'Season Pack':
$this->sortTorrentTypes($packOrEpisodes);
break;
case 'Episodes':
krsort($packOrEpisodes, SORT_NATURAL);
foreach ($packOrEpisodes as &$episodeTorrents) {
$this->sortTorrentTypes($episodeTorrents);
}
break;
}
}
}
}
}
}
}
}
$medias = $groups->through(function ($group) use ($groupedTorrents, $movies, $tv) {
switch ($group->meta) {
case 'movie':
if ($movies->has($group->tmdb)) {
$media = $movies[$group->tmdb];
$media->setAttribute('meta', 'movie');
$media->setRelation('torrents', $torrents['movie'][$group->tmdb] ?? collect());
$media->setAttribute('category_id', $media->torrents->pop());
$media->setRelation('torrents', $groupedTorrents['movie'][$group->tmdb] ?? []);
$media->setAttribute('category_id', $media->torrents['category_id']);
} else {
$media = null;
}
@@ -728,8 +764,8 @@ class TorrentSearch extends Component
if ($tv->has($group->tmdb)) {
$media = $tv[$group->tmdb];
$media->setAttribute('meta', 'tv');
$media->setRelation('torrents', $torrents['tv'][$group->tmdb] ?? collect());
$media->setAttribute('category_id', $media->torrents->pop());
$media->setRelation('torrents', $groupedTorrents['tv'][$group->tmdb] ?? []);
$media->setAttribute('category_id', $media->torrents['category_id']);
} else {
$media = null;
}
@@ -746,23 +782,28 @@ class TorrentSearch extends Component
}
/**
* @param \Illuminate\Support\Collection<int, Torrent> $torrents
* @return \Illuminate\Support\Collection<string, \Illuminate\Support\Collection<int, Torrent>>
* @param array<Torrent> $torrentTypeTorrents
*/
private function groupByTypeAndSort($torrents): \Illuminate\Support\Collection
private function sortTorrentTypes(&$torrentTypeTorrents): void
{
return $torrents
->sortBy('type.position')
->values()
->groupBy(fn ($torrent) => $torrent->type->name)
->map(
fn ($torrentsByType) => $torrentsByType
->sortBy([
['resolution.position', 'asc'],
['name', 'asc'],
])
->values()
uasort(
$torrentTypeTorrents,
fn ($a, $b) => $a[0]->getRelationValue('type')->getAttributeValue('position')
<=> $b[0]->getRelationValue('type')->getAttributeValue('position')
);
foreach ($torrentTypeTorrents as &$torrents) {
usort(
$torrents,
fn ($a, $b) => [
$a->getRelationValue('resolution')->getAttributeValue('position'),
$a->getAttributeValue('name')
] <=> [
$b->getRelationValue('resolution')->getAttributeValue('position'),
$b->getAttributeValue('name')
]
);
}
}
/**
@@ -59,7 +59,7 @@
</header>
<section>
<table class="torrent-search--grouped__torrents">
@foreach ($media->torrents as $type => $torrents)
@foreach ($media->torrents['Movie'] as $type => $torrents)
<tbody>
@foreach ($torrents as $torrent)
<tr>
+6 -6
View File
@@ -58,7 +58,7 @@
<p class="torrent-search--grouped__plot">{{ $media->overview ?? '' }}</p>
</header>
<section>
@if ($media->torrents->has('Complete Pack'))
@if (array_key_exists('Complete Pack', $media->torrents))
<details class="torrent-search--grouped__dropdown" open>
<summary x-bind="complete">Complete Pack</summary>
<table class="torrent-search--grouped__torrents">
@@ -85,10 +85,10 @@
</details>
@endif
@if ($media->torrents->has('Specials'))
@if (array_key_exists('Specials', $media->torrents))
<details
class="torrent-search--grouped__dropdown"
@if (! $media->torrents->has('Complete Pack') && ! $media->torrents->has('Seasons'))
@if (! array_key_exists('Complete Pack', $media->torrents) && ! array_key_exists('Seasons', $media->torrents))
open
@endif
>
@@ -135,7 +135,7 @@
@endif
>
<summary x-bind="season">{{ $seasonName }}</summary>
@if ($season->has('Season Pack') && ! $season->has('Episodes'))
@if (array_key_exists('Season Pack', $season) && ! array_key_exists('Episodes', $season))
<table class="torrent-search--grouped__torrents">
@foreach ($season['Season Pack'] as $type => $torrents)
<tbody>
@@ -157,7 +157,7 @@
</tbody>
@endforeach
</table>
@elseif ($season->has('Season Pack'))
@elseif (array_key_exists('Season Pack', $season))
<details open class="torrent-search--grouped__dropdown">
<summary x-bind="pack">Season Pack</summary>
<table class="torrent-search--grouped__torrents">
@@ -187,7 +187,7 @@
@foreach ($season['Episodes'] ?? [] as $episodeName => $episode)
<details
class="torrent-search--grouped__dropdown"
@if ($loop->first && ! $season->has('Season Pack'))
@if ($loop->first && ! array_key_exists('Season Pack', $season))
open
@endif
>