tracing
This commit is contained in:
@@ -16,11 +16,9 @@ async fn main() -> anyhow::Result<()> {
|
||||
|
||||
let config = Config::from_env()?;
|
||||
|
||||
env_logger::builder()
|
||||
.format_target(false)
|
||||
.filter_level(log::LevelFilter::Info)
|
||||
.parse_default_env()
|
||||
.filter_level(config.log_level)
|
||||
tracing_subscriber::fmt()
|
||||
.with_max_level(config.log_level)
|
||||
.with_target(cfg!(debug_assertions))
|
||||
.init();
|
||||
|
||||
let metrics = MetricsDebugLogger::new();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::{env, str::FromStr as _};
|
||||
use std::{env, str::FromStr};
|
||||
|
||||
use anyhow::Context as _;
|
||||
use log::LevelFilter;
|
||||
use tracing::level_filters::LevelFilter;
|
||||
|
||||
const DATABASE_URL_KEY: &str = "DATABASE_URL";
|
||||
const DATABASE_NAME_KEY: &str = "DATABASE_NAME";
|
||||
|
||||
@@ -28,6 +28,7 @@ pub enum ListFilesError {
|
||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct DeleteDirectoryRequest {
|
||||
path: AbsoluteFilePath,
|
||||
force: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
@@ -36,13 +37,17 @@ pub struct DeleteFileRequest {
|
||||
}
|
||||
|
||||
impl DeleteDirectoryRequest {
|
||||
pub fn new(path: AbsoluteFilePath) -> Self {
|
||||
Self { path }
|
||||
pub fn new(path: AbsoluteFilePath, force: bool) -> Self {
|
||||
Self { path, force }
|
||||
}
|
||||
|
||||
pub fn path(&self) -> &AbsoluteFilePath {
|
||||
&self.path
|
||||
}
|
||||
|
||||
pub fn force(&self) -> bool {
|
||||
self.force
|
||||
}
|
||||
}
|
||||
|
||||
impl DeleteFileRequest {
|
||||
@@ -57,6 +62,10 @@ impl DeleteFileRequest {
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum DeleteDirectoryError {
|
||||
#[error("The directory does not exist")]
|
||||
NotFound,
|
||||
#[error("The directory is not empty")]
|
||||
NotEmpty,
|
||||
#[error(transparent)]
|
||||
Unknown(#[from] anyhow::Error),
|
||||
}
|
||||
@@ -84,6 +93,8 @@ impl CreateDirectoryRequest {
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum CreateDirectoryError {
|
||||
#[error("The directory already exists")]
|
||||
Exists,
|
||||
#[error(transparent)]
|
||||
Unknown(#[from] anyhow::Error),
|
||||
}
|
||||
|
||||
@@ -148,7 +148,7 @@ impl DeleteWarrenDirectoryRequest {
|
||||
|
||||
pub fn to_fs_request(self, warren: &Warren) -> DeleteDirectoryRequest {
|
||||
let path = warren.path().clone().join(&self.path.to_relative());
|
||||
DeleteDirectoryRequest::new(path)
|
||||
DeleteDirectoryRequest::new(path, self.force)
|
||||
}
|
||||
|
||||
pub fn warren_id(&self) -> &Uuid {
|
||||
|
||||
127
backend/src/lib/inbound/http/errors.rs
Normal file
127
backend/src/lib/inbound/http/errors.rs
Normal file
@@ -0,0 +1,127 @@
|
||||
use crate::{
|
||||
domain::warren::models::{
|
||||
file::{CreateDirectoryError, DeleteDirectoryError, DeleteFileError, ListFilesError},
|
||||
warren::{
|
||||
CreateWarrenDirectoryError, DeleteWarrenDirectoryError, DeleteWarrenFileError,
|
||||
FetchWarrenError, ListWarrenFilesError, ListWarrensError, RenameWarrenEntryError,
|
||||
UploadWarrenFilesError,
|
||||
},
|
||||
},
|
||||
inbound::http::responses::ApiError,
|
||||
};
|
||||
|
||||
impl From<CreateDirectoryError> for ApiError {
|
||||
fn from(value: CreateDirectoryError) -> Self {
|
||||
match value {
|
||||
CreateDirectoryError::Exists => match value {
|
||||
CreateDirectoryError::Exists => {
|
||||
Self::BadRequest("The directory already exists".to_string())
|
||||
}
|
||||
CreateDirectoryError::Unknown(error) => {
|
||||
Self::InternalServerError(error.to_string())
|
||||
}
|
||||
},
|
||||
CreateDirectoryError::Unknown(error) => Self::InternalServerError(error.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CreateWarrenDirectoryError> for ApiError {
|
||||
fn from(value: CreateWarrenDirectoryError) -> Self {
|
||||
match value {
|
||||
CreateWarrenDirectoryError::FileSystem(fs) => fs.into(),
|
||||
CreateWarrenDirectoryError::Unknown(error) => {
|
||||
Self::InternalServerError(error.to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DeleteDirectoryError> for ApiError {
|
||||
fn from(value: DeleteDirectoryError) -> Self {
|
||||
match value {
|
||||
DeleteDirectoryError::NotFound => {
|
||||
Self::NotFound("The directory does not exist".to_string())
|
||||
}
|
||||
DeleteDirectoryError::NotEmpty => {
|
||||
Self::BadRequest("The directory is not empty".to_string())
|
||||
}
|
||||
DeleteDirectoryError::Unknown(e) => Self::InternalServerError(e.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DeleteWarrenDirectoryError> for ApiError {
|
||||
fn from(value: DeleteWarrenDirectoryError) -> Self {
|
||||
match value {
|
||||
DeleteWarrenDirectoryError::FileSystem(fs) => fs.into(),
|
||||
DeleteWarrenDirectoryError::Unknown(error) => {
|
||||
Self::InternalServerError(error.to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DeleteFileError> for ApiError {
|
||||
fn from(value: DeleteFileError) -> Self {
|
||||
Self::InternalServerError(value.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DeleteWarrenFileError> for ApiError {
|
||||
fn from(value: DeleteWarrenFileError) -> Self {
|
||||
match value {
|
||||
DeleteWarrenFileError::FileSystem(fs) => fs.into(),
|
||||
DeleteWarrenFileError::Unknown(error) => Self::InternalServerError(error.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FetchWarrenError> for ApiError {
|
||||
fn from(value: FetchWarrenError) -> Self {
|
||||
match value {
|
||||
FetchWarrenError::NotFound(uuid) => {
|
||||
Self::NotFound(format!("Warren with id {uuid} does not exist"))
|
||||
}
|
||||
FetchWarrenError::Unknown(error) => Self::InternalServerError(error.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ListFilesError> for ApiError {
|
||||
fn from(value: ListFilesError) -> Self {
|
||||
match value {
|
||||
ListFilesError::NotFound(_) => {
|
||||
Self::NotFound("Could not find the requested directory".to_string())
|
||||
}
|
||||
ListFilesError::Unknown(e) => Self::InternalServerError(e.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ListWarrenFilesError> for ApiError {
|
||||
fn from(value: ListWarrenFilesError) -> Self {
|
||||
match value {
|
||||
ListWarrenFilesError::FileSystem(fs_error) => fs_error.into(),
|
||||
ListWarrenFilesError::Unknown(error) => Self::InternalServerError(error.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ListWarrensError> for ApiError {
|
||||
fn from(error: ListWarrensError) -> Self {
|
||||
Self::InternalServerError(error.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RenameWarrenEntryError> for ApiError {
|
||||
fn from(value: RenameWarrenEntryError) -> Self {
|
||||
ApiError::InternalServerError(value.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<UploadWarrenFilesError> for ApiError {
|
||||
fn from(value: UploadWarrenFilesError) -> Self {
|
||||
ApiError::InternalServerError(value.to_string())
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ use crate::{
|
||||
domain::warren::{
|
||||
models::{
|
||||
file::{AbsoluteFilePathError, FilePath, FilePathError},
|
||||
warren::{CreateWarrenDirectoryError, CreateWarrenDirectoryRequest},
|
||||
warren::CreateWarrenDirectoryRequest,
|
||||
},
|
||||
ports::WarrenService,
|
||||
},
|
||||
@@ -62,12 +62,6 @@ impl CreateWarrenDirectoryHttpRequestBody {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CreateWarrenDirectoryError> for ApiError {
|
||||
fn from(_value: CreateWarrenDirectoryError) -> Self {
|
||||
ApiError::InternalServerError("Internal server error".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn create_warren_directory<WS>(
|
||||
State(state): State<AppState<WS>>,
|
||||
Json(request): Json<CreateWarrenDirectoryHttpRequestBody>,
|
||||
|
||||
@@ -7,7 +7,7 @@ use crate::{
|
||||
domain::warren::{
|
||||
models::{
|
||||
file::{AbsoluteFilePathError, FilePath, FilePathError},
|
||||
warren::{DeleteWarrenDirectoryError, DeleteWarrenDirectoryRequest},
|
||||
warren::DeleteWarrenDirectoryRequest,
|
||||
},
|
||||
ports::WarrenService,
|
||||
},
|
||||
@@ -64,12 +64,6 @@ impl DeleteWarrenDirectoryHttpRequestBody {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DeleteWarrenDirectoryError> for ApiError {
|
||||
fn from(_value: DeleteWarrenDirectoryError) -> Self {
|
||||
ApiError::InternalServerError("Internal server error".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn delete_warren_directory<WS>(
|
||||
State(state): State<AppState<WS>>,
|
||||
Json(request): Json<DeleteWarrenDirectoryHttpRequestBody>,
|
||||
|
||||
@@ -7,7 +7,7 @@ use crate::{
|
||||
domain::warren::{
|
||||
models::{
|
||||
file::{AbsoluteFilePathError, FilePath, FilePathError},
|
||||
warren::{DeleteWarrenFileError, DeleteWarrenFileRequest},
|
||||
warren::DeleteWarrenFileRequest,
|
||||
},
|
||||
ports::WarrenService,
|
||||
},
|
||||
@@ -62,12 +62,6 @@ impl DeleteWarrenFileHttpRequestBody {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DeleteWarrenFileError> for ApiError {
|
||||
fn from(_value: DeleteWarrenFileError) -> Self {
|
||||
ApiError::InternalServerError("Internal server error".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn delete_warren_file<WS>(
|
||||
State(state): State<AppState<WS>>,
|
||||
Json(request): Json<DeleteWarrenFileHttpRequestBody>,
|
||||
|
||||
@@ -5,7 +5,7 @@ use uuid::Uuid;
|
||||
|
||||
use crate::{
|
||||
domain::warren::{
|
||||
models::warren::{FetchWarrenError, FetchWarrenRequest, Warren},
|
||||
models::warren::{FetchWarrenRequest, Warren},
|
||||
ports::WarrenService,
|
||||
},
|
||||
inbound::http::{
|
||||
@@ -29,25 +29,12 @@ impl Into<FetchWarrenResponseData> for &Warren {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<FetchWarrenError> for ApiError {
|
||||
fn from(error: FetchWarrenError) -> Self {
|
||||
match error {
|
||||
FetchWarrenError::NotFound(uuid) => {
|
||||
Self::NotFound(format!("Warren with id {uuid} does not exist"))
|
||||
}
|
||||
FetchWarrenError::Unknown(_cause) => {
|
||||
Self::InternalServerError("Internal server error".to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Error)]
|
||||
enum ParseFetchWarrenHttpRequestError {}
|
||||
|
||||
impl From<ParseFetchWarrenHttpRequestError> for ApiError {
|
||||
fn from(_e: ParseFetchWarrenHttpRequestError) -> Self {
|
||||
ApiError::InternalServerError("Internal server error".to_string())
|
||||
fn from(e: ParseFetchWarrenHttpRequestError) -> Self {
|
||||
ApiError::BadRequest(e.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ use crate::{
|
||||
domain::warren::{
|
||||
models::{
|
||||
file::{AbsoluteFilePathError, File, FileMimeType, FilePath, FilePathError, FileType},
|
||||
warren::{ListWarrenFilesError, ListWarrenFilesRequest},
|
||||
warren::ListWarrenFilesRequest,
|
||||
},
|
||||
ports::WarrenService,
|
||||
},
|
||||
@@ -94,12 +94,6 @@ impl From<Vec<File>> for ListWarrenFilesResponseData {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ListWarrenFilesError> for ApiError {
|
||||
fn from(_value: ListWarrenFilesError) -> Self {
|
||||
ApiError::InternalServerError("Internal server error".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn list_warren_files<WS: WarrenService>(
|
||||
State(state): State<AppState<WS>>,
|
||||
Json(request): Json<ListWarrenFilesHttpRequestBody>,
|
||||
|
||||
@@ -4,7 +4,7 @@ use uuid::Uuid;
|
||||
|
||||
use crate::{
|
||||
domain::warren::{
|
||||
models::warren::{ListWarrensError, ListWarrensRequest, Warren},
|
||||
models::warren::{ListWarrensRequest, Warren},
|
||||
ports::WarrenService,
|
||||
},
|
||||
inbound::http::{
|
||||
@@ -41,16 +41,6 @@ impl From<&Vec<Warren>> for ListWarrensResponseData {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ListWarrensError> for ApiError {
|
||||
fn from(error: ListWarrensError) -> Self {
|
||||
match error {
|
||||
ListWarrensError::Unknown(_cause) => {
|
||||
Self::InternalServerError("Internal server error".to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn list_warrens<WS: WarrenService>(
|
||||
State(state): State<AppState<WS>>,
|
||||
) -> Result<ApiSuccess<ListWarrensResponseData>, ApiError> {
|
||||
|
||||
@@ -10,7 +10,7 @@ use crate::{
|
||||
AbsoluteFilePath, AbsoluteFilePathError, FileName, FileNameError, FilePath,
|
||||
FilePathError,
|
||||
},
|
||||
warren::{RenameWarrenEntryError, RenameWarrenEntryRequest},
|
||||
warren::RenameWarrenEntryRequest,
|
||||
},
|
||||
ports::WarrenService,
|
||||
},
|
||||
@@ -78,12 +78,6 @@ impl From<ParseRenameWarrenEntryHttpRequestError> for ApiError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RenameWarrenEntryError> for ApiError {
|
||||
fn from(_: RenameWarrenEntryError) -> Self {
|
||||
ApiError::InternalServerError("Internal server error".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn rename_warren_entry<WS: WarrenService>(
|
||||
State(state): State<AppState<WS>>,
|
||||
Json(request): Json<RenameWarrenEntryHttpRequestBody>,
|
||||
|
||||
@@ -7,10 +7,7 @@ use crate::{
|
||||
domain::warren::{
|
||||
models::{
|
||||
file::{AbsoluteFilePathError, FileName, FileNameError, FilePath, FilePathError},
|
||||
warren::{
|
||||
UploadFile, UploadFileList, UploadFileListError, UploadWarrenFilesError,
|
||||
UploadWarrenFilesRequest,
|
||||
},
|
||||
warren::{UploadFile, UploadFileList, UploadFileListError, UploadWarrenFilesRequest},
|
||||
},
|
||||
ports::WarrenService,
|
||||
},
|
||||
@@ -95,12 +92,6 @@ impl From<ParseUploadWarrenFilesHttpRequestError> for ApiError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<UploadWarrenFilesError> for ApiError {
|
||||
fn from(_: UploadWarrenFilesError) -> Self {
|
||||
ApiError::InternalServerError("Internal server error".to_string())
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn upload_warren_files<WS>(
|
||||
State(state): State<AppState<WS>>,
|
||||
TypedMultipart(multipart): TypedMultipart<UploadWarrenFilesHttpRequestBody>,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
pub mod errors;
|
||||
pub mod handlers;
|
||||
pub mod responses;
|
||||
|
||||
@@ -7,7 +8,13 @@ use anyhow::Context;
|
||||
use axum::{Router, http::HeaderValue};
|
||||
use handlers::warrens;
|
||||
use tokio::net::TcpListener;
|
||||
use tower_http::{cors::CorsLayer, services::ServeDir};
|
||||
use tower::ServiceBuilder;
|
||||
use tower_http::{
|
||||
cors::CorsLayer,
|
||||
services::ServeDir,
|
||||
trace::{DefaultOnBodyChunk, DefaultOnFailure, DefaultOnRequest, DefaultOnResponse},
|
||||
};
|
||||
use tracing::Level;
|
||||
|
||||
use crate::domain::warren::ports::WarrenService;
|
||||
|
||||
@@ -55,19 +62,28 @@ impl HttpServer {
|
||||
) -> anyhow::Result<Self> {
|
||||
let cors_layer = cors_layer(&config)?;
|
||||
|
||||
let trace_layer = tower_http::trace::TraceLayer::new_for_http()
|
||||
.make_span_with(|request: &axum::extract::Request| {
|
||||
let uri = request.uri().to_string();
|
||||
tracing::info_span!("http_request", "{} {}", request.method(), uri)
|
||||
})
|
||||
.on_response(DefaultOnResponse::new().level(Level::TRACE))
|
||||
.on_request(DefaultOnRequest::new().level(Level::TRACE))
|
||||
.on_failure(DefaultOnFailure::new().level(Level::INFO));
|
||||
|
||||
let state = AppState {
|
||||
warren_service: Arc::new(warren_service),
|
||||
};
|
||||
|
||||
let mut router = Router::new()
|
||||
.nest("/api", api_routes())
|
||||
.layer(cors_layer)
|
||||
.layer(ServiceBuilder::new().layer(trace_layer).layer(cors_layer))
|
||||
.with_state(state);
|
||||
|
||||
if let Some(frontend_dir) = config.static_frontend_dir {
|
||||
let frontend_service = ServeDir::new(frontend_dir);
|
||||
tracing::debug!("Registering static frontend: {}", frontend_dir);
|
||||
|
||||
log::debug!("Registering static frontend");
|
||||
let frontend_service = ServeDir::new(frontend_dir);
|
||||
router = router.fallback_service(frontend_service);
|
||||
}
|
||||
|
||||
@@ -80,7 +96,7 @@ impl HttpServer {
|
||||
}
|
||||
|
||||
pub async fn run(self) -> anyhow::Result<()> {
|
||||
log::info!("Listening on {}", self.listener.local_addr()?);
|
||||
tracing::info!("Listening on {}", self.listener.local_addr()?);
|
||||
|
||||
axum::serve(self.listener, self.router)
|
||||
.await
|
||||
|
||||
@@ -64,13 +64,16 @@ impl IntoResponse for ApiError {
|
||||
use ApiError::*;
|
||||
|
||||
match self {
|
||||
BadRequest(_) => (StatusCode::BAD_REQUEST, "Bad request".to_string()).into_response(),
|
||||
NotFound(_) => (StatusCode::NOT_FOUND, "Not found".to_string()).into_response(),
|
||||
InternalServerError(_) => (
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
"Internal server error".to_string(),
|
||||
)
|
||||
.into_response(),
|
||||
BadRequest(e) => (StatusCode::BAD_REQUEST, e).into_response(),
|
||||
NotFound(e) => (StatusCode::NOT_FOUND, e).into_response(),
|
||||
InternalServerError(e) => {
|
||||
tracing::error!("{}", e);
|
||||
(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
"Internal Server Error".to_string(),
|
||||
)
|
||||
.into_response()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
use std::time::UNIX_EPOCH;
|
||||
|
||||
use anyhow::{Context, anyhow, bail};
|
||||
use tokio::{fs, io::AsyncWriteExt as _};
|
||||
use tokio::{
|
||||
fs,
|
||||
io::{self, AsyncWriteExt as _},
|
||||
};
|
||||
|
||||
use crate::domain::warren::{
|
||||
models::file::{
|
||||
@@ -91,9 +94,13 @@ impl FileSystem {
|
||||
/// Actually created a directory in the underlying file system
|
||||
///
|
||||
/// * `path`: The directory's absolute path (absolute not in relation to the root file system but `self.base_directory`)
|
||||
async fn create_dir(&self, path: &AbsoluteFilePath) -> anyhow::Result<FilePath> {
|
||||
async fn create_dir(&self, path: &AbsoluteFilePath) -> io::Result<FilePath> {
|
||||
let file_path = self.get_target_path(path);
|
||||
|
||||
if fs::try_exists(&file_path).await? {
|
||||
return Err(io::ErrorKind::AlreadyExists.into());
|
||||
}
|
||||
|
||||
fs::create_dir(&file_path).await?;
|
||||
|
||||
Ok(file_path)
|
||||
@@ -103,7 +110,7 @@ impl FileSystem {
|
||||
///
|
||||
/// * `path`: The directory's absolute path (absolute not in relation to the root file system but `self.base_directory`)
|
||||
/// * `force`: Whether to delete directories that are not empty
|
||||
async fn remove_dir(&self, path: &AbsoluteFilePath, force: bool) -> anyhow::Result<FilePath> {
|
||||
async fn remove_dir(&self, path: &AbsoluteFilePath, force: bool) -> io::Result<FilePath> {
|
||||
let file_path = self.get_target_path(path);
|
||||
|
||||
if force {
|
||||
@@ -157,7 +164,7 @@ impl FileSystem {
|
||||
};
|
||||
|
||||
if fs::try_exists(&new_path).await? {
|
||||
bail!("File already exists");
|
||||
bail!("File exists");
|
||||
}
|
||||
|
||||
fs::rename(current_path, &new_path).await?;
|
||||
@@ -182,35 +189,40 @@ impl FileSystemRepository for FileSystem {
|
||||
&self,
|
||||
request: CreateDirectoryRequest,
|
||||
) -> Result<FilePath, CreateDirectoryError> {
|
||||
let created_path = self.create_dir(request.path()).await.context(format!(
|
||||
"Failed to create directory at path {}",
|
||||
request.path()
|
||||
))?;
|
||||
|
||||
Ok(created_path)
|
||||
match self.create_dir(request.path()).await {
|
||||
Ok(path) => Ok(path),
|
||||
Err(e) => match e.kind() {
|
||||
std::io::ErrorKind::AlreadyExists => Err(CreateDirectoryError::Exists),
|
||||
_ => Err(anyhow!("Failed to create directory at path: {}", request.path()).into()),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
async fn delete_directory(
|
||||
&self,
|
||||
request: DeleteDirectoryRequest,
|
||||
) -> Result<FilePath, DeleteDirectoryError> {
|
||||
let deleted_path = self
|
||||
.remove_dir(request.path(), false)
|
||||
.await
|
||||
.context(format!("Failed to delete directory at {}", request.path()))?;
|
||||
|
||||
Ok(deleted_path)
|
||||
match self.remove_dir(request.path(), request.force()).await {
|
||||
Ok(deleted_path) => return Ok(deleted_path),
|
||||
Err(e) => match e.kind() {
|
||||
std::io::ErrorKind::NotFound => Err(DeleteDirectoryError::NotFound),
|
||||
std::io::ErrorKind::DirectoryNotEmpty => Err(DeleteDirectoryError::NotEmpty),
|
||||
_ => Err(anyhow!("Failed to delete directory at {}: {e:?}", request.path()).into()),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
async fn create_file(&self, request: CreateFileRequest) -> Result<FilePath, CreateFileError> {
|
||||
let file_path = self
|
||||
.write_file(request.path(), request.data())
|
||||
.await
|
||||
.context(format!(
|
||||
"Failed to write {} byte(s) to path {}",
|
||||
request.data().len(),
|
||||
request.path()
|
||||
))?;
|
||||
.map_err(|e| {
|
||||
anyhow!(
|
||||
"Failed to write {} byte(s) to path {}: {e:?}",
|
||||
request.data().len(),
|
||||
request.path()
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(file_path)
|
||||
}
|
||||
@@ -231,11 +243,13 @@ impl FileSystemRepository for FileSystem {
|
||||
let new_path = self
|
||||
.rename(request.path(), request.new_name())
|
||||
.await
|
||||
.context(format!(
|
||||
"Failed to rename {} to {}",
|
||||
request.path(),
|
||||
request.new_name()
|
||||
))?;
|
||||
.map_err(|e| {
|
||||
anyhow!(
|
||||
"Failed to rename {} to {}: {e:?}",
|
||||
request.path(),
|
||||
request.new_name()
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(new_path)
|
||||
}
|
||||
|
||||
@@ -11,114 +11,114 @@ impl MetricsDebugLogger {
|
||||
|
||||
impl WarrenMetrics for MetricsDebugLogger {
|
||||
async fn record_warren_list_success(&self) {
|
||||
log::debug!("[Metrics] Warren list succeeded");
|
||||
tracing::debug!("[Metrics] Warren list succeeded");
|
||||
}
|
||||
|
||||
async fn record_warren_list_failure(&self) {
|
||||
log::debug!("[Metrics] Warren list failed");
|
||||
tracing::debug!("[Metrics] Warren list failed");
|
||||
}
|
||||
|
||||
async fn record_warren_fetch_success(&self) {
|
||||
log::debug!("[Metrics] Warren fetch succeeded");
|
||||
tracing::debug!("[Metrics] Warren fetch succeeded");
|
||||
}
|
||||
|
||||
async fn record_warren_fetch_failure(&self) {
|
||||
log::debug!("[Metrics] Warren fetch failed");
|
||||
tracing::debug!("[Metrics] Warren fetch failed");
|
||||
}
|
||||
|
||||
async fn record_list_warren_files_success(&self) {
|
||||
log::debug!("[Metrics] Warren list files succeeded");
|
||||
tracing::debug!("[Metrics] Warren list files succeeded");
|
||||
}
|
||||
|
||||
async fn record_list_warren_files_failure(&self) {
|
||||
log::debug!("[Metrics] Warren list files failed");
|
||||
tracing::debug!("[Metrics] Warren list files failed");
|
||||
}
|
||||
|
||||
async fn record_warren_directory_creation_success(&self) {
|
||||
log::debug!("[Metrics] Warren directory creation succeeded");
|
||||
tracing::debug!("[Metrics] Warren directory creation succeeded");
|
||||
}
|
||||
|
||||
async fn record_warren_directory_creation_failure(&self) {
|
||||
log::debug!("[Metrics] Warren directory creation failed");
|
||||
tracing::debug!("[Metrics] Warren directory creation failed");
|
||||
}
|
||||
|
||||
async fn record_warren_directory_deletion_success(&self) {
|
||||
log::debug!("[Metrics] Warren directory deletion succeeded");
|
||||
tracing::debug!("[Metrics] Warren directory deletion succeeded");
|
||||
}
|
||||
|
||||
async fn record_warren_directory_deletion_failure(&self) {
|
||||
log::debug!("[Metrics] Warren directory deletion failed");
|
||||
tracing::debug!("[Metrics] Warren directory deletion failed");
|
||||
}
|
||||
|
||||
async fn record_warren_file_upload_success(&self) {
|
||||
log::debug!("[Metrics] Warren file upload succeeded");
|
||||
tracing::debug!("[Metrics] Warren file upload succeeded");
|
||||
}
|
||||
async fn record_warren_file_upload_failure(&self) {
|
||||
log::debug!("[Metrics] Warren file upload failed");
|
||||
tracing::debug!("[Metrics] Warren file upload failed");
|
||||
}
|
||||
|
||||
async fn record_warren_files_upload_success(&self) {
|
||||
log::debug!("[Metrics] Warren files upload succeded");
|
||||
tracing::debug!("[Metrics] Warren files upload succeded");
|
||||
}
|
||||
async fn record_warren_files_upload_failure(&self) {
|
||||
log::debug!("[Metrics] Warren files upload failed at least partially");
|
||||
tracing::debug!("[Metrics] Warren files upload failed at least partially");
|
||||
}
|
||||
|
||||
async fn record_warren_file_deletion_success(&self) {
|
||||
log::debug!("[Metrics] Warren file deletion succeeded");
|
||||
tracing::debug!("[Metrics] Warren file deletion succeeded");
|
||||
}
|
||||
async fn record_warren_file_deletion_failure(&self) {
|
||||
log::debug!("[Metrics] Warren file deletion failed");
|
||||
tracing::debug!("[Metrics] Warren file deletion failed");
|
||||
}
|
||||
|
||||
async fn record_warren_entry_rename_success(&self) {
|
||||
log::debug!("[Metrics] Warren entry rename succeeded");
|
||||
tracing::debug!("[Metrics] Warren entry rename succeeded");
|
||||
}
|
||||
async fn record_warren_entry_rename_failure(&self) {
|
||||
log::debug!("[Metrics] Warren entry rename failed");
|
||||
tracing::debug!("[Metrics] Warren entry rename failed");
|
||||
}
|
||||
}
|
||||
|
||||
impl FileSystemMetrics for MetricsDebugLogger {
|
||||
async fn record_list_files_success(&self) {
|
||||
log::debug!("[Metrics] File list succeeded");
|
||||
tracing::debug!("[Metrics] File list succeeded");
|
||||
}
|
||||
async fn record_list_files_failure(&self) {
|
||||
log::debug!("[Metrics] File list failed");
|
||||
tracing::debug!("[Metrics] File list failed");
|
||||
}
|
||||
|
||||
async fn record_directory_creation_success(&self) {
|
||||
log::debug!("[Metrics] Directory creation succeeded");
|
||||
tracing::debug!("[Metrics] Directory creation succeeded");
|
||||
}
|
||||
async fn record_directory_creation_failure(&self) {
|
||||
log::debug!("[Metrics] Directory creation failed");
|
||||
tracing::debug!("[Metrics] Directory creation failed");
|
||||
}
|
||||
|
||||
async fn record_directory_deletion_success(&self) {
|
||||
log::debug!("[Metrics] Directory deletion succeeded");
|
||||
tracing::debug!("[Metrics] Directory deletion succeeded");
|
||||
}
|
||||
async fn record_directory_deletion_failure(&self) {
|
||||
log::debug!("[Metrics] Directory deletion failed");
|
||||
tracing::debug!("[Metrics] Directory deletion failed");
|
||||
}
|
||||
|
||||
async fn record_file_creation_success(&self) {
|
||||
log::debug!("[Metrics] File creation succeeded");
|
||||
tracing::debug!("[Metrics] File creation succeeded");
|
||||
}
|
||||
async fn record_file_creation_failure(&self) {
|
||||
log::debug!("[Metrics] File creation failed");
|
||||
tracing::debug!("[Metrics] File creation failed");
|
||||
}
|
||||
|
||||
async fn record_file_deletion_success(&self) {
|
||||
log::debug!("[Metrics] File deletion succeeded");
|
||||
tracing::debug!("[Metrics] File deletion succeeded");
|
||||
}
|
||||
async fn record_file_deletion_failure(&self) {
|
||||
log::debug!("[Metrics] File deletion failed");
|
||||
tracing::debug!("[Metrics] File deletion failed");
|
||||
}
|
||||
|
||||
async fn record_entry_rename_success(&self) -> () {
|
||||
log::debug!("[Metrics] Entry rename succeeded");
|
||||
tracing::debug!("[Metrics] Entry rename succeeded");
|
||||
}
|
||||
async fn record_entry_rename_failure(&self) -> () {
|
||||
log::debug!("[Metrics] Entry rename failed");
|
||||
tracing::debug!("[Metrics] Entry rename failed");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,15 +17,15 @@ impl NotifierDebugLogger {
|
||||
|
||||
impl WarrenNotifier for NotifierDebugLogger {
|
||||
async fn warrens_listed(&self, warrens: &Vec<Warren>) {
|
||||
log::debug!("[Notifier] Listed {} warren(s)", warrens.len());
|
||||
tracing::debug!("[Notifier] Listed {} warren(s)", warrens.len());
|
||||
}
|
||||
|
||||
async fn warren_fetched(&self, warren: &Warren) {
|
||||
log::debug!("[Notifier] Fetched warren {}", warren.name());
|
||||
tracing::debug!("[Notifier] Fetched warren {}", warren.name());
|
||||
}
|
||||
|
||||
async fn warren_files_listed(&self, warren: &Warren, files: &Vec<File>) {
|
||||
log::debug!(
|
||||
tracing::debug!(
|
||||
"[Notifier] Listed {} file(s) in warren {}",
|
||||
files.len(),
|
||||
warren.name()
|
||||
@@ -33,7 +33,7 @@ impl WarrenNotifier for NotifierDebugLogger {
|
||||
}
|
||||
|
||||
async fn warren_directory_created(&self, warren: &Warren, path: &FilePath) {
|
||||
log::debug!(
|
||||
tracing::debug!(
|
||||
"[Notifier] Created directory {} in warren {}",
|
||||
path,
|
||||
warren.name()
|
||||
@@ -41,7 +41,7 @@ impl WarrenNotifier for NotifierDebugLogger {
|
||||
}
|
||||
|
||||
async fn warren_directory_deleted(&self, warren: &Warren, path: &FilePath) {
|
||||
log::debug!(
|
||||
tracing::debug!(
|
||||
"[Notifier] Deleted directory {} in warren {}",
|
||||
path,
|
||||
warren.name()
|
||||
@@ -49,7 +49,7 @@ impl WarrenNotifier for NotifierDebugLogger {
|
||||
}
|
||||
|
||||
async fn warren_file_uploaded(&self, warren: &Warren, path: &FilePath) {
|
||||
log::debug!(
|
||||
tracing::debug!(
|
||||
"[Notifier] Uploaded file {} to warren {}",
|
||||
path,
|
||||
warren.name()
|
||||
@@ -57,7 +57,7 @@ impl WarrenNotifier for NotifierDebugLogger {
|
||||
}
|
||||
|
||||
async fn warren_files_uploaded(&self, warren: &Warren, paths: &[FilePath]) {
|
||||
log::debug!(
|
||||
tracing::debug!(
|
||||
"[Notifier] Uploaded {} file(s) to warren {}",
|
||||
paths.len(),
|
||||
warren.name()
|
||||
@@ -65,7 +65,7 @@ impl WarrenNotifier for NotifierDebugLogger {
|
||||
}
|
||||
|
||||
async fn warren_file_deleted(&self, warren: &Warren, path: &FilePath) {
|
||||
log::debug!(
|
||||
tracing::debug!(
|
||||
"[Notifier] Deleted file {} from warren {}",
|
||||
path,
|
||||
warren.name(),
|
||||
@@ -78,7 +78,7 @@ impl WarrenNotifier for NotifierDebugLogger {
|
||||
old_path: &crate::domain::warren::models::file::AbsoluteFilePath,
|
||||
new_path: &FilePath,
|
||||
) {
|
||||
log::debug!(
|
||||
tracing::debug!(
|
||||
"[Notifier] Renamed file {} to {} in warren {}",
|
||||
old_path,
|
||||
new_path,
|
||||
@@ -89,26 +89,26 @@ impl WarrenNotifier for NotifierDebugLogger {
|
||||
|
||||
impl FileSystemNotifier for NotifierDebugLogger {
|
||||
async fn files_listed(&self, files: &Vec<File>) {
|
||||
log::debug!("[Notifier] Listed {} file(s)", files.len());
|
||||
tracing::debug!("[Notifier] Listed {} file(s)", files.len());
|
||||
}
|
||||
|
||||
async fn directory_created(&self, path: &FilePath) {
|
||||
log::debug!("[Notifier] Created directory {}", path);
|
||||
tracing::debug!("[Notifier] Created directory {}", path);
|
||||
}
|
||||
|
||||
async fn directory_deleted(&self, path: &FilePath) {
|
||||
log::debug!("[Notifier] Deleted directory {}", path);
|
||||
tracing::debug!("[Notifier] Deleted directory {}", path);
|
||||
}
|
||||
|
||||
async fn file_created(&self, path: &FilePath) {
|
||||
log::debug!("[Notifier] Created file {}", path);
|
||||
tracing::debug!("[Notifier] Created file {}", path);
|
||||
}
|
||||
|
||||
async fn file_deleted(&self, path: &FilePath) {
|
||||
log::debug!("[Notifier] Deleted file {}", path);
|
||||
tracing::debug!("[Notifier] Deleted file {}", path);
|
||||
}
|
||||
|
||||
async fn entry_renamed(&self, old_path: &FilePath, new_path: &FilePath) {
|
||||
log::debug!("[Notifier] Renamed file {} to {}", old_path, new_path);
|
||||
tracing::debug!("[Notifier] Renamed file {} to {}", old_path, new_path);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ impl WarrenRepository for Postgres {
|
||||
let warrens = self
|
||||
.list_warrens(&mut connection)
|
||||
.await
|
||||
.map_err(|err| anyhow!(err).context("Failed to fetch warren with id"))?;
|
||||
.map_err(|err| anyhow!(err).context("Failed to list warrens"))?;
|
||||
|
||||
Ok(warrens)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user