no preview assets anymore
This commit is contained in:
+109
-44
@@ -28,7 +28,7 @@ use papercrate::{
|
||||
user_memberships, users,
|
||||
},
|
||||
storage::{ObjectStorage, S3Storage, TenantStorage},
|
||||
tenants::TenantService,
|
||||
tenants::{apply_tenant_guc, clear_tenant_context, TenantService},
|
||||
utils::{text::normalize_identifier, tracing::init_tracing},
|
||||
workers::tenants::{build_delete_proof_message, sign_delete_proof, DeleteAction},
|
||||
};
|
||||
@@ -86,6 +86,10 @@ enum Command {
|
||||
ListTenants,
|
||||
DeleteAssets {
|
||||
tenant_id: Uuid,
|
||||
#[arg(long = "asset-type")]
|
||||
asset_type: Option<String>,
|
||||
#[arg(long = "all", help = "Confirm deleting every asset for the tenant")]
|
||||
delete_all: bool,
|
||||
},
|
||||
QuickwitCreate {
|
||||
tenant_id: Uuid,
|
||||
@@ -192,8 +196,17 @@ async fn main() -> Result<()> {
|
||||
} => remove_user_from_tenant(&pool, &username, tenant_id)?,
|
||||
Command::ReanalyzeDocuments { tenant_id } => reanalyze_documents(&pool, tenant_id)?,
|
||||
Command::ListTenants => list_tenants(&pool)?,
|
||||
Command::DeleteAssets { tenant_id } => {
|
||||
delete_assets_for_tenant(&config, &pool, tenant_id).await?
|
||||
Command::DeleteAssets {
|
||||
tenant_id,
|
||||
asset_type,
|
||||
delete_all,
|
||||
} => {
|
||||
let asset_type = asset_type.as_deref();
|
||||
if asset_type.is_none() && !delete_all {
|
||||
bail!("refusing to delete all assets without --all confirmation");
|
||||
}
|
||||
|
||||
delete_assets_for_tenant(&config, &pool, tenant_id, asset_type).await?
|
||||
}
|
||||
Command::QuickwitCreate { tenant_id } => {
|
||||
quickwit_index(&config, &pool, tenant_id, Method::POST).await?
|
||||
@@ -486,6 +499,9 @@ fn enqueue_delete_tenant_job_internal(
|
||||
.optional()?
|
||||
.ok_or_else(|| anyhow!("tenant '{}' not found", tenant_id))?;
|
||||
|
||||
apply_tenant_guc(&mut conn, tenant.id)
|
||||
.map_err(|err| anyhow!("failed to set tenant context for {}: {err:?}", tenant.name))?;
|
||||
|
||||
if tenant.name != expected_name {
|
||||
bail!(
|
||||
"tenant name mismatch: expected '{}', database has '{}'",
|
||||
@@ -548,6 +564,14 @@ fn enqueue_delete_tenant_job_internal(
|
||||
"delete-tenant job enqueued for '{}' (remove_tenant={}, final_status={})",
|
||||
tenant.name, remove_tenant, status_label
|
||||
);
|
||||
|
||||
clear_tenant_context(&mut conn).map_err(|err| {
|
||||
anyhow!(
|
||||
"failed to clear tenant context for {}: {err:?}",
|
||||
tenant.name
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -705,6 +729,7 @@ async fn delete_assets_for_tenant(
|
||||
config: &AppConfig,
|
||||
pool: &PgPool,
|
||||
tenant_id: Uuid,
|
||||
asset_type: Option<&str>,
|
||||
) -> Result<()> {
|
||||
let bucket = s3::build_bucket(config)?;
|
||||
let storage: Arc<dyn ObjectStorage> = Arc::new(S3Storage::new(bucket));
|
||||
@@ -716,57 +741,97 @@ async fn delete_assets_for_tenant(
|
||||
.optional()?
|
||||
.ok_or_else(|| anyhow!("tenant '{}' not found", tenant_id))?;
|
||||
|
||||
let tenant_storage = TenantStorage::new(Arc::clone(&storage), &tenant)
|
||||
.with_context(|| format!("missing storage root for tenant {}", tenant.name))?;
|
||||
apply_tenant_guc(&mut conn, tenant.id)
|
||||
.map_err(|err| anyhow!("failed to set tenant context for {}: {err:?}", tenant.name))?;
|
||||
|
||||
let assets: Vec<DocumentAsset> = document_assets::table
|
||||
.filter(document_assets::tenant_id.eq(tenant.id))
|
||||
.load(&mut conn)
|
||||
.with_context(|| format!("failed to load assets for tenant {}", tenant.name))?;
|
||||
let result = async {
|
||||
let tenant_storage = TenantStorage::new(Arc::clone(&storage), &tenant)
|
||||
.with_context(|| format!("missing storage root for tenant {}", tenant.name))?;
|
||||
|
||||
if assets.is_empty() {
|
||||
println!("Tenant {}: no assets", tenant.name);
|
||||
return Ok(());
|
||||
}
|
||||
let mut asset_query = document_assets::table
|
||||
.filter(document_assets::tenant_id.eq(tenant.id))
|
||||
.into_boxed();
|
||||
|
||||
println!(
|
||||
"Tenant {} ({}): deleting {} assets…",
|
||||
tenant.name,
|
||||
tenant.id,
|
||||
assets.len()
|
||||
);
|
||||
|
||||
let asset_ids: Vec<Uuid> = assets.iter().map(|asset| asset.id).collect();
|
||||
|
||||
let objects: Vec<DocumentAssetObject> = document_asset_objects::table
|
||||
.filter(document_asset_objects::tenant_id.eq(tenant.id))
|
||||
.filter(document_asset_objects::asset_id.eq_any(&asset_ids))
|
||||
.load(&mut conn)
|
||||
.with_context(|| format!("failed to load asset objects for tenant {}", tenant.name))?;
|
||||
|
||||
for object in &objects {
|
||||
if let Err(err) = tenant_storage.delete_object(&object.s3_key).await {
|
||||
eprintln!(
|
||||
"Failed to delete object {} (tenant {}): {err}",
|
||||
object.s3_key, tenant.name
|
||||
);
|
||||
if let Some(asset_type) = asset_type {
|
||||
asset_query = asset_query.filter(document_assets::asset_type.eq(asset_type));
|
||||
}
|
||||
}
|
||||
|
||||
diesel::delete(
|
||||
document_asset_objects::table
|
||||
let assets: Vec<DocumentAsset> = asset_query
|
||||
.load(&mut conn)
|
||||
.with_context(|| format!("failed to load assets for tenant {}", tenant.name))?;
|
||||
|
||||
if assets.is_empty() {
|
||||
match asset_type {
|
||||
Some(asset_type) => {
|
||||
println!("Tenant {}: no assets of type '{}'", tenant.name, asset_type)
|
||||
}
|
||||
None => println!("Tenant {}: no assets", tenant.name),
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
match asset_type {
|
||||
Some(asset_type) => println!(
|
||||
"Tenant {} ({}): deleting {} '{}' assets…",
|
||||
tenant.name,
|
||||
tenant.id,
|
||||
assets.len(),
|
||||
asset_type
|
||||
),
|
||||
None => println!(
|
||||
"Tenant {} ({}): deleting {} assets…",
|
||||
tenant.name,
|
||||
tenant.id,
|
||||
assets.len()
|
||||
),
|
||||
}
|
||||
|
||||
let asset_ids: Vec<Uuid> = assets.iter().map(|asset| asset.id).collect();
|
||||
|
||||
let objects: Vec<DocumentAssetObject> = document_asset_objects::table
|
||||
.filter(document_asset_objects::tenant_id.eq(tenant.id))
|
||||
.filter(document_asset_objects::asset_id.eq_any(&asset_ids)),
|
||||
)
|
||||
.execute(&mut conn)
|
||||
.with_context(|| format!("failed to remove asset objects for tenant {}", tenant.name))?;
|
||||
.filter(document_asset_objects::asset_id.eq_any(&asset_ids))
|
||||
.load(&mut conn)
|
||||
.with_context(|| format!("failed to load asset objects for tenant {}", tenant.name))?;
|
||||
|
||||
diesel::delete(document_assets::table.filter(document_assets::tenant_id.eq(tenant.id)))
|
||||
for object in &objects {
|
||||
if let Err(err) = tenant_storage.delete_object(&object.s3_key).await {
|
||||
eprintln!(
|
||||
"Failed to delete object {} (tenant {}): {err}",
|
||||
object.s3_key, tenant.name
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
diesel::delete(
|
||||
document_asset_objects::table
|
||||
.filter(document_asset_objects::tenant_id.eq(tenant.id))
|
||||
.filter(document_asset_objects::asset_id.eq_any(&asset_ids)),
|
||||
)
|
||||
.execute(&mut conn)
|
||||
.with_context(|| format!("failed to remove asset objects for tenant {}", tenant.name))?;
|
||||
|
||||
diesel::delete(
|
||||
document_assets::table
|
||||
.filter(document_assets::tenant_id.eq(tenant.id))
|
||||
.filter(document_assets::id.eq_any(&asset_ids)),
|
||||
)
|
||||
.execute(&mut conn)
|
||||
.with_context(|| format!("failed to remove asset records for tenant {}", tenant.name))?;
|
||||
|
||||
println!("Tenant {}: asset records deleted.", tenant.name);
|
||||
Ok(())
|
||||
println!("Tenant {}: asset records deleted.", tenant.name);
|
||||
Ok(())
|
||||
}
|
||||
.await;
|
||||
|
||||
clear_tenant_context(&mut conn).map_err(|err| {
|
||||
anyhow!(
|
||||
"failed to clear tenant context for {}: {err:?}",
|
||||
tenant.name
|
||||
)
|
||||
})?;
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
async fn quickwit_index(
|
||||
|
||||
Reference in New Issue
Block a user