mirror of
https://github.com/koel/koel
synced 2024-11-27 22:40:26 +00:00
chore(perf): improve podcast adding performance
This commit is contained in:
parent
1afd8ba7d5
commit
7f3692b65e
4 changed files with 32 additions and 24 deletions
|
@ -16,7 +16,6 @@ use Illuminate\Support\Str;
|
|||
use Laravel\Scout\Searchable;
|
||||
use PhanAn\Poddle\Values\CategoryCollection;
|
||||
use PhanAn\Poddle\Values\ChannelMetadata;
|
||||
use PhanAn\Poddle\Values\Episode as EpisodeDTO;
|
||||
|
||||
/**
|
||||
* @property-read string $id
|
||||
|
@ -82,21 +81,6 @@ class Podcast extends Model
|
|||
->withTimestamps();
|
||||
}
|
||||
|
||||
public function addEpisodeByDTO(EpisodeDTO $dto): Episode
|
||||
{
|
||||
return $this->episodes()->create([
|
||||
'title' => $dto->title,
|
||||
'lyrics' => '',
|
||||
'path' => $dto->enclosure->url,
|
||||
'created_at' => $dto->metadata->pubDate ?: now(),
|
||||
'episode_metadata' => $dto->metadata,
|
||||
'episode_guid' => $dto->guid,
|
||||
'length' => $dto->metadata->duration ?? 0,
|
||||
'mtime' => time(),
|
||||
'is_public' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
/** @return array<mixed> */
|
||||
public function toSearchableArray(): array
|
||||
{
|
||||
|
|
|
@ -99,9 +99,7 @@ class Song extends Model
|
|||
|
||||
protected static function booted(): void
|
||||
{
|
||||
static::creating(static function (self $song): void {
|
||||
$song->id ??= Str::uuid()->toString();
|
||||
});
|
||||
static::creating(static fn (Song $song) => $song->id ??= Str::uuid()->toString());
|
||||
}
|
||||
|
||||
public static function query(?PlayableType $type = null, ?User $user = null): SongBuilder
|
||||
|
|
|
@ -17,6 +17,7 @@ use Illuminate\Support\Arr;
|
|||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Str;
|
||||
use PhanAn\Poddle\Poddle;
|
||||
use PhanAn\Poddle\Values\Episode as EpisodeValue;
|
||||
use PhanAn\Poddle\Values\EpisodeCollection;
|
||||
|
@ -118,13 +119,38 @@ class PodcastService
|
|||
private function synchronizeEpisodes(Podcast $podcast, EpisodeCollection $episodeCollection): void
|
||||
{
|
||||
$existingEpisodeGuids = $this->songRepository->getEpisodeGuidsByPodcast($podcast);
|
||||
$records = [];
|
||||
$ids = [];
|
||||
|
||||
/** @var EpisodeValue $episodeValue */
|
||||
foreach ($episodeCollection as $episodeValue) {
|
||||
if (!in_array($episodeValue->guid->value, $existingEpisodeGuids, true)) {
|
||||
$podcast->addEpisodeByDTO($episodeValue);
|
||||
$id = Str::uuid()->toString();
|
||||
$ids[] = $id;
|
||||
$records[] = [
|
||||
'id' => $id,
|
||||
'podcast_id' => $podcast->id,
|
||||
'title' => $episodeValue->title,
|
||||
'lyrics' => '',
|
||||
'path' => $episodeValue->enclosure->url,
|
||||
'created_at' => $episodeValue->metadata->pubDate ?: now(),
|
||||
'updated_at' => $episodeValue->metadata->pubDate ?: now(),
|
||||
'episode_metadata' => $episodeValue->metadata->toJson(),
|
||||
'episode_guid' => $episodeValue->guid,
|
||||
'length' => $episodeValue->metadata->duration ?? 0,
|
||||
'mtime' => time(),
|
||||
'is_public' => true,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// We use insert() instead of $podcast->episodes()->createMany() for better performance,
|
||||
// as the latter would trigger a separate query for each episode.
|
||||
Episode::insert($records);
|
||||
|
||||
// Since insert() doesn't trigger model events, Scout operations will not be called.
|
||||
// We have to manually update the search index.
|
||||
Episode::query()->whereIn('id', $ids)->searchable();
|
||||
}
|
||||
|
||||
private function subscribeUserToPodcast(User $user, Podcast $podcast): void
|
||||
|
|
|
@ -149,13 +149,13 @@ export const songStore = {
|
|||
getShareableUrl: (song: Playable) => `${window.BASE_URL}#/song/${song.id}`,
|
||||
|
||||
syncWithVault (playables: MaybeArray<Playable>) {
|
||||
return arrayify(playables).map(song => {
|
||||
let local = this.byId(song.id)
|
||||
return arrayify(playables).map(playable => {
|
||||
let local = this.byId(playable.id)
|
||||
|
||||
if (local) {
|
||||
merge(local, song)
|
||||
merge(local, playable)
|
||||
} else {
|
||||
local = reactive(song)
|
||||
local = reactive(playable)
|
||||
local.playback_state = 'Stopped'
|
||||
this.watchPlayCount(local)
|
||||
this.vault.set(local.id, local)
|
||||
|
|
Loading…
Reference in a new issue