hashiverse_lib/client/post_bundle/
stub_post_bundle_manager.rs1use crate::client::post_bundle::post_bundle_manager::PostBundleManager;
12use crate::protocol::peer::Peer;
13use crate::protocol::posting::encoded_post_bundle::{EncodedPostBundleHeaderV1, EncodedPostBundleV1};
14use crate::tools::buckets::{BucketLocation, BucketType};
15use crate::tools::config;
16use crate::tools::time::{DurationMillis, TimeMillis};
17use crate::tools::types::{Id, Signature};
18use log::{trace, warn};
19use parking_lot::RwLock;
20use std::collections::{HashMap, HashSet};
21use bytes::Bytes;
22
23pub struct StubPostBundleManager {
24 post_bundles: RwLock<HashMap<Id, EncodedPostBundleV1>>,
25}
26
27impl StubPostBundleManager {
28 pub fn add_random_stub_post_bundle(&self, id: &Id, granularity: DurationMillis, epoch_offset_str: &str, num_posts: u8) -> anyhow::Result<EncodedPostBundleV1> {
29 let bucket_location = BucketLocation::new(BucketType::User, *id, granularity, TimeMillis::from_epoch_offset_str(epoch_offset_str)?)?;
30
31 let mut post_bundle = EncodedPostBundleV1::stub();
32 post_bundle.header.location_id = bucket_location.location_id;
33 post_bundle.header.num_posts = num_posts;
34 for _ in 0..num_posts {
35 post_bundle.header.encoded_post_ids.push(Id::random());
36 post_bundle.header.encoded_post_lengths.push(0);
37 }
38 let result = self.post_bundles.write().insert(bucket_location.location_id, post_bundle.clone());
39 if result.is_some() {
40 warn!("Replaced stub post bundle for location_id: {}", bucket_location.location_id);
41 }
42
43 Ok(post_bundle)
44 }
45
46 pub fn add_stub_post_bundle(&self, id: &Id, granularity: DurationMillis, epoch_offset_str: &str, post_bundle: &EncodedPostBundleV1) -> anyhow::Result<()> {
47 let bucket_location = BucketLocation::new(BucketType::User, *id, granularity, TimeMillis::from_epoch_offset_str(epoch_offset_str)?)?;
48
49 let result = self.post_bundles.write().insert(bucket_location.location_id, post_bundle.clone());
50 if result.is_some() {
51 warn!("Replaced stub post bundle for location_id: {}", bucket_location.location_id);
52 }
53
54 Ok(())
55 }
56}
57
58impl Default for StubPostBundleManager {
59 fn default() -> Self {
60 Self { post_bundles: RwLock::new(HashMap::new()) }
61 }
62}
63
64#[cfg_attr(target_arch = "wasm32", async_trait::async_trait(?Send))]
65#[cfg_attr(not(target_arch = "wasm32"), async_trait::async_trait)]
66impl PostBundleManager for StubPostBundleManager {
67 async fn get_post_bundle(&self, bucket_location: &BucketLocation, time_millis: TimeMillis) -> anyhow::Result<EncodedPostBundleV1> {
68 let post_bundles = self.post_bundles.read();
69 let post_bundle = post_bundles.get(&bucket_location.location_id);
70 let post_bundle = match post_bundle {
71 Some(post_bundle) => {
72 let mut post_bundle = post_bundle.clone();
73 post_bundle.header.time_millis = time_millis;
74 post_bundle.header.overflowed = post_bundle.header.num_posts > config::ENCODED_POST_BUNDLE_V1_OVERFLOWED_NUM_POSTS;
75 post_bundle.header.sealed = post_bundle.header.overflowed || time_millis > bucket_location.bucket_time_millis + bucket_location.duration + config::ENCODED_POST_BUNDLE_V1_ELAPSED_THRESHOLD_MILLIS;
76 trace!("Returning stub postbundle: {}", post_bundle);
77 post_bundle
78 }
79 None => {
80 let sealed = time_millis > bucket_location.bucket_time_millis + bucket_location.duration + config::ENCODED_POST_BUNDLE_V1_ELAPSED_THRESHOLD_MILLIS;
81 let mut post_bundle = EncodedPostBundleV1::stub();
82 post_bundle.header.time_millis = time_millis;
83 post_bundle.header.location_id = bucket_location.location_id;
84 post_bundle.header.sealed = sealed;
85 trace!("Returning phantom postbundle: {}", post_bundle);
86 post_bundle
87 }
88 };
89
90 Ok(post_bundle)
91 }
92}
93
94impl EncodedPostBundleV1 {
95 pub fn stub() -> Self {
96 let header = EncodedPostBundleHeaderV1 {
97 time_millis: TimeMillis::zero(),
98 location_id: Id::zero(),
99 overflowed: false,
100 sealed: false,
101 num_posts: 0,
102 encoded_post_ids: vec![],
103 encoded_post_lengths: vec![],
104 encoded_post_healed: HashSet::new(),
105 peer: Peer::zero(),
106 signature: Signature::zero(),
107 };
108
109 EncodedPostBundleV1 { header, encoded_posts_bytes: Bytes::new() }
110 }
111}