mutant_lib/mutant/
update_logic.rs

1use super::MutAnt;
2use crate::error::Error;
3use crate::events::{invoke_callback, PutCallback, PutEvent};
4use log::{debug, error, info, trace, warn};
5
6/// Updates an existing item with new data.
7///
8/// If the key does not exist, it returns a `KeyNotFound` error.
9pub(super) async fn update_item(
10    es: &MutAnt,
11    key: &str,
12    data_bytes: &[u8],
13    mut callback: Option<PutCallback>,
14) -> Result<(), Error> {
15    let data_size = data_bytes.len();
16    trace!(
17        "MutAnt [{}]: Starting update_item for key '{}' ({} bytes) using PadManager",
18        es.master_index_addr, // Assuming this is still relevant for logging
19        key,
20        data_size
21    );
22
23    {
24        let mis_guard = es.master_index_storage.lock().await;
25        if !mis_guard.index.contains_key(key) {
26            debug!("UpdateItem[{}]: Key does not exist.", key);
27            return Err(Error::KeyNotFound(key.to_string()));
28        }
29    }
30
31    let mut needs_confirmation = false;
32    let mut estimated_new_pads_needed = 0;
33
34    match es.pad_manager.estimate_reservation(data_size).await {
35        Ok(Some(pads)) => {
36            if pads > 0 {
37                needs_confirmation = true;
38                estimated_new_pads_needed = pads;
39                debug!(
40                    "UpdateItem[{}]: Estimate indicates {} new pads needed. Confirmation required.",
41                    key, pads
42                );
43                invoke_callback(
44                    &mut callback,
45                    PutEvent::ReservingScratchpads {
46                        needed: pads as u64,
47                    },
48                )
49                .await?;
50            } else {
51                warn!(
52                    "UpdateItem[{}]: estimate_reservation returned Some(0), which is unexpected. Proceeding.",
53                    key
54                );
55            }
56        }
57        Ok(None) => {
58            debug!(
59                "UpdateItem[{}]: Estimate indicates enough free/existing pads available. No confirmation needed.",
60                key
61            );
62        }
63        Err(e) => {
64            error!(
65                "UpdateItem[{}]: Failed to estimate reservation needs: {}",
66                key, e
67            );
68            return Err(e);
69        }
70    }
71
72    if needs_confirmation {
73        let (total_space_bytes, free_space_bytes, current_scratchpads, _scratchpad_size) = {
74            let mis_guard = es.master_index_storage.lock().await;
75            let total_pads = mis_guard
76                .index
77                .values()
78                .map(|v| v.pads.len())
79                .sum::<usize>()
80                + mis_guard.free_pads.len();
81            let pad_size = mis_guard.scratchpad_size;
82            let total_space = total_pads * pad_size;
83            let free_space = mis_guard.free_pads.len() * pad_size;
84            (total_space, free_space, total_pads, pad_size)
85        };
86
87        debug!(
88            "UpdateItem[{}]: Invoking ConfirmReservation callback...",
89            key
90        );
91        invoke_callback(
92            &mut callback,
93            PutEvent::ConfirmReservation {
94                needed: estimated_new_pads_needed as u64,
95                data_size: data_size as u64,
96                total_space: total_space_bytes as u64,
97                free_space: free_space_bytes as u64,
98                current_scratchpads,
99                estimated_cost: None,
100            },
101        )
102        .await?;
103        info!(
104            "UpdateItem[{}]: Reservation confirmation received from user.",
105            key
106        );
107    } else {
108        info!(
109            "UpdateItem[{}]: Reservation confirmation not required.",
110            key
111        );
112    }
113
114    debug!(
115        "UpdateItem[{}]: Calling pad_manager.allocate_and_write...",
116        key
117    );
118
119    es.pad_manager
120        .allocate_and_write(key, data_bytes, callback)
121        .await?;
122
123    info!(
124        "UpdateItem[{}]: PadManager allocate_and_write completed successfully for update.",
125        key
126    );
127
128    debug!("UpdateItem[{}]: Saving final master index state...", key);
129    es.save_master_index().await?;
130
131    info!("UpdateItem[{}]: Update operation fully completed.", key);
132    Ok(())
133}