node/ledger/read/
ledger_read_state.rs1use openmina_core::requests::{PendingRequests, RequestId, RequestIdType};
2use serde::{Deserialize, Serialize};
3
4use super::{LedgerReadRequest, LedgerReadResponse};
5
6const MAX_TOTAL_COST: usize = 256;
7
8pub struct LedgerReadIdType;
9impl RequestIdType for LedgerReadIdType {
10 fn request_id_type() -> &'static str {
11 "LedgerReadId"
12 }
13}
14
15pub type LedgerReadId = RequestId<LedgerReadIdType>;
16
17#[derive(Serialize, Deserialize, Debug, Default, Clone)]
18pub struct LedgerReadState {
19 pending: PendingRequests<LedgerReadIdType, LedgerReadRequestState>,
20 total_cost: usize,
22}
23
24#[derive(Serialize, Deserialize, Debug, Clone)]
25pub enum LedgerReadRequestState {
26 Pending {
27 time: redux::Timestamp,
28 request: LedgerReadRequest,
29 },
30 Success {
31 time: redux::Timestamp,
32 request: LedgerReadRequest,
33 response: LedgerReadResponse,
34 },
35}
36
37impl LedgerReadState {
38 pub fn contains(&self, id: LedgerReadId) -> bool {
39 self.pending.contains(id)
40 }
41
42 pub fn get(&self, id: LedgerReadId) -> Option<&LedgerReadRequestState> {
43 self.pending.get(id)
44 }
45
46 pub fn get_mut(&mut self, id: LedgerReadId) -> Option<&mut LedgerReadRequestState> {
47 self.pending.get_mut(id)
48 }
49
50 pub fn is_total_cost_under_limit(&self) -> bool {
51 self.total_cost < MAX_TOTAL_COST
52 }
53
54 pub fn next_req_id(&self) -> LedgerReadId {
55 self.pending.next_req_id()
56 }
57
58 pub fn add(&mut self, time: redux::Timestamp, request: LedgerReadRequest) -> LedgerReadId {
59 self.total_cost = self.total_cost.saturating_add(request.cost());
60 self.pending
61 .add(LedgerReadRequestState::Pending { time, request })
62 }
63
64 pub fn remove(&mut self, id: LedgerReadId) -> Option<LedgerReadRequestState> {
65 let req = self.pending.remove(id)?;
66 self.total_cost = self.total_cost.saturating_sub(req.request().cost());
67 Some(req)
68 }
69
70 pub fn add_response(
71 &mut self,
72 id: LedgerReadId,
73 time: redux::Timestamp,
74 response: LedgerReadResponse,
75 ) {
76 self.pending.update(id, move |req| match req {
77 LedgerReadRequestState::Pending { request, .. } => LedgerReadRequestState::Success {
78 time,
79 request,
80 response,
81 },
82 LedgerReadRequestState::Success { .. } => {
83 unreachable!("must be prevented by enabling condition")
84 }
85 });
86 }
87
88 pub fn has_same_request(&self, req: &LedgerReadRequest) -> bool {
89 self.pending
90 .iter()
91 .any(|(_, pending)| pending.request() == req)
92 }
93
94 pub fn pending_requests(
95 &self,
96 ) -> impl Iterator<Item = (LedgerReadId, &LedgerReadRequest, redux::Timestamp)> {
97 self.pending.iter().filter_map(|(id, s)| match s {
98 LedgerReadRequestState::Pending { time, request } => Some((id, request, *time)),
99 _ => None,
100 })
101 }
102}
103
104impl LedgerReadRequestState {
105 pub fn request(&self) -> &LedgerReadRequest {
106 match self {
107 Self::Pending { request, .. } | Self::Success { request, .. } => request,
108 }
109 }
110}