refactor: 引入 enum_dispatch 静态分发,提升性能 (#232)

This commit is contained in:
ᴀᴍᴛᴏᴀᴇʀ
2025-01-24 13:44:27 +08:00
committed by GitHub
parent 9e5a8b0573
commit 40cf22a7fa
10 changed files with 79 additions and 67 deletions

View File

@@ -9,7 +9,7 @@ use sea_orm::sea_query::{OnConflict, SimpleExpr};
use sea_orm::ActiveValue::Set;
use sea_orm::{DatabaseConnection, Unchanged};
use crate::adapter::{VideoListModel, _ActiveModel};
use crate::adapter::{VideoListModel, VideoListModelEnum, _ActiveModel};
use crate::bilibili::{BiliClient, Collection, CollectionItem, CollectionType, VideoInfo};
impl VideoListModel for collection::Model {
@@ -98,10 +98,7 @@ pub(super) async fn collection_from<'a>(
path: &Path,
bili_client: &'a BiliClient,
connection: &DatabaseConnection,
) -> Result<(
Box<dyn VideoListModel>,
Pin<Box<dyn Stream<Item = Result<VideoInfo>> + 'a>>,
)> {
) -> Result<(VideoListModelEnum, Pin<Box<dyn Stream<Item = Result<VideoInfo>> + 'a>>)> {
let collection = Collection::new(bili_client, collection_item);
let collection_info = collection.get_info().await?;
collection::Entity::insert(collection::ActiveModel {
@@ -124,18 +121,17 @@ pub(super) async fn collection_from<'a>(
.exec(connection)
.await?;
Ok((
Box::new(
collection::Entity::find()
.filter(
collection::Column::SId
.eq(collection_item.sid.clone())
.and(collection::Column::MId.eq(collection_item.mid.clone()))
.and(collection::Column::Type.eq(Into::<i32>::into(collection_item.collection_type.clone()))),
)
.one(connection)
.await?
.context("collection not found")?,
),
collection::Entity::find()
.filter(
collection::Column::SId
.eq(collection_item.sid.clone())
.and(collection::Column::MId.eq(collection_item.mid.clone()))
.and(collection::Column::Type.eq(Into::<i32>::into(collection_item.collection_type.clone()))),
)
.one(connection)
.await?
.context("collection not found")?
.into(),
Box::pin(collection.into_video_stream()),
))
}

View File

@@ -9,7 +9,7 @@ use sea_orm::sea_query::{OnConflict, SimpleExpr};
use sea_orm::ActiveValue::Set;
use sea_orm::{DatabaseConnection, Unchanged};
use crate::adapter::{VideoListModel, _ActiveModel};
use crate::adapter::{VideoListModel, VideoListModelEnum, _ActiveModel};
use crate::bilibili::{BiliClient, FavoriteList, VideoInfo};
impl VideoListModel for favorite::Model {
@@ -70,10 +70,7 @@ pub(super) async fn favorite_from<'a>(
path: &Path,
bili_client: &'a BiliClient,
connection: &DatabaseConnection,
) -> Result<(
Box<dyn VideoListModel>,
Pin<Box<dyn Stream<Item = Result<VideoInfo>> + 'a>>,
)> {
) -> Result<(VideoListModelEnum, Pin<Box<dyn Stream<Item = Result<VideoInfo>> + 'a>>)> {
let favorite = FavoriteList::new(bili_client, fid.to_owned());
let favorite_info = favorite.get_info().await?;
favorite::Entity::insert(favorite::ActiveModel {
@@ -90,13 +87,12 @@ pub(super) async fn favorite_from<'a>(
.exec(connection)
.await?;
Ok((
Box::new(
favorite::Entity::find()
.filter(favorite::Column::FId.eq(favorite_info.id))
.one(connection)
.await?
.context("favorite not found")?,
),
favorite::Entity::find()
.filter(favorite::Column::FId.eq(favorite_info.id))
.one(connection)
.await?
.context("favorite not found")?
.into(),
Box::pin(favorite.into_video_stream()),
))
}

View File

@@ -7,17 +7,33 @@ use std::path::Path;
use std::pin::Pin;
use anyhow::Result;
use enum_dispatch::enum_dispatch;
use futures::Stream;
use sea_orm::entity::prelude::*;
use sea_orm::sea_query::SimpleExpr;
use sea_orm::DatabaseConnection;
#[rustfmt::skip]
use bili_sync_entity::collection::Model as Collection;
use bili_sync_entity::favorite::Model as Favorite;
use bili_sync_entity::submission::Model as Submission;
use bili_sync_entity::watch_later::Model as WatchLater;
use crate::adapter::collection::collection_from;
use crate::adapter::favorite::favorite_from;
use crate::adapter::submission::submission_from;
use crate::adapter::watch_later::watch_later_from;
use crate::bilibili::{BiliClient, CollectionItem, VideoInfo};
#[enum_dispatch]
pub enum VideoListModelEnum {
Favorite,
Collection,
Submission,
WatchLater,
}
#[enum_dispatch(VideoListModelEnum)]
pub trait VideoListModel {
/// 获取特定视频列表的筛选条件
fn filter_expr(&self) -> SimpleExpr;
@@ -67,10 +83,7 @@ pub async fn video_list_from<'a>(
path: &Path,
bili_client: &'a BiliClient,
connection: &DatabaseConnection,
) -> Result<(
Box<dyn VideoListModel>,
Pin<Box<dyn Stream<Item = Result<VideoInfo>> + 'a>>,
)> {
) -> Result<(VideoListModelEnum, Pin<Box<dyn Stream<Item = Result<VideoInfo>> + 'a>>)> {
match args {
Args::Favorite { fid } => favorite_from(fid, path, bili_client, connection).await,
Args::Collection { collection_item } => collection_from(collection_item, path, bili_client, connection).await,

View File

@@ -9,7 +9,7 @@ use sea_orm::sea_query::{OnConflict, SimpleExpr};
use sea_orm::ActiveValue::Set;
use sea_orm::{DatabaseConnection, Unchanged};
use crate::adapter::{VideoListModel, _ActiveModel};
use crate::adapter::{VideoListModel, VideoListModelEnum, _ActiveModel};
use crate::bilibili::{BiliClient, Submission, VideoInfo};
impl VideoListModel for submission::Model {
@@ -82,10 +82,7 @@ pub(super) async fn submission_from<'a>(
path: &Path,
bili_client: &'a BiliClient,
connection: &DatabaseConnection,
) -> Result<(
Box<dyn VideoListModel>,
Pin<Box<dyn Stream<Item = Result<VideoInfo>> + 'a>>,
)> {
) -> Result<(VideoListModelEnum, Pin<Box<dyn Stream<Item = Result<VideoInfo>> + 'a>>)> {
let submission = Submission::new(bili_client, upper_id.to_owned());
let upper = submission.get_info().await?;
submission::Entity::insert(submission::ActiveModel {
@@ -102,13 +99,12 @@ pub(super) async fn submission_from<'a>(
.exec(connection)
.await?;
Ok((
Box::new(
submission::Entity::find()
.filter(submission::Column::UpperId.eq(upper.mid))
.one(connection)
.await?
.context("submission not found")?,
),
submission::Entity::find()
.filter(submission::Column::UpperId.eq(upper.mid))
.one(connection)
.await?
.context("submission not found")?
.into(),
Box::pin(submission.into_video_stream()),
))
}

View File

@@ -9,7 +9,7 @@ use sea_orm::sea_query::{OnConflict, SimpleExpr};
use sea_orm::ActiveValue::Set;
use sea_orm::{DatabaseConnection, Unchanged};
use crate::adapter::{VideoListModel, _ActiveModel};
use crate::adapter::{VideoListModel, VideoListModelEnum, _ActiveModel};
use crate::bilibili::{BiliClient, VideoInfo, WatchLater};
impl VideoListModel for watch_later::Model {
@@ -66,10 +66,7 @@ pub(super) async fn watch_later_from<'a>(
path: &Path,
bili_client: &'a BiliClient,
connection: &DatabaseConnection,
) -> Result<(
Box<dyn VideoListModel>,
Pin<Box<dyn Stream<Item = Result<VideoInfo>> + 'a>>,
)> {
) -> Result<(VideoListModelEnum, Pin<Box<dyn Stream<Item = Result<VideoInfo>> + 'a>>)> {
let watch_later = WatchLater::new(bili_client);
watch_later::Entity::insert(watch_later::ActiveModel {
id: Set(1),
@@ -84,13 +81,12 @@ pub(super) async fn watch_later_from<'a>(
.exec(connection)
.await?;
Ok((
Box::new(
watch_later::Entity::find()
.filter(watch_later::Column::Id.eq(1))
.one(connection)
.await?
.context("watch_later not found")?,
),
watch_later::Entity::find()
.filter(watch_later::Column::Id.eq(1))
.one(connection)
.await?
.context("watch_later not found")?
.into(),
Box::pin(watch_later.into_video_stream()),
))
}