Skip to content

Commit 485a578

Browse files
Create domain errors for subscriber proto types
You may notice an `h3o::error::InvalidCellIndex` error in usage counts. One of the benefits for flipping error logic over to the implementer is now file-store has no more reason to know about h3o.
1 parent 3272bca commit 485a578

File tree

7 files changed

+184
-126
lines changed

7 files changed

+184
-126
lines changed

file_store_oracles/src/network_common/entropy_report.rs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
use chrono::{DateTime, Utc};
2-
use file_store::{
3-
traits::{MsgDecode, TimestampDecode, TimestampEncode},
4-
Error, Result,
2+
use file_store::traits::{
3+
MsgDecode, TimestampDecode, TimestampDecodeError, TimestampDecodeResult, TimestampEncode,
54
};
65
use helium_proto::EntropyReportV1;
76
use serde::Serialize;
87

98
use crate::traits::MsgTimestamp;
109

10+
#[derive(thiserror::Error, Debug)]
11+
pub enum EntropyReportError {
12+
#[error("invalid timestamp: {0}")]
13+
Timestamp(#[from] TimestampDecodeError),
14+
}
15+
1116
#[derive(Serialize, Clone, Debug)]
1217
pub struct EntropyReport {
1318
pub data: Vec<u8>,
@@ -21,8 +26,8 @@ impl MsgTimestamp<u64> for EntropyReport {
2126
}
2227
}
2328

24-
impl MsgTimestamp<Result<DateTime<Utc>>> for EntropyReportV1 {
25-
fn timestamp(&self) -> Result<DateTime<Utc>> {
29+
impl MsgTimestamp<TimestampDecodeResult> for EntropyReportV1 {
30+
fn timestamp(&self) -> TimestampDecodeResult {
2631
self.timestamp.to_timestamp()
2732
}
2833
}
@@ -32,10 +37,10 @@ impl MsgDecode for EntropyReport {
3237
}
3338

3439
impl TryFrom<EntropyReportV1> for EntropyReport {
35-
type Error = Error;
40+
type Error = EntropyReportError;
3641

37-
fn try_from(v: EntropyReportV1) -> Result<Self> {
38-
let timestamp = v.timestamp.to_timestamp()?;
42+
fn try_from(v: EntropyReportV1) -> Result<Self, Self::Error> {
43+
let timestamp = v.timestamp()?;
3944
Ok(Self {
4045
data: v.data,
4146
version: v.version,

file_store_oracles/src/network_common/reward_manifest.rs

Lines changed: 46 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,30 @@
1-
use chrono::{DateTime, TimeZone, Utc};
2-
use file_store::{traits::MsgDecode, DecodeError, Error};
3-
use helium_proto::{self as proto, IotRewardToken, MobileRewardToken};
1+
use chrono::{DateTime, Utc};
2+
use file_store::traits::{MsgDecode, TimestampDecode, TimestampDecodeError};
3+
use helium_proto as proto;
4+
use helium_proto::{IotRewardToken, MobileRewardToken};
45
use rust_decimal::Decimal;
56
use serde::Serialize;
67

8+
use crate::prost_enum;
9+
10+
#[derive(thiserror::Error, Debug)]
11+
pub enum RewardManifestError {
12+
#[error("invalid timestamp: {0}")]
13+
Timestamp(#[from] TimestampDecodeError),
14+
15+
#[error("missing field: {0}")]
16+
MissingField(&'static str),
17+
18+
#[error("unsupported mobile token type: {0}")]
19+
MobileTokenType(prost::UnknownEnumValue),
20+
21+
#[error("unsupported iot token type: {0}")]
22+
IotTokenType(prost::UnknownEnumValue),
23+
24+
#[error("error parsing decimal: {0}")]
25+
Decimal(#[from] rust_decimal::Error),
26+
}
27+
728
#[derive(Clone, Debug, Serialize)]
829
pub struct RewardManifest {
930
pub written_files: Vec<String>,
@@ -34,82 +55,59 @@ impl MsgDecode for RewardManifest {
3455
}
3556

3657
impl TryFrom<proto::RewardManifest> for RewardManifest {
37-
type Error = Error;
58+
type Error = RewardManifestError;
3859

3960
fn try_from(value: proto::RewardManifest) -> Result<Self, Self::Error> {
4061
Ok(RewardManifest {
4162
written_files: value.written_files,
42-
start_timestamp: Utc
43-
.timestamp_opt(value.start_timestamp as i64, 0)
44-
.single()
45-
.ok_or(Error::Decode(DecodeError::InvalidTimestamp(
46-
value.start_timestamp,
47-
)))?,
48-
end_timestamp: Utc
49-
.timestamp_opt(value.end_timestamp as i64, 0)
50-
.single()
51-
.ok_or(Error::Decode(DecodeError::InvalidTimestamp(
52-
value.end_timestamp,
53-
)))?,
63+
start_timestamp: value.start_timestamp.to_timestamp()?,
64+
end_timestamp: value.end_timestamp.to_timestamp()?,
5465
epoch: value.epoch,
5566
price: value.price,
5667
reward_data: match value.reward_data {
5768
Some(proto::reward_manifest::RewardData::MobileRewardData(reward_data)) => {
58-
let token = MobileRewardToken::try_from(reward_data.token).map_err(|_| {
59-
DecodeError::unsupported_token_type(
60-
"mobile_reward_manifest",
61-
reward_data.token,
62-
)
63-
})?;
6469
Some(RewardData::MobileRewardData {
6570
poc_bones_per_reward_share: reward_data
6671
.poc_bones_per_reward_share
67-
.ok_or(DecodeError::empty_field("poc_bones_per_reward_share"))?
72+
.ok_or(RewardManifestError::MissingField(
73+
"mobile_reward_data.poc_bones_per_reward_share",
74+
))?
6875
.value
69-
.parse()
70-
.map_err(DecodeError::from)?,
76+
.parse()?,
7177
boosted_poc_bones_per_reward_share: reward_data
7278
.boosted_poc_bones_per_reward_share
73-
.ok_or(DecodeError::empty_field(
74-
"boosted_poc_bones_per_reward_share",
79+
.ok_or(RewardManifestError::MissingField(
80+
"mobile_reward_data.boosted_poc_bones_per_reward_share",
7581
))?
7682
.value
77-
.parse()
78-
.map_err(DecodeError::from)?,
79-
token,
83+
.parse()?,
84+
token: prost_enum(reward_data.token, RewardManifestError::MobileTokenType)?,
8085
})
8186
}
8287
Some(proto::reward_manifest::RewardData::IotRewardData(reward_data)) => {
83-
let token = IotRewardToken::try_from(reward_data.token).map_err(|_| {
84-
DecodeError::unsupported_token_type(
85-
"iot_reward_manifest",
86-
reward_data.token,
87-
)
88-
})?;
8988
Some(RewardData::IotRewardData {
9089
poc_bones_per_beacon_reward_share: reward_data
9190
.poc_bones_per_beacon_reward_share
92-
.ok_or(DecodeError::empty_field(
93-
"poc_bones_per_beacon_reward_share",
91+
.ok_or(RewardManifestError::MissingField(
92+
"iot_reward_data.poc_bones_per_beacon_reward_share",
9493
))?
9594
.value
96-
.parse()
97-
.map_err(DecodeError::from)?,
95+
.parse()?,
9896
poc_bones_per_witness_reward_share: reward_data
9997
.poc_bones_per_witness_reward_share
100-
.ok_or(DecodeError::empty_field(
101-
"poc_bones_per_witness_reward_share",
98+
.ok_or(RewardManifestError::MissingField(
99+
"iot_reward_data.poc_bones_per_witness_reward_share",
102100
))?
103101
.value
104-
.parse()
105-
.map_err(DecodeError::from)?,
102+
.parse()?,
106103
dc_bones_per_share: reward_data
107104
.dc_bones_per_share
108-
.ok_or(DecodeError::empty_field("dc_bones_per_share"))?
105+
.ok_or(RewardManifestError::MissingField(
106+
"iot_reward_data.dc_bones_per_share",
107+
))?
109108
.value
110-
.parse()
111-
.map_err(DecodeError::from)?,
112-
token,
109+
.parse()?,
110+
token: prost_enum(reward_data.token, RewardManifestError::IotTokenType)?,
113111
})
114112
}
115113
None => None,

file_store_oracles/src/subscriber/subscriber_verified_mapping_event.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
use chrono::{DateTime, Utc};
2-
use file_store::{
3-
traits::{MsgDecode, TimestampDecode, TimestampEncode},
4-
Error, Result,
2+
use file_store::traits::{
3+
MsgDecode, TimestampDecode, TimestampDecodeError, TimestampDecodeResult, TimestampEncode,
54
};
65
use helium_crypto::PublicKeyBinary;
76
use helium_proto::services::poc_mobile::SubscriberVerifiedMappingEventReqV1;
87
use serde::{Deserialize, Serialize};
98

109
use crate::traits::MsgTimestamp;
1110

11+
#[derive(thiserror::Error, Debug)]
12+
pub enum SubscriberMappingError {
13+
#[error("invalid timestamp: {0}")]
14+
Timestamp(#[from] TimestampDecodeError),
15+
}
16+
1217
#[derive(Clone, Deserialize, Serialize, Debug, PartialEq)]
1318
pub struct SubscriberVerifiedMappingEvent {
1419
pub subscriber_id: Vec<u8>,
@@ -21,8 +26,8 @@ impl MsgDecode for SubscriberVerifiedMappingEvent {
2126
type Msg = SubscriberVerifiedMappingEventReqV1;
2227
}
2328

24-
impl MsgTimestamp<Result<DateTime<Utc>>> for SubscriberVerifiedMappingEventReqV1 {
25-
fn timestamp(&self) -> Result<DateTime<Utc>> {
29+
impl MsgTimestamp<TimestampDecodeResult> for SubscriberVerifiedMappingEventReqV1 {
30+
fn timestamp(&self) -> TimestampDecodeResult {
2631
self.timestamp.to_timestamp()
2732
}
2833
}
@@ -47,8 +52,9 @@ impl From<SubscriberVerifiedMappingEvent> for SubscriberVerifiedMappingEventReqV
4752
}
4853

4954
impl TryFrom<SubscriberVerifiedMappingEventReqV1> for SubscriberVerifiedMappingEvent {
50-
type Error = Error;
51-
fn try_from(v: SubscriberVerifiedMappingEventReqV1) -> Result<Self> {
55+
type Error = SubscriberMappingError;
56+
57+
fn try_from(v: SubscriberVerifiedMappingEventReqV1) -> Result<Self, Self::Error> {
5258
let timestamp = v.timestamp()?;
5359
Ok(Self {
5460
subscriber_id: v.subscriber_id,

file_store_oracles/src/subscriber/subscriber_verified_mapping_event_ingest_report.rs

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,29 @@
11
use chrono::{DateTime, Utc};
2-
use file_store::{
3-
traits::{MsgDecode, TimestampDecode, TimestampEncode},
4-
Error, Result,
2+
use file_store::traits::{
3+
MsgDecode, TimestampDecode, TimestampDecodeError, TimestampDecodeResult, TimestampEncode,
54
};
65
use helium_proto::services::poc_mobile::{
76
SubscriberVerifiedMappingEventIngestReportV1, SubscriberVerifiedMappingEventReqV1,
87
};
98
use serde::{Deserialize, Serialize};
109

1110
use crate::{
12-
subscriber_verified_mapping_event::SubscriberVerifiedMappingEvent, traits::MsgTimestamp,
11+
subscriber_verified_mapping_event::{SubscriberMappingError, SubscriberVerifiedMappingEvent},
12+
traits::MsgTimestamp,
1313
};
1414

15+
#[derive(thiserror::Error, Debug)]
16+
pub enum SubscriberIngestReportError {
17+
#[error("invalid timestamp: {0}")]
18+
Timestamp(#[from] TimestampDecodeError),
19+
20+
#[error("missing field: {0}")]
21+
MissingField(&'static str),
22+
23+
#[error("subscriber location: {0}")]
24+
SubscriberLocation(#[from] SubscriberMappingError),
25+
}
26+
1527
#[derive(Clone, Deserialize, Serialize, Debug, PartialEq)]
1628
pub struct SubscriberVerifiedMappingEventIngestReport {
1729
pub received_timestamp: DateTime<Utc>,
@@ -22,8 +34,8 @@ impl MsgDecode for SubscriberVerifiedMappingEventIngestReport {
2234
type Msg = SubscriberVerifiedMappingEventIngestReportV1;
2335
}
2436

25-
impl MsgTimestamp<Result<DateTime<Utc>>> for SubscriberVerifiedMappingEventIngestReportV1 {
26-
fn timestamp(&self) -> Result<DateTime<Utc>> {
37+
impl MsgTimestamp<TimestampDecodeResult> for SubscriberVerifiedMappingEventIngestReportV1 {
38+
fn timestamp(&self) -> TimestampDecodeResult {
2739
self.received_timestamp.to_timestamp_millis()
2840
}
2941
}
@@ -50,15 +62,16 @@ impl From<SubscriberVerifiedMappingEventIngestReport>
5062
impl TryFrom<SubscriberVerifiedMappingEventIngestReportV1>
5163
for SubscriberVerifiedMappingEventIngestReport
5264
{
53-
type Error = Error;
54-
fn try_from(v: SubscriberVerifiedMappingEventIngestReportV1) -> Result<Self> {
65+
type Error = SubscriberIngestReportError;
66+
67+
fn try_from(v: SubscriberVerifiedMappingEventIngestReportV1) -> Result<Self, Self::Error> {
5568
Ok(Self {
5669
received_timestamp: v.timestamp()?,
5770
report: v
5871
.report
59-
.ok_or_else(|| {
60-
Error::not_found("ingest SubscriberVerifiedMappingEventIngestReport report")
61-
})?
72+
.ok_or(SubscriberIngestReportError::MissingField(
73+
"subscriber_verified_mapping_event_ingest_report.report",
74+
))?
6275
.try_into()?,
6376
})
6477
}

file_store_oracles/src/subscriber/unique_connections.rs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
11
use chrono::{DateTime, Utc};
2+
use file_store::traits::{MsgDecode, TimestampDecode, TimestampDecodeError};
23
use helium_crypto::PublicKeyBinary;
34
use serde::{Deserialize, Serialize};
45

5-
use file_store::{
6-
traits::{MsgDecode, TimestampDecode},
7-
Error,
8-
};
9-
106
pub mod proto {
117
pub use helium_proto::services::poc_mobile::{
128
UniqueConnectionsIngestReportV1, UniqueConnectionsReqV1,
139
VerifiedUniqueConnectionsIngestReportStatus, VerifiedUniqueConnectionsIngestReportV1,
1410
};
1511
}
1612

13+
#[derive(thiserror::Error, Debug)]
14+
pub enum UniqueConnectionsError {
15+
#[error("invalid timestamp: {0}")]
16+
Timestamp(#[from] TimestampDecodeError),
17+
18+
#[error("missing field: {0}")]
19+
MissingField(&'static str),
20+
}
21+
1722
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
1823
pub struct UniqueConnectionsIngestReport {
1924
pub received_timestamp: DateTime<Utc>,
@@ -43,14 +48,16 @@ impl MsgDecode for UniqueConnectionsIngestReport {
4348
}
4449

4550
impl TryFrom<proto::UniqueConnectionsIngestReportV1> for UniqueConnectionsIngestReport {
46-
type Error = Error;
51+
type Error = UniqueConnectionsError;
4752

4853
fn try_from(value: proto::UniqueConnectionsIngestReportV1) -> Result<Self, Self::Error> {
4954
Ok(Self {
5055
received_timestamp: value.received_timestamp.to_timestamp_millis()?,
5156
report: value
5257
.report
53-
.ok_or_else(|| Error::not_found("ingest unique connections"))?
58+
.ok_or(UniqueConnectionsError::MissingField(
59+
"unique_connections_ingest_report.report",
60+
))?
5461
.try_into()?,
5562
})
5663
}
@@ -66,7 +73,7 @@ impl From<UniqueConnectionsIngestReport> for proto::UniqueConnectionsIngestRepor
6673
}
6774

6875
impl TryFrom<proto::UniqueConnectionsReqV1> for UniqueConnectionReq {
69-
type Error = Error;
76+
type Error = UniqueConnectionsError;
7077

7178
fn try_from(value: proto::UniqueConnectionsReqV1) -> Result<Self, Self::Error> {
7279
Ok(Self {

0 commit comments

Comments
 (0)