0.0.5-fixes
Some checks failed
deploy / deploy (push) Failing after 4m9s

This commit is contained in:
Untone 2024-10-22 00:11:33 +03:00
parent c5038dd610
commit 4a1f985cce
3 changed files with 36 additions and 32 deletions

View File

@ -1,6 +1,6 @@
[package] [package]
name = "discoursio-quoter" name = "discoursio-quoter"
version = "0.0.4" version = "0.0.5"
edition = "2021" edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View File

@ -4,7 +4,7 @@ use aws_sdk_s3::{config::Credentials, Client as S3Client};
use redis::{aio::MultiplexedConnection, AsyncCommands, Client as RedisClient}; use redis::{aio::MultiplexedConnection, AsyncCommands, Client as RedisClient};
use std::{env, time::Duration}; use std::{env, time::Duration};
use tokio::time::interval; use tokio::time::interval;
use std::collections::HashMap;
use crate::s3_utils::check_file_exists; use crate::s3_utils::check_file_exists;
#[derive(Clone)] #[derive(Clone)]
@ -110,12 +110,13 @@ impl AppState {
for object in objects.iter() { for object in objects.iter() {
if let Some(key) = &object.key { if let Some(key) = &object.key {
let parts: Vec<&str> = key.split('.').collect(); let parts: Vec<&str> = key.split('.').collect();
if parts.len() > 1 && !parts.last().unwrap().contains('/') { let filename = parts.first().unwrap_or(&"");
let filename = parts[0..parts.len()-1].join("."); let ext = parts.get(1).unwrap_or(&"");
file_list.entry(filename).or_insert(key.clone()); if ext.contains('/') {
} else { continue;
file_list.entry(key.to_string()).or_insert(key.clone());
} }
let filename_with_extension = format!("{}.{}", filename, ext);
file_list.insert(filename_with_extension, key.clone());
} }
} }
@ -150,25 +151,25 @@ impl AppState {
} }
/// Сохраняет маппинг старого пути из AWS S3 на новый путь в Storj S3. /// Сохраняет маппинг старого пути из AWS S3 на новый путь в Storj S3.
async fn save_path_by_filekey( async fn save_path_by_filename_with_extension(
&self, &self,
filekey: &str, filename_with_extension: &str,
path: &str, path: &str,
) -> Result<(), actix_web::Error> { ) -> Result<(), actix_web::Error> {
let mut redis = self.redis.clone(); let mut redis = self.redis.clone();
// Храним маппинг в формате Hash: old_path -> new_path // Храним маппинг в формате Hash: old_path -> new_path
redis redis
.hset::<_, &str, &str, ()>(PATH_MAPPING_KEY, filekey, path) .hset::<_, &str, &str, ()>(PATH_MAPPING_KEY, filename_with_extension, path)
.await .await
.map_err(|_| ErrorInternalServerError("Failed to save path mapping in Redis"))?; .map_err(|_| ErrorInternalServerError("Failed to save path mapping in Redis"))?;
Ok(()) Ok(())
} }
/// Получает путь в хранилище из ключа (имени файла) в Redis. /// Получает путь в хранилище из ключа (имени файла) в Redis.
pub async fn get_path(&self, filekey: &str) -> Result<Option<String>, actix_web::Error> { pub async fn get_path(&self, filename_with_extension: &str) -> Result<Option<String>, actix_web::Error> {
let mut redis = self.redis.clone(); let mut redis = self.redis.clone();
let new_path: Option<String> = redis let new_path: Option<String> = redis
.hget(PATH_MAPPING_KEY, filekey) .hget(PATH_MAPPING_KEY, filename_with_extension)
.await .await
.map_err(|_| ErrorInternalServerError("Failed to get path mapping from Redis"))?; .map_err(|_| ErrorInternalServerError("Failed to get path mapping from Redis"))?;
Ok(new_path) Ok(new_path)
@ -186,35 +187,38 @@ impl AppState {
for object in objects { for object in objects {
if let Some(key) = object.key { if let Some(key) = object.key {
// Получаем имя файла с расширением // Получаем имя файла с расширением
let [filename, ext] = key.split('.').collect::<Vec<&str>>(); let parts: Vec<&str> = key.split('.').collect();
let filename = parts.first().unwrap_or(&"");
let ext = parts.get(1).unwrap_or(&"");
if ext.contains('/') {
continue;
}
let filename_with_extension = format!("{}.{}", filename, ext);
if filename.is_empty() { if filename.is_empty() {
eprint!("Пустое имя файла {}", key); eprint!("[ERROR] empty filename: {}", key);
} else { } else {
// Проверяем, существует ли файл на Storj S3 // Проверяем, существует ли файл на Storj S3
match check_file_exists(&self.s3_client, &self.s3_bucket, filename) match check_file_exists(&self.s3_client, &self.s3_bucket, &filename_with_extension)
.await .await
{ {
Ok(false) => { Ok(false) => {
// Сохраняем маппинг пути // Сохраняем маппинг пути
if let Err(e) = if let Err(e) =
self.save_path_by_filekey(filename, &key).await self.save_path_by_filename_with_extension(&filename_with_extension, &key).await
{ {
eprintln!( eprintln!("[ERROR] save {}: {:?}", key, e);
"[ОШИБКА СОХРАНЕНИЯ] {}: {:?}",
filename_with_extension, e
);
} else { } else {
println!("{}", filename_with_extension); println!("{}", key);
} }
} }
Ok(true) => { Ok(true) => {
println!("Файл {} уже существует в Storj.", filename); println!("Already exists in Storj: {}", filename_with_extension);
} }
Err(e) => { Err(e) => {
eprintln!( eprintln!(
"Ошибка при проверке файла {} на Storj: {:?}", "[ERROR] check {}: {:?}",
filename, e filename_with_extension, e
); );
} }
} }
@ -222,11 +226,11 @@ impl AppState {
} }
} }
} else { } else {
println!("Список файлов в AWS S3 пуст."); println!("AWS S3 file list is empty.");
} }
} }
Err(e) => { Err(e) => {
eprintln!("Не удалось получить список файлов из AWS S3: {:?}", e); eprintln!("[ERROR] get AWS S3 file list: {:?}", e);
} }
} }
} }

View File

@ -17,14 +17,14 @@ use crate::thumbnail::{
pub const MAX_WEEK_BYTES: u64 = 2 * 1024 * 1024 * 1024; pub const MAX_WEEK_BYTES: u64 = 2 * 1024 * 1024 * 1024;
/// Функция для обслуживания файла по заданному пути. /// Функция для обслуживания файла по заданному пути.
async fn serve_file(file_key: &str, state: &AppState) -> Result<HttpResponse, actix_web::Error> { async fn serve_file(filename_with_extension: &str, state: &AppState) -> Result<HttpResponse, actix_web::Error> {
// Проверяем наличие файла в Storj S3 // Проверяем наличие файла в Storj S3
if !check_file_exists(&state.s3_client, &state.s3_bucket, file_key).await? { if !check_file_exists(&state.s3_client, &state.s3_bucket, filename_with_extension).await? {
warn!("{}", file_key); warn!("{}", filename_with_extension);
return Err(ErrorInternalServerError("File not found in S3")); return Err(ErrorInternalServerError("File not found in S3"));
} }
let checked_filekey = state.get_path(file_key).await.unwrap().unwrap(); let checked_filekey = state.get_path(filename_with_extension).await.unwrap().unwrap();
// Получаем объект из Storj S3 // Получаем объект из Storj S3
let get_object_output = state let get_object_output = state
@ -43,7 +43,7 @@ async fn serve_file(file_key: &str, state: &AppState) -> Result<HttpResponse, ac
.map_err(|_| ErrorInternalServerError("Failed to read object body"))?; .map_err(|_| ErrorInternalServerError("Failed to read object body"))?;
let data_bytes = data.into_bytes(); let data_bytes = data.into_bytes();
let mime_type = MimeGuess::from_path(file_key).first_or_octet_stream(); // Определяем MIME-тип файла let mime_type = MimeGuess::from_path(filename_with_extension).first_or_octet_stream(); // Определяем MIME-тип файла
Ok(HttpResponse::Ok() Ok(HttpResponse::Ok()
.content_type(mime_type.as_ref()) .content_type(mime_type.as_ref())
@ -126,7 +126,7 @@ pub async fn proxy_handler(
path: web::Path<String>, path: web::Path<String>,
state: web::Data<AppState>, state: web::Data<AppState>,
) -> Result<HttpResponse, actix_web::Error> { ) -> Result<HttpResponse, actix_web::Error> {
info!("proxy_handler вызван с путем: {}", path); info!("proxy_handler: {}", path);
let requested_path = match state.get_path(&path).await { let requested_path = match state.get_path(&path).await {
Ok(Some(path)) => path, Ok(Some(path)) => path,