Skip to content

Commit

Permalink
Use hextree::Cell for BoostedHex and HexCoverage
Browse files Browse the repository at this point in the history
Got some advice from Jay to only use a `h3o::CellIndex` when you need to
convert to/from a LatLng. So we went with `hextree::Cell` for the type.

`hextree::Cell` is a loose wrapper around a u64. Parsing the value as
early as possible tightens the gaurantee that we can make valid types
that need use `Cell`s.

It is also an attempt to remove discrepancies where some types carry a
`i64` hex straight from a database, and other types carry a `u64` that
were converted out of a database, even though they're goal is the same.

(see previous commit where `#[sqlx(try_from = "i64")]` was enabled by
the update to hextree).
  • Loading branch information
michaeldjeffrey committed Apr 23, 2024
1 parent 277c0d3 commit e3e5057
Show file tree
Hide file tree
Showing 8 changed files with 122 additions and 91 deletions.
14 changes: 6 additions & 8 deletions boost_manager/src/activator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,11 @@ use file_store::{
};
use futures::{future::LocalBoxFuture, stream, StreamExt, TryFutureExt, TryStreamExt};
use helium_proto::{
services::poc_mobile::{
mobile_reward_share::Reward as MobileReward, BoostedHex as BoostedHexProto,
MobileRewardShare,
},
services::poc_mobile::{mobile_reward_share::Reward as MobileReward, MobileRewardShare},
Message,
};
use mobile_config::{
boosted_hex_info::BoostedHexes,
boosted_hex_info::{BoostedHex, BoostedHexes},
client::{hex_boosting_client::HexBoostingInfoResolver, ClientError},
};
use poc_metrics::record_duration;
Expand Down Expand Up @@ -118,7 +115,8 @@ where
let share = MobileRewardShare::decode(msg)?;
if let Some(MobileReward::RadioReward(r)) = share.reward {
for hex in r.boosted_hexes.into_iter() {
process_boosted_hex(txn, manifest_time, &boosted_hexes, &hex).await?
process_boosted_hex(txn, manifest_time, &boosted_hexes, &hex.try_into()?)
.await?
}
}
}
Expand All @@ -130,14 +128,14 @@ pub async fn process_boosted_hex(
txn: &mut Transaction<'_, Postgres>,
manifest_time: DateTime<Utc>,
boosted_hexes: &BoostedHexes,
hex: &BoostedHexProto,
hex: &BoostedHex,
) -> Result<()> {
match boosted_hexes.hexes.get(&hex.location) {
Some(info) => {
if info.start_ts.is_none() {
db::insert_activated_hex(
txn,
hex.location,
hex.location.into_raw(),
&info.boosted_hex_pubkey.to_string(),
&info.boost_config_pubkey.to_string(),
manifest_time,
Expand Down
33 changes: 16 additions & 17 deletions boost_manager/tests/activator_tests.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
mod common;
use boost_manager::{activator, db, OnChainStatus};
use chrono::{DateTime, Duration as ChronoDuration, Duration, Timelike, Utc};
use helium_proto::services::poc_mobile::BoostedHex as BoostedHexProto;
use mobile_config::boosted_hex_info::{BoostedHexInfo, BoostedHexes};
use mobile_config::boosted_hex_info::{BoostedHex, BoostedHexInfo, BoostedHexes};
use solana_sdk::pubkey::Pubkey;
use sqlx::PgPool;
use std::{collections::HashMap, num::NonZeroU32, str::FromStr};
Expand Down Expand Up @@ -44,7 +43,7 @@ impl TestContext {

let boosts = vec![
BoostedHexInfo {
location: 0x8a1fb466d2dffff_u64,
location: 0x8a1fb466d2dffff_u64.try_into().expect("valid h3 cell"),
start_ts: Some(start_ts_1),
end_ts: Some(end_ts_1),
period_length: boost_period_length,
Expand All @@ -54,7 +53,7 @@ impl TestContext {
version: 0,
},
BoostedHexInfo {
location: 0x8a1fb49642dffff_u64,
location: 0x8a1fb49642dffff_u64.try_into().expect("valid h3 cell"),
start_ts: Some(start_ts_2),
end_ts: Some(end_ts_2),
period_length: boost_period_length,
Expand All @@ -65,7 +64,7 @@ impl TestContext {
},
BoostedHexInfo {
// hotspot 3's location
location: 0x8c2681a306607ff_u64,
location: 0x8c2681a306607ff_u64.try_into().expect("valid h3 cell"),
start_ts: None,
end_ts: None,
period_length: boost_period_length,
Expand Down Expand Up @@ -101,9 +100,9 @@ async fn test_activated_hex_insert(pool: PgPool) -> anyhow::Result<()> {
&mut txn,
now,
&boosted_hexes,
&BoostedHexProto {
location: 0x8c2681a306607ff_u64,
multiplier: 10,
&BoostedHex {
location: 0x8c2681a306607ff_u64.try_into().expect("valid h3 cell"),
multiplier: NonZeroU32::new(10).unwrap(),
},
)
.await?;
Expand Down Expand Up @@ -138,9 +137,9 @@ async fn test_activated_hex_no_insert(pool: PgPool) -> anyhow::Result<()> {
&mut txn,
now,
&boosted_hexes,
&BoostedHexProto {
location: 0x8a1fb49642dffff_u64,
multiplier: 10,
&BoostedHex {
location: 0x8a1fb49642dffff_u64.try_into().expect("valid h3 cell"),
multiplier: NonZeroU32::new(10).unwrap(),
},
)
.await?;
Expand Down Expand Up @@ -172,9 +171,9 @@ async fn test_activated_dup_hex_insert(pool: PgPool) -> anyhow::Result<()> {
&mut txn,
now,
&boosted_hexes,
&BoostedHexProto {
location: 0x8c2681a306607ff_u64,
multiplier: 10,
&BoostedHex {
location: 0x8c2681a306607ff_u64.try_into().expect("valid h3 cell"),
multiplier: NonZeroU32::new(10).unwrap(),
},
)
.await?;
Expand All @@ -183,9 +182,9 @@ async fn test_activated_dup_hex_insert(pool: PgPool) -> anyhow::Result<()> {
&mut txn,
now - ChronoDuration::days(1),
&boosted_hexes,
&BoostedHexProto {
location: 0x8c2681a306607ff_u64,
multiplier: 5,
&BoostedHex {
location: 0x8c2681a306607ff_u64.try_into().expect("valid h3 cell"),
multiplier: NonZeroU32::new(5).unwrap(),
},
)
.await?;
Expand Down
4 changes: 2 additions & 2 deletions boost_manager/tests/watcher_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ async fn test_boosted_hex_updates_to_filestore(pool: PgPool) -> anyhow::Result<(

let boosted_hexes = vec![
BoostedHexInfo {
location: 0x8a1fb466d2dffff_u64,
location: 0x8a1fb466d2dffff_u64.try_into().expect("valid h3 cell"),
start_ts: Some(start_ts_1),
end_ts: Some(end_ts_1),
period_length: boost_period_length,
Expand All @@ -75,7 +75,7 @@ async fn test_boosted_hex_updates_to_filestore(pool: PgPool) -> anyhow::Result<(
version: 0,
},
BoostedHexInfo {
location: 0x8a1fb49642dffff_u64,
location: 0x8a1fb49642dffff_u64.try_into().expect("valid h3 cell"),
start_ts: Some(start_ts_2),
end_ts: Some(end_ts_2),
period_length: boost_period_length,
Expand Down
43 changes: 33 additions & 10 deletions mobile_config/src/boosted_hex_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ use crate::client::{hex_boosting_client::HexBoostingInfoResolver, ClientError};
use chrono::{DateTime, Duration, Utc};
use file_store::traits::TimestampDecode;
use futures::stream::{BoxStream, StreamExt};
use helium_proto::services::poc_mobile::BoostedHex as BoostedHexProto;
use helium_proto::BoostedHexInfoV1 as BoostedHexInfoProto;
use hextree::Cell;
use solana_sdk::pubkey::Pubkey;
use std::{collections::HashMap, convert::TryFrom, num::NonZeroU32};

Expand All @@ -14,7 +16,7 @@ lazy_static::lazy_static! {

#[derive(Clone, Debug)]
pub struct BoostedHexInfo {
pub location: u64,
pub location: Cell,
pub start_ts: Option<DateTime<Utc>>,
pub end_ts: Option<DateTime<Utc>>,
pub period_length: Duration,
Expand All @@ -39,7 +41,7 @@ impl TryFrom<BoostedHexInfoProto> for BoostedHexInfo {
let boosted_hex_pubkey: Pubkey = Pubkey::try_from(v.boosted_hex_pubkey.as_slice())?;
let boost_config_pubkey: Pubkey = Pubkey::try_from(v.boost_config_pubkey.as_slice())?;
Ok(Self {
location: v.location,
location: v.location.try_into()?,
start_ts,
end_ts,
period_length,
Expand All @@ -63,7 +65,7 @@ impl TryFrom<BoostedHexInfo> for BoostedHexInfoProto {
.map(|v| v.get())
.collect::<Vec<_>>();
Ok(Self {
location: v.location,
location: v.location.into_raw(),
start_ts,
end_ts,
period_length: v.period_length.num_seconds() as u32,
Expand Down Expand Up @@ -102,15 +104,30 @@ impl BoostedHexInfo {

#[derive(Debug, Clone, Default)]
pub struct BoostedHexes {
pub hexes: HashMap<u64, BoostedHexInfo>,
pub hexes: HashMap<Cell, BoostedHexInfo>,
}

#[derive(PartialEq, Debug, Clone)]
pub struct BoostedHex {
pub location: u64,
pub location: Cell,
pub multiplier: NonZeroU32,
}

impl TryFrom<BoostedHexProto> for BoostedHex {
type Error = anyhow::Error;

fn try_from(value: BoostedHexProto) -> Result<Self, Self::Error> {
let location = Cell::from_raw(value.location)?;
let multiplier = NonZeroU32::new(value.multiplier)
.ok_or_else(|| anyhow::anyhow!("multiplier cannot be 0"))?;

Ok(Self {
location,
multiplier,
})
}
}

impl BoostedHexes {
pub fn new(hexes: Vec<BoostedHexInfo>) -> Self {
let hexes = hexes
Expand All @@ -134,7 +151,7 @@ impl BoostedHexes {
Ok(Self { hexes: map })
}

pub fn is_boosted(&self, location: &u64) -> bool {
pub fn is_boosted(&self, location: &Cell) -> bool {
self.hexes.contains_key(location)
}

Expand All @@ -153,7 +170,7 @@ impl BoostedHexes {
Ok(Self { hexes: map })
}

pub fn get_current_multiplier(&self, location: u64, ts: DateTime<Utc>) -> Option<NonZeroU32> {
pub fn get_current_multiplier(&self, location: Cell, ts: DateTime<Utc>) -> Option<NonZeroU32> {
self.hexes
.get(&location)
.and_then(|info| info.current_multiplier(ts).ok()?)
Expand All @@ -164,6 +181,7 @@ pub(crate) mod db {
use super::{to_end_ts, to_start_ts, BoostedHexInfo};
use chrono::{DateTime, Duration, Utc};
use futures::stream::{Stream, StreamExt};
use hextree::Cell;
use solana_sdk::pubkey::Pubkey;
use sqlx::{PgExecutor, Row};
use std::num::NonZeroU32;
Expand Down Expand Up @@ -236,8 +254,12 @@ pub(crate) mod db {
let boosted_hex_pubkey = Pubkey::from_str(row.get::<&str, &str>("boosted_hex_pubkey"))
.map_err(|e| sqlx::Error::Decode(Box::new(e)))?;
let version = row.get::<i32, &str>("version") as u32;

let location = Cell::try_from(row.get::<i64, &str>("location"))
.map_err(|e| sqlx::Error::Decode(Box::new(e)))?;

Ok(Self {
location: row.get::<i64, &str>("location") as u64,
location,
start_ts,
end_ts,
period_length,
Expand Down Expand Up @@ -270,6 +292,7 @@ fn to_end_ts(
mod tests {
use super::*;
use chrono::NaiveDateTime;
use hextree::Cell;
use std::str::FromStr;

const BOOST_HEX_PUBKEY: &str = "J9JiLTpjaShxL8eMvUs8txVw6TZ36E38SiJ89NxnMbLU";
Expand All @@ -295,7 +318,7 @@ mod tests {
};

let msg = BoostedHexInfo::try_from(proto)?;
assert_eq!(631252734740306943, msg.location);
assert_eq!(Cell::from_raw(631252734740306943)?, msg.location);
assert_eq!(None, msg.start_ts);
assert_eq!(None, msg.end_ts);
assert_eq!(2592000, msg.period_length.num_seconds());
Expand Down Expand Up @@ -336,7 +359,7 @@ mod tests {
};

let msg = BoostedHexInfo::try_from(proto)?;
assert_eq!(631252734740306943, msg.location);
assert_eq!(Cell::from_raw(631252734740306943)?, msg.location);
assert_eq!(parse_dt("2024-03-14 01:00:00"), msg.start_ts.unwrap());
assert_eq!(parse_dt("2024-07-12 01:00:00"), msg.end_ts.unwrap());
assert_eq!(2592000, msg.period_length.num_seconds());
Expand Down
Loading

0 comments on commit e3e5057

Please sign in to comment.