mirror of
https://github.com/LemmyNet/lemmy.git
synced 2024-11-26 14:21:19 +00:00
Refactoring image inserts to use transactions.
This commit is contained in:
parent
44014c397d
commit
8a0b7c05d3
7 changed files with 66 additions and 51 deletions
|
@ -11,7 +11,7 @@ use encoding_rs::{Encoding, UTF_8};
|
|||
use lemmy_db_schema::{
|
||||
newtypes::DbUrl,
|
||||
source::{
|
||||
images::{ImageDetails, ImageDetailsForm, LocalImage, LocalImageForm},
|
||||
images::{ImageDetailsForm, LocalImage, LocalImageForm},
|
||||
local_site::LocalSite,
|
||||
post::{Post, PostUpdateForm},
|
||||
},
|
||||
|
@ -346,14 +346,12 @@ async fn generate_pictrs_thumbnail(image_url: &Url, context: &LemmyContext) -> L
|
|||
pictrs_alias: image.file.clone(),
|
||||
pictrs_delete_token: image.delete_token.clone(),
|
||||
};
|
||||
LocalImage::create(&mut context.pool(), &form).await?;
|
||||
|
||||
let protocol_and_hostname = context.settings().get_protocol_and_hostname();
|
||||
let thumbnail_url = image.thumbnail_url(&protocol_and_hostname)?;
|
||||
|
||||
// Also store the details for the image
|
||||
let details_form = image.details.build_image_details_form(&thumbnail_url);
|
||||
ImageDetails::create(&mut context.pool(), &details_form).await?;
|
||||
LocalImage::create(&mut context.pool(), &form, &details_form).await?;
|
||||
|
||||
Ok(thumbnail_url)
|
||||
} else {
|
||||
|
|
|
@ -16,7 +16,7 @@ use lemmy_db_schema::{
|
|||
community::{Community, CommunityModerator, CommunityUpdateForm},
|
||||
community_block::CommunityBlock,
|
||||
email_verification::{EmailVerification, EmailVerificationForm},
|
||||
images::{ImageDetails, RemoteImage},
|
||||
images::RemoteImage,
|
||||
instance::Instance,
|
||||
instance_block::InstanceBlock,
|
||||
local_site::LocalSite,
|
||||
|
@ -938,15 +938,13 @@ pub async fn process_markdown(
|
|||
|
||||
// Create images and image detail rows
|
||||
for link in links {
|
||||
RemoteImage::create(&mut context.pool(), &link).await?;
|
||||
|
||||
// Insert image details for the remote image
|
||||
let details_res = fetch_pictrs_proxied_image_details(&link, context).await;
|
||||
if let Ok(details) = details_res {
|
||||
let proxied =
|
||||
build_proxied_image_url(&link, &context.settings().get_protocol_and_hostname())?;
|
||||
let details_form = details.build_image_details_form(&proxied);
|
||||
ImageDetails::create(&mut context.pool(), &details_form).await?;
|
||||
RemoteImage::create(&mut context.pool(), &details_form).await?;
|
||||
}
|
||||
}
|
||||
Ok(text)
|
||||
|
@ -984,14 +982,12 @@ async fn proxy_image_link_internal(
|
|||
} else if image_mode == PictrsImageMode::ProxyAllImages {
|
||||
let proxied = build_proxied_image_url(&link, &context.settings().get_protocol_and_hostname())?;
|
||||
|
||||
RemoteImage::create(&mut context.pool(), &link).await?;
|
||||
|
||||
// This should fail softly, since pictrs might not even be running
|
||||
let details_res = fetch_pictrs_proxied_image_details(&link, context).await;
|
||||
|
||||
if let Ok(details) = details_res {
|
||||
let details_form = details.build_image_details_form(&proxied);
|
||||
ImageDetails::create(&mut context.pool(), &details_form).await?;
|
||||
RemoteImage::create(&mut context.pool(), &details_form).await?;
|
||||
}
|
||||
|
||||
Ok(proxied.into())
|
||||
|
|
|
@ -19,15 +19,29 @@ use diesel::{
|
|||
OptionalExtension,
|
||||
QueryDsl,
|
||||
};
|
||||
use diesel_async::RunQueryDsl;
|
||||
use url::Url;
|
||||
use diesel_async::{AsyncPgConnection, RunQueryDsl};
|
||||
|
||||
impl LocalImage {
|
||||
pub async fn create(pool: &mut DbPool<'_>, form: &LocalImageForm) -> Result<Self, Error> {
|
||||
pub async fn create(
|
||||
pool: &mut DbPool<'_>,
|
||||
form: &LocalImageForm,
|
||||
image_details_form: &ImageDetailsForm,
|
||||
) -> Result<Self, Error> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
insert_into(local_image::table)
|
||||
.values(form)
|
||||
.get_result::<Self>(conn)
|
||||
conn
|
||||
.build_transaction()
|
||||
.run(|conn| {
|
||||
Box::pin(async move {
|
||||
let local_insert = insert_into(local_image::table)
|
||||
.values(form)
|
||||
.get_result::<Self>(conn)
|
||||
.await;
|
||||
|
||||
ImageDetails::create(conn, image_details_form).await?;
|
||||
|
||||
local_insert
|
||||
}) as _
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
|
@ -45,15 +59,26 @@ impl LocalImage {
|
|||
}
|
||||
|
||||
impl RemoteImage {
|
||||
pub async fn create(pool: &mut DbPool<'_>, link_: &Url) -> Result<usize, Error> {
|
||||
pub async fn create(pool: &mut DbPool<'_>, form: &ImageDetailsForm) -> Result<usize, Error> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
let form = RemoteImageForm {
|
||||
link: link_.clone().into(),
|
||||
};
|
||||
insert_into(remote_image::table)
|
||||
.values(form)
|
||||
.on_conflict_do_nothing()
|
||||
.execute(conn)
|
||||
conn
|
||||
.build_transaction()
|
||||
.run(|conn| {
|
||||
Box::pin(async move {
|
||||
let remote_image_form = RemoteImageForm {
|
||||
link: form.link.clone(),
|
||||
};
|
||||
let remote_insert = insert_into(remote_image::table)
|
||||
.values(remote_image_form)
|
||||
.on_conflict_do_nothing()
|
||||
.execute(conn)
|
||||
.await;
|
||||
|
||||
ImageDetails::create(conn, form).await?;
|
||||
|
||||
remote_insert
|
||||
}) as _
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
|
@ -73,12 +98,14 @@ impl RemoteImage {
|
|||
}
|
||||
|
||||
impl ImageDetails {
|
||||
pub async fn create(pool: &mut DbPool<'_>, form: &ImageDetailsForm) -> Result<Self, Error> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
pub(crate) async fn create(
|
||||
conn: &mut AsyncPgConnection,
|
||||
form: &ImageDetailsForm,
|
||||
) -> Result<Self, Error> {
|
||||
insert_into(image_details::table)
|
||||
.values(form)
|
||||
.on_conflict_do_nothing()
|
||||
.get_result::<Self>(conn)
|
||||
.get_result::<ImageDetails>(conn)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
|
|
@ -315,7 +315,6 @@ diesel::table! {
|
|||
width -> Int4,
|
||||
height -> Int4,
|
||||
content_type -> Text,
|
||||
published -> Timestamptz,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -71,7 +71,6 @@ pub struct ImageDetails {
|
|||
pub width: i32,
|
||||
pub height: i32,
|
||||
pub content_type: String,
|
||||
pub published: DateTime<Utc>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, TypedBuilder)]
|
||||
|
|
|
@ -10,7 +10,10 @@ use actix_web::{
|
|||
HttpResponse,
|
||||
};
|
||||
use futures::stream::{Stream, StreamExt};
|
||||
use lemmy_api_common::{context::LemmyContext, request::PictrsFileDetails};
|
||||
use lemmy_api_common::{
|
||||
context::LemmyContext,
|
||||
request::{PictrsFileDetails, PictrsResponse},
|
||||
};
|
||||
use lemmy_db_schema::source::{
|
||||
images::{LocalImage, LocalImageForm, RemoteImage},
|
||||
local_site::LocalSite,
|
||||
|
@ -19,7 +22,7 @@ use lemmy_db_views::structs::LocalUserView;
|
|||
use lemmy_utils::{error::LemmyResult, rate_limit::RateLimitCell, REQWEST_TIMEOUT};
|
||||
use reqwest::Body;
|
||||
use reqwest_middleware::{ClientWithMiddleware, RequestBuilder};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::Deserialize;
|
||||
use std::time::Duration;
|
||||
use url::Url;
|
||||
use urlencoding::decode;
|
||||
|
@ -42,18 +45,6 @@ pub fn config(
|
|||
.service(web::resource("/pictrs/image/delete/{token}/{filename}").route(web::get().to(delete)));
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct Image {
|
||||
file: String,
|
||||
delete_token: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct Images {
|
||||
msg: String,
|
||||
files: Option<Vec<Image>>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct PictrsGetParams {
|
||||
format: Option<String>,
|
||||
|
@ -114,15 +105,21 @@ async fn upload(
|
|||
.await?;
|
||||
|
||||
let status = res.status();
|
||||
let images = res.json::<Images>().await?;
|
||||
let images = res.json::<PictrsResponse>().await?;
|
||||
if let Some(images) = &images.files {
|
||||
for uploaded_image in images {
|
||||
for image in images {
|
||||
let form = LocalImageForm {
|
||||
local_user_id: Some(local_user_view.local_user.id),
|
||||
pictrs_alias: uploaded_image.file.to_string(),
|
||||
pictrs_delete_token: uploaded_image.delete_token.to_string(),
|
||||
pictrs_alias: image.file.to_string(),
|
||||
pictrs_delete_token: image.delete_token.to_string(),
|
||||
};
|
||||
LocalImage::create(&mut context.pool(), &form).await?;
|
||||
|
||||
let protocol_and_hostname = context.settings().get_protocol_and_hostname();
|
||||
let thumbnail_url = image.thumbnail_url(&protocol_and_hostname)?;
|
||||
|
||||
// Also store the details for the image
|
||||
let details_form = image.details.build_image_details_form(&thumbnail_url);
|
||||
LocalImage::create(&mut context.pool(), &form, &details_form).await?;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@ CREATE TABLE image_details (
|
|||
link text PRIMARY KEY,
|
||||
width integer NOT NULL,
|
||||
height integer NOT NULL,
|
||||
content_type text NOT NULL,
|
||||
published timestamptz DEFAULT now() NOT NULL
|
||||
content_type text NOT NULL
|
||||
);
|
||||
|
||||
|
|
Loading…
Reference in a new issue