Skip to content

Commit 5a2d239

Browse files
authored
feat(fortuna): allow filtering callback failing logs (#2932)
1 parent a97f93e commit 5a2d239

File tree

3 files changed

+112
-17
lines changed

3 files changed

+112
-17
lines changed

apps/fortuna/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "fortuna"
3-
version = "9.0.0"
3+
version = "9.1.0"
44
edition = "2021"
55

66
[lib]

apps/fortuna/src/api.rs

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,21 +39,12 @@ mod revelation;
3939
pub type ChainId = String;
4040
pub type NetworkId = u64;
4141

42-
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, utoipa::ToSchema, sqlx::Type)]
42+
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, utoipa::ToSchema)]
4343
pub enum StateTag {
4444
Pending,
45-
Completed,
4645
Failed,
47-
}
48-
49-
impl std::fmt::Display for StateTag {
50-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
51-
match self {
52-
StateTag::Pending => write!(f, "Pending"),
53-
StateTag::Completed => write!(f, "Completed"),
54-
StateTag::Failed => write!(f, "Failed"),
55-
}
56-
}
46+
Completed,
47+
CallbackErrored,
5748
}
5849

5950
#[derive(Clone, Debug, Hash, PartialEq, Eq, EncodeLabelSet)]

apps/fortuna/src/history.rs

Lines changed: 108 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -533,9 +533,15 @@ impl<'a> RequestQueryBuilder<'a> {
533533
sql.push_str(&format!(" AND network_id = ${param_count}"));
534534
}
535535

536-
if self.state.is_some() {
536+
if let Some(state) = &self.state {
537537
param_count += 1;
538538
sql.push_str(&format!(" AND state = ${param_count}"));
539+
540+
if *state == StateTag::Completed {
541+
sql.push_str(" AND NOT callback_failed");
542+
} else if *state == StateTag::CallbackErrored {
543+
sql.push_str(" AND callback_failed");
544+
}
539545
}
540546

541547
sql.push_str(" ORDER BY created_at DESC");
@@ -570,7 +576,11 @@ impl<'a> RequestQueryBuilder<'a> {
570576
}
571577

572578
if let Some(state) = &self.state {
573-
query = query.bind(state.to_string());
579+
query = query.bind(match state {
580+
StateTag::Pending => "Pending",
581+
StateTag::Failed => "Failed",
582+
StateTag::Completed | StateTag::CallbackErrored => "Completed",
583+
})
574584
}
575585

576586
query = query.bind(self.limit).bind(self.offset);
@@ -612,9 +622,15 @@ impl<'a> RequestQueryBuilder<'a> {
612622
sql.push_str(&format!(" AND network_id = ${param_count}"));
613623
}
614624

615-
if self.state.is_some() {
625+
if let Some(state) = &self.state {
616626
param_count += 1;
617627
sql.push_str(&format!(" AND state = ${param_count}"));
628+
629+
if *state == StateTag::Completed {
630+
sql.push_str(" AND NOT callback_failed");
631+
} else if *state == StateTag::CallbackErrored {
632+
sql.push_str(" AND callback_failed");
633+
}
618634
}
619635

620636
// Now bind all parameters in order
@@ -642,7 +658,11 @@ impl<'a> RequestQueryBuilder<'a> {
642658
}
643659

644660
if let Some(state) = &self.state {
645-
query = query.bind(state.to_string());
661+
query = query.bind(match state {
662+
StateTag::Pending => "Pending",
663+
StateTag::Failed => "Failed",
664+
StateTag::Completed | StateTag::CallbackErrored => "Completed",
665+
})
646666
}
647667

648668
query.fetch_one(self.pool).await.map_err(|err| err.into())
@@ -1088,6 +1108,90 @@ mod test {
10881108
}
10891109
}
10901110

1111+
#[tokio::test]
1112+
async fn test_history_state_filter() {
1113+
let history = History::new_in_memory().await.unwrap();
1114+
let reveal_tx_hash = TxHash::random();
1115+
1116+
let pending_status = get_random_request_status();
1117+
History::update_request_status(&history.pool, pending_status.clone()).await;
1118+
1119+
let mut failed_status = get_random_request_status();
1120+
History::update_request_status(&history.pool, failed_status.clone()).await;
1121+
failed_status.state = RequestEntryState::Failed {
1122+
reason: "Failed".to_string(),
1123+
provider_random_number: None,
1124+
};
1125+
History::update_request_status(&history.pool, failed_status.clone()).await;
1126+
1127+
let mut completed_status = get_random_request_status();
1128+
History::update_request_status(&history.pool, completed_status.clone()).await;
1129+
completed_status.state = RequestEntryState::Completed {
1130+
reveal_block_number: 1,
1131+
reveal_tx_hash,
1132+
provider_random_number: [40; 32],
1133+
gas_used: U256::from(567890),
1134+
combined_random_number: RequestStatus::generate_combined_random_number(
1135+
&completed_status.user_random_number,
1136+
&[40; 32],
1137+
),
1138+
callback_failed: false,
1139+
callback_return_value: Default::default(),
1140+
callback_gas_used: 100_000,
1141+
};
1142+
History::update_request_status(&history.pool, completed_status.clone()).await;
1143+
1144+
let reveal_tx_hash = TxHash::random();
1145+
let mut callback_errored_status = get_random_request_status();
1146+
History::update_request_status(&history.pool, callback_errored_status.clone()).await;
1147+
callback_errored_status.state = RequestEntryState::Completed {
1148+
reveal_block_number: 1,
1149+
reveal_tx_hash,
1150+
provider_random_number: [40; 32],
1151+
gas_used: U256::from(567890),
1152+
combined_random_number: RequestStatus::generate_combined_random_number(
1153+
&callback_errored_status.user_random_number,
1154+
&[40; 32],
1155+
),
1156+
callback_failed: true,
1157+
callback_return_value: Default::default(),
1158+
callback_gas_used: 100_000,
1159+
};
1160+
History::update_request_status(&history.pool, callback_errored_status.clone()).await;
1161+
1162+
let logs = history
1163+
.query()
1164+
.state(StateTag::Pending)
1165+
.execute()
1166+
.await
1167+
.unwrap();
1168+
assert_eq!(logs, vec![pending_status.clone()]);
1169+
1170+
let logs = history
1171+
.query()
1172+
.state(StateTag::Failed)
1173+
.execute()
1174+
.await
1175+
.unwrap();
1176+
assert_eq!(logs, vec![failed_status.clone()]);
1177+
1178+
let logs = history
1179+
.query()
1180+
.state(StateTag::Completed)
1181+
.execute()
1182+
.await
1183+
.unwrap();
1184+
assert_eq!(logs, vec![completed_status.clone()]);
1185+
1186+
let logs = history
1187+
.query()
1188+
.state(StateTag::CallbackErrored)
1189+
.execute()
1190+
.await
1191+
.unwrap();
1192+
assert_eq!(logs, vec![callback_errored_status.clone()]);
1193+
}
1194+
10911195
#[tokio::test(flavor = "multi_thread")]
10921196
async fn test_writer_thread() {
10931197
let history = History::new_in_memory().await.unwrap();

0 commit comments

Comments
 (0)