refactor(companies): remove local-disk fallback from submit_with_documents — B2 only
All checks were successful
build-and-release / build (social-media-managers) (push) Successful in 4s
build-and-release / build (ugc-content-creators) (push) Successful in 4s
build-and-release / build (users) (push) Successful in 4s
build-and-release / build (companies) (push) Successful in 6m14s
build-and-release / build (developers) (push) Successful in 7s
build-and-release / build (fitness-trainers) (push) Successful in 3s
build-and-release / build (catering-services) (push) Successful in 13s
build-and-release / build (customers) (push) Successful in 12s
build-and-release / build (cron) (push) Successful in 15s
build-and-release / build (employees) (push) Successful in 14s
build-and-release / build (makeup-artists) (push) Successful in 4s
build-and-release / build (gateway) (push) Successful in 3s
build-and-release / build (graphic-designers) (push) Successful in 4s
build-and-release / build (jobs) (push) Successful in 4s
build-and-release / build (job-seekers) (push) Successful in 4s
build-and-release / build (leads) (push) Successful in 4s
build-and-release / build (payments) (push) Successful in 4s
build-and-release / build (tutors) (push) Successful in 4s
build-and-release / build (video-editors) (push) Successful in 4s
build-and-release / build (photographers) (push) Successful in 4s

This commit is contained in:
Ashwin Kumar Sivakumar 2026-07-11 02:13:56 +05:30
parent a019f86477
commit e53098728a

View file

@ -748,9 +748,6 @@ async fn view_contact(
} }
} }
/// Local-disk fallback directory for company documents when B2 is down.
const COMPANY_DOCS_LOCAL_DIR: &str = "/var/lib/nxtgauge-uploads/company_documents";
/// POST /api/companies/profile/submit-with-documents /// POST /api/companies/profile/submit-with-documents
/// ///
/// Accepts multipart/form-data with: /// Accepts multipart/form-data with:
@ -759,9 +756,9 @@ const COMPANY_DOCS_LOCAL_DIR: &str = "/var/lib/nxtgauge-uploads/company_document
/// ///
/// In one request this handler: /// In one request this handler:
/// 1. Saves the profile into `company_profiles` (DRAFT upsert, same SQL as users service). /// 1. Saves the profile into `company_profiles` (DRAFT upsert, same SQL as users service).
/// 2. Uploads each document, trying B2 first then falling back to local disk /// 2. Uploads each document to B2 (`storage_backend` is always `"b2"`). On B2 failure
/// (`/var/lib/nxtgauge-uploads/company_documents/{uuid}.{ext}`) and inserting /// the file is recorded in `failure_details` and `documents_failed` is incremented,
/// a `company_documents` row regardless of source. /// then processing continues with the next file. No local-disk fallback.
/// 3. Creates a `verifications` row (case_type = "PROFILE_VERIFICATION", priority = "MEDIUM"). /// 3. Creates a `verifications` row (case_type = "PROFILE_VERIFICATION", priority = "MEDIUM").
/// 4. Updates `company_profiles.status` to 'PENDING'. /// 4. Updates `company_profiles.status` to 'PENDING'.
/// 5. Returns `{ verification_id, status, documents_uploaded, documents_failed, storage_backend }`. /// 5. Returns `{ verification_id, status, documents_uploaded, documents_failed, storage_backend }`.
@ -779,7 +776,7 @@ async fn submit_with_documents(
let mut documents_meta: Vec<serde_json::Value> = Vec::new(); let mut documents_meta: Vec<serde_json::Value> = Vec::new();
let mut documents_uploaded: usize = 0; let mut documents_uploaded: usize = 0;
let mut documents_failed: usize = 0; let mut documents_failed: usize = 0;
let mut storage_backend: &str = "b2"; let storage_backend: &str = "b2";
let mut failure_details: Vec<serde_json::Value> = Vec::new(); let mut failure_details: Vec<serde_json::Value> = Vec::new();
while let Ok(Some(field)) = multipart.next_field().await { while let Ok(Some(field)) = multipart.next_field().await {
@ -796,7 +793,7 @@ async fn submit_with_documents(
} }
} }
} else if name == "documents" || name == "files" || name == "file" { } else if name == "documents" || name == "files" || name == "file" {
// ---- 2a. Upload to storage (B2 with local-disk fallback). ---- // ---- 2a. Upload to B2. ----
let original_filename = field.file_name().unwrap_or("").to_string(); let original_filename = field.file_name().unwrap_or("").to_string();
let content_type = field let content_type = field
.content_type() .content_type()
@ -846,60 +843,30 @@ async fn submit_with_documents(
let data_len = data.len() as i64; let data_len = data.len() as i64;
// Try B2 first. // Upload to B2. On failure, record the file in failure_details and continue.
let (url, source) = match state let url: String = match state
.storage .storage
.upload("company_documents", &ext, data.clone(), &content_type) .upload("company_documents", &ext, data.clone(), &content_type)
.await .await
{ {
Ok(u) => (u, "b2"), Ok(u) => u,
Err(b2_err) => { Err(b2_err) => {
tracing::warn!( tracing::warn!(
"B2 upload failed for company user {} ({}) — falling back to local disk: {}", "B2 upload failed for company user {} ({}): {}",
auth.user_id, auth.user_id,
original_filename, original_filename,
b2_err b2_err
); );
// Fallback: write to local disk. documents_failed += 1;
let dir = std::path::Path::new(COMPANY_DOCS_LOCAL_DIR); failure_details.push(serde_json::json!({
if let Err(mkdir_err) = tokio::fs::create_dir_all(dir).await { "filename": original_filename,
tracing::error!( "error": format!("B2 upload failed: {}", b2_err),
"Local-disk fallback unavailable: failed to create {}: {}", }));
COMPANY_DOCS_LOCAL_DIR, continue;
mkdir_err
);
documents_failed += 1;
failure_details.push(serde_json::json!({
"filename": original_filename,
"error": format!("B2 failed and local fallback mkdir failed: {}", mkdir_err),
"b2_error": b2_err.to_string(),
}));
continue;
}
let file_id = Uuid::new_v4();
let file_path = dir.join(format!("{}.{}", file_id, ext));
if let Err(write_err) = tokio::fs::write(&file_path, &data).await {
tracing::error!(
"Local-disk fallback write failed for {}: {}",
file_path.display(),
write_err
);
documents_failed += 1;
failure_details.push(serde_json::json!({
"filename": original_filename,
"error": format!("B2 failed and local fallback write failed: {}", write_err),
"b2_error": b2_err.to_string(),
}));
continue;
}
(format!("file://{}", file_path.display()), "local")
} }
}; };
// Track storage backend for the response: once any file goes local, the request is "local". // storage_backend is always "b2" (set at top of function).
if source == "local" {
storage_backend = "local";
}
// Derive a stable document_type from the original filename (stem) so the admin UI can group. // Derive a stable document_type from the original filename (stem) so the admin UI can group.
let document_type = if !original_filename.is_empty() { let document_type = if !original_filename.is_empty() {