bmrlab / gendam

A privacy-first generative DAM
6 stars 1 forks source link

增加索引删除接口,assetobject 没有被 file_path 引用以后删除 mediadata 和索引。 #20

Closed web3nomad closed 1 month ago

web3nomad commented 2 months ago

删除 file_path 以后要检查一下 assetobject 是否还有其他引用,如果没有的话,要删除 assetobject,进一步的,删除 filehandlertask

Originally posted by @web3nomad in https://github.com/bmrlab/tauri-dam-test-playground/issues/15#issuecomment-2001957102

zhuojg commented 1 month ago

88e5c382e7da378e410e8d36385f9290265b295a 解决了删除问题:

但部分代码还可以再优化一下,暂时没想到特别好的优化思路,主要是删除的部分,我先贴到这里

// apps/api-server/src/routes/assets/delete.rs

...

    library
        .prisma_client()
        ._transaction()
        .run(|client| async move {
            let mut related_asset_object_ids = HashSet::new();

            let deleted_one = client
                .file_path()
                .delete(file_path::materialized_path_name(
                    materialized_path.clone(),
                    name.clone(),
                ))
                .exec()
                .await
                .map_err(|e| {
                    tracing::error!("failed to delete file_path item: {}", e);
                    e
                })?;
            related_asset_object_ids.insert(deleted_one.asset_object_id);

            let materialized_path_startswith = format!("{}{}/", &materialized_path, &name);
            // TODO 这里分页查一下
            // 会比较慢
            let mut skip = 0;
            loop {
                let data: Vec<_> = client
                    .file_path()
                    .find_many(vec![file_path::materialized_path::starts_with(
                        materialized_path_startswith.clone(),
                    )])
                    .order_by(file_path::OrderByParam::Id(Direction::Asc))
                    .skip(skip)
                    .take(50)
                    .exec()
                    .await?;

                if data.len() == 0 {
                    break;
                }

                data.iter().for_each(|v| {
                    related_asset_object_ids.insert(v.asset_object_id);
                });

                skip += data.len() as i64;
            }

            // TODO 之前已经查过id了,这里也许可以优化一下
            client
                .file_path()
                .delete_many(vec![file_path::materialized_path::starts_with(
                    materialized_path_startswith,
                )])
                .exec()
                .await
                .map_err(|e| {
                    tracing::error!("failed to delete file_path for children: {}", e);
                    e
                })?;

            // TODO 这里循环删,感觉又会有点慢
            // 但是好像没有特别好的写法
            for asset_object_id in related_asset_object_ids {
                if let Some(asset_object_id) = asset_object_id {
                    let count = client
                        .file_path()
                        .count(vec![file_path::asset_object_id::equals(Some(
                            asset_object_id,
                        ))])
                        .exec()
                        .await?;
                    if count == 0 {
                        let deleted_asset_object = client
                            .asset_object()
                            .delete(asset_object::id::equals(asset_object_id))
                            .exec()
                            .await?;
                        deleted_file_hashes
                            .lock()
                            .await
                            .push(deleted_asset_object.hash);
                    }
                }
            }

...