feat: document storage size
This commit is contained in:
parent
d7cd101c44
commit
9093363b4f
|
|
@ -1,8 +1,8 @@
|
||||||
use database_entity::dto::AFWorkspace;
|
use database_entity::dto::AFWorkspace;
|
||||||
|
|
||||||
use super::entities::{
|
use super::entities::{
|
||||||
JsonResponse, UserUsageLimit, WorkspaceBlobUsage, WorkspaceMember, WorkspaceUsage,
|
JsonResponse, UserUsageLimit, WorkspaceBlobUsage, WorkspaceDocUsage, WorkspaceMember,
|
||||||
WorkspaceUsageLimit,
|
WorkspaceUsageLimit, WorkspaceUsageLimits,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub async fn get_user_workspace_count(auth_header: &str, appflowy_cloud_base_url: &str) -> u32 {
|
pub async fn get_user_workspace_count(auth_header: &str, appflowy_cloud_base_url: &str) -> u32 {
|
||||||
|
|
@ -68,24 +68,35 @@ pub async fn get_user_workspace_usages(
|
||||||
auth_header: &str,
|
auth_header: &str,
|
||||||
appflowy_cloud_base_url: &str,
|
appflowy_cloud_base_url: &str,
|
||||||
appflowy_cloud_gateway_base_url: &str,
|
appflowy_cloud_gateway_base_url: &str,
|
||||||
) -> Vec<WorkspaceUsage> {
|
) -> Vec<WorkspaceUsageLimits> {
|
||||||
let user_workspaces = get_user_workspaces(auth_header, appflowy_cloud_base_url).await;
|
let user_workspaces = get_user_workspaces(auth_header, appflowy_cloud_base_url).await;
|
||||||
|
|
||||||
let mut workspace_usages: Vec<WorkspaceUsage> = Vec::with_capacity(user_workspaces.len());
|
let mut workspace_usages: Vec<WorkspaceUsageLimits> = Vec::with_capacity(user_workspaces.len());
|
||||||
for user_workspace in user_workspaces {
|
for user_workspace in user_workspaces {
|
||||||
let workspace_id = user_workspace.workspace_id.to_string();
|
let workspace_id = user_workspace.workspace_id.to_string();
|
||||||
let members =
|
let members =
|
||||||
get_user_workspace_members(&workspace_id, auth_header, appflowy_cloud_base_url).await;
|
get_user_workspace_members(&workspace_id, auth_header, appflowy_cloud_base_url).await;
|
||||||
let workspace_limits =
|
let workspace_limits =
|
||||||
get_user_workspace_limits(&workspace_id, auth_header, appflowy_cloud_gateway_base_url).await;
|
get_user_workspace_limits(&workspace_id, auth_header, appflowy_cloud_gateway_base_url).await;
|
||||||
let blob_usage =
|
let total_blob_size =
|
||||||
get_user_workspace_blob_usage(&workspace_id, auth_header, appflowy_cloud_base_url)
|
get_user_workspace_blob_usage(&workspace_id, auth_header, appflowy_cloud_base_url)
|
||||||
.await
|
.await
|
||||||
.map(|u| u.consumed_capacity)
|
.map(|u| human_bytes::human_bytes(u.consumed_capacity as f64))
|
||||||
.unwrap_or_else(|err| {
|
.unwrap_or_else(|err| {
|
||||||
tracing::error!("Error getting user workspace blob usage: {:?}", err);
|
tracing::error!("Error getting user workspace blob usage: {:?}", err);
|
||||||
0
|
"0".to_owned()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let total_doc_size = {
|
||||||
|
get_user_workspace_doc_usage(&workspace_id, auth_header, appflowy_cloud_base_url)
|
||||||
|
.await
|
||||||
|
.map(|u| human_bytes::human_bytes(u.total_document_size as f64))
|
||||||
|
.unwrap_or_else(|err| {
|
||||||
|
tracing::error!("Error getting user workspace doc usage: {:?}", err);
|
||||||
|
"0".to_owned()
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
let (member_limit, total_blob_limit) = match workspace_limits {
|
let (member_limit, total_blob_limit) = match workspace_limits {
|
||||||
Some(limit) => (
|
Some(limit) => (
|
||||||
limit.member_count.to_string(),
|
limit.member_count.to_string(),
|
||||||
|
|
@ -94,12 +105,12 @@ pub async fn get_user_workspace_usages(
|
||||||
None => ("N/A".to_string(), "N/A".to_string()),
|
None => ("N/A".to_string(), "N/A".to_string()),
|
||||||
};
|
};
|
||||||
|
|
||||||
workspace_usages.push(WorkspaceUsage {
|
workspace_usages.push(WorkspaceUsageLimits {
|
||||||
name: user_workspace.workspace_name,
|
name: user_workspace.workspace_name,
|
||||||
member_count: members.len(),
|
member_count: members.len(),
|
||||||
member_limit,
|
member_limit,
|
||||||
total_doc_size: "WIP".to_string(),
|
total_doc_size,
|
||||||
total_blob_size: human_bytes::human_bytes(blob_usage as f64),
|
total_blob_size,
|
||||||
total_blob_limit,
|
total_blob_limit,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -189,3 +200,23 @@ async fn get_user_workspace_blob_usage(
|
||||||
let res = resp.json::<JsonResponse<WorkspaceBlobUsage>>().await?;
|
let res = resp.json::<JsonResponse<WorkspaceBlobUsage>>().await?;
|
||||||
Ok(res.data)
|
Ok(res.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn get_user_workspace_doc_usage(
|
||||||
|
workspace_id: &str,
|
||||||
|
auth_header: &str,
|
||||||
|
appflowy_cloud_base_url: &str,
|
||||||
|
) -> Result<WorkspaceDocUsage, reqwest::Error> {
|
||||||
|
let http_client = reqwest::Client::new();
|
||||||
|
let url = format!(
|
||||||
|
"{}/api/workspace/{}/usage",
|
||||||
|
appflowy_cloud_base_url, workspace_id
|
||||||
|
);
|
||||||
|
let resp = http_client
|
||||||
|
.get(url)
|
||||||
|
.header("Authorization", format!("Bearer {}", auth_header))
|
||||||
|
.send()
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let res = resp.json::<JsonResponse<WorkspaceDocUsage>>().await?;
|
||||||
|
Ok(res.data)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ pub struct UserUsageLimit {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct WorkspaceUsage {
|
pub struct WorkspaceUsageLimits {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub member_count: usize,
|
pub member_count: usize,
|
||||||
pub member_limit: String,
|
pub member_limit: String,
|
||||||
|
|
@ -39,3 +39,8 @@ pub struct WorkspaceUsageLimit {
|
||||||
pub struct WorkspaceBlobUsage {
|
pub struct WorkspaceBlobUsage {
|
||||||
pub consumed_capacity: u64,
|
pub consumed_capacity: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct WorkspaceDocUsage {
|
||||||
|
pub total_document_size: i64,
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use askama::Template;
|
use askama::Template;
|
||||||
use gotrue_entity::{dto::User, sso::SSOProvider};
|
use gotrue_entity::{dto::User, sso::SSOProvider};
|
||||||
|
|
||||||
use crate::ext::entities::WorkspaceUsage;
|
use crate::ext::entities::WorkspaceUsageLimits;
|
||||||
|
|
||||||
#[derive(Template)]
|
#[derive(Template)]
|
||||||
#[template(path = "components/user_usage.html")]
|
#[template(path = "components/user_usage.html")]
|
||||||
|
|
@ -14,7 +14,7 @@ pub struct UserUsage {
|
||||||
#[derive(Template)]
|
#[derive(Template)]
|
||||||
#[template(path = "components/workspace_usage.html")]
|
#[template(path = "components/workspace_usage.html")]
|
||||||
pub struct WorkspaceUsageList {
|
pub struct WorkspaceUsageList {
|
||||||
pub workspace_usages: Vec<WorkspaceUsage>,
|
pub workspace_usages: Vec<WorkspaceUsageLimits>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Template)]
|
#[derive(Template)]
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use crate::error::WebAppError;
|
||||||
use crate::ext::api::{
|
use crate::ext::api::{
|
||||||
get_user_workspace_count, get_user_workspace_limit, get_user_workspace_usages,
|
get_user_workspace_count, get_user_workspace_limit, get_user_workspace_usages,
|
||||||
};
|
};
|
||||||
use crate::ext::entities::WorkspaceUsage;
|
use crate::ext::entities::WorkspaceUsageLimits;
|
||||||
use crate::session::UserSession;
|
use crate::session::UserSession;
|
||||||
use askama::Template;
|
use askama::Template;
|
||||||
use axum::extract::{Path, State};
|
use axum::extract::{Path, State};
|
||||||
|
|
|
||||||
|
|
@ -258,6 +258,11 @@ pub enum QueryCollabResult {
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct BatchQueryCollabResult(pub HashMap<String, QueryCollabResult>);
|
pub struct BatchQueryCollabResult(pub HashMap<String, QueryCollabResult>);
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct WorkspaceUsage {
|
||||||
|
pub total_document_size: i64,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Validate, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Validate, Serialize, Deserialize)]
|
||||||
pub struct InsertCollabMemberParams {
|
pub struct InsertCollabMemberParams {
|
||||||
pub uid: i64,
|
pub uid: i64,
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,9 @@ pub fn workspace_scope() -> Scope {
|
||||||
.app_data(PayloadConfig::new(10 * 1024 * 1024))
|
.app_data(PayloadConfig::new(10 * 1024 * 1024))
|
||||||
.route(web::post().to(create_collab_list_handler)),
|
.route(web::post().to(create_collab_list_handler)),
|
||||||
)
|
)
|
||||||
|
.service(
|
||||||
|
web::resource("/{workspace_id}/usage").route(web::get().to(get_workspace_usage_handler)),
|
||||||
|
)
|
||||||
.service(
|
.service(
|
||||||
web::resource("/{workspace_id}/{object_id}/snapshot")
|
web::resource("/{workspace_id}/{object_id}/snapshot")
|
||||||
.route(web::get().to(get_collab_snapshot_handler))
|
.route(web::get().to(get_collab_snapshot_handler))
|
||||||
|
|
@ -841,6 +844,17 @@ async fn post_realtime_message_stream_handler(
|
||||||
Err(AppError::Internal(anyhow!("Failed to send message to websocket server")).into())
|
Err(AppError::Internal(anyhow!("Failed to send message to websocket server")).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn get_workspace_usage_handler(
|
||||||
|
user_uuid: UserUuid,
|
||||||
|
workspace_id: web::Path<Uuid>,
|
||||||
|
state: Data<AppState>,
|
||||||
|
) -> Result<Json<AppResponse<WorkspaceUsage>>> {
|
||||||
|
let res = WorkspaceUsage {
|
||||||
|
total_document_size: 19978, // TODO
|
||||||
|
};
|
||||||
|
Ok(Json(AppResponse::Ok().with_data(res)))
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
async fn parser_realtime_msg(
|
async fn parser_realtime_msg(
|
||||||
payload: Bytes,
|
payload: Bytes,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue