Skip to main content

ma_core/
pinning.rs

1//! Safe pin lifecycle management.
2//!
3//! [`pin_update_add_rm`] pins a new CID, then attempts to unpin the old
4//! one, reporting any unpin failure as metadata rather than a hard error.
5
6use std::future::Future;
7
8use anyhow::Result;
9
10#[derive(Debug, Default, Clone)]
11pub struct PinUpdateOutcome {
12    pub previous_unpin_error: Option<String>,
13}
14
15pub async fn pin_update_add_rm<FAdd, FRm, FutAdd, FutRm>(
16    old_cid: Option<&str>,
17    new_cid: &str,
18    pin_name: &str,
19    add_named: FAdd,
20    remove_pin: FRm,
21) -> Result<PinUpdateOutcome>
22where
23    FAdd: Fn(String, String) -> FutAdd,
24    FRm: Fn(String) -> FutRm,
25    FutAdd: Future<Output = Result<()>>,
26    FutRm: Future<Output = Result<()>>,
27{
28    let Some(previous) = old_cid else {
29        add_named(new_cid.to_string(), pin_name.to_string()).await?;
30        return Ok(PinUpdateOutcome::default());
31    };
32
33    if previous == new_cid {
34        return Ok(PinUpdateOutcome::default());
35    }
36
37    add_named(new_cid.to_string(), pin_name.to_string()).await?;
38
39    let previous_unpin_error = remove_pin(previous.to_string())
40        .await
41        .err()
42        .map(|err| err.to_string());
43
44    Ok(PinUpdateOutcome {
45        previous_unpin_error,
46    })
47}