Skip to main content

ma_core/kubo/
pinning.rs

1//! Safe pin lifecycle management.
2//!
3//! [`pin_add_then_rm`] pins a new CID, then attempts to remove the old
4//! pin, reporting any removal failure as metadata rather than a hard error.
5
6use std::future::Future;
7
8use anyhow::Result;
9
10#[cfg(feature = "config")]
11use crate::config::RemotePinConfig;
12
13#[derive(Debug, Default, Clone)]
14pub struct PinReplaceOutcome {
15    pub previous_remove_error: Option<String>,
16}
17
18pub async fn pin_add_then_rm<FAdd, FRm, FutAdd, FutRm>(
19    old_cid: Option<&str>,
20    new_cid: &str,
21    pin_name: &str,
22    add_named: FAdd,
23    remove_pin: FRm,
24) -> Result<PinReplaceOutcome>
25where
26    FAdd: Fn(String, String) -> FutAdd,
27    FRm: Fn(String) -> FutRm,
28    FutAdd: Future<Output = Result<()>>,
29    FutRm: Future<Output = Result<()>>,
30{
31    let Some(previous) = old_cid else {
32        add_named(new_cid.to_string(), pin_name.to_string()).await?;
33        return Ok(PinReplaceOutcome::default());
34    };
35
36    if previous == new_cid {
37        return Ok(PinReplaceOutcome::default());
38    }
39
40    add_named(new_cid.to_string(), pin_name.to_string()).await?;
41
42    let previous_remove_error = remove_pin(previous.to_string())
43        .await
44        .err()
45        .map(|err| err.to_string());
46
47    Ok(PinReplaceOutcome {
48        previous_remove_error,
49    })
50}
51
52#[cfg(feature = "config")]
53pub async fn remote_pin_replace(
54    kubo_url: &str,
55    remote: &RemotePinConfig,
56    old_cid: Option<&str>,
57    new_cid: &str,
58) -> Result<PinReplaceOutcome> {
59    let add_url = kubo_url.to_string();
60    let add_service = remote.service.clone();
61    let rm_url = kubo_url.to_string();
62    let rm_service = remote.service.clone();
63    pin_add_then_rm(
64        old_cid,
65        new_cid,
66        &remote.name,
67        move |cid, name| {
68            let add_url = add_url.clone();
69            let add_service = add_service.clone();
70            async move {
71                crate::kubo::kubo::remote_pin_add_named(&add_url, &add_service, &cid, &name).await
72            }
73        },
74        move |cid| {
75            let rm_url = rm_url.clone();
76            let rm_service = rm_service.clone();
77            async move { crate::kubo::kubo::remote_pin_rm(&rm_url, &rm_service, &cid).await }
78        },
79    )
80    .await
81}