Skip to content

Commit 30a13fc

Browse files
committed
fix(tap-agent): Prevent panic on NULL allocation_ids from RAV query
The `ARRAY_AGG(...) FILTER (WHERE NOT last)` query for RAVs can return NULL. Changed `.expect()` to `if let Some` to handle this valid case where a sender has only finalized RAVs, preventing a panic.
1 parent 523783c commit 30a13fc

File tree

1 file changed

+46
-38
lines changed

1 file changed

+46
-38
lines changed

crates/tap-agent/src/agent/sender_accounts_manager.rs

Lines changed: 46 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,7 @@ impl Actor for SenderAccountsManager {
465465
let mut sender_allocation = select! {
466466
sender_allocation = state.get_pending_sender_allocation_id_v1() => sender_allocation,
467467
_ = tokio::time::sleep(state.config.tap_sender_timeout) => {
468-
tracing::error!("Timeout while getting pending sender allocation ids");
468+
tracing::error!(version = "V1", "Timeout while getting pending sender allocation ids");
469469
return Ok(());
470470
}
471471
};
@@ -483,7 +483,7 @@ impl Actor for SenderAccountsManager {
483483
let mut sender_allocation = select! {
484484
sender_allocation = state.get_pending_sender_allocation_id_v2() => sender_allocation,
485485
_ = tokio::time::sleep(state.config.tap_sender_timeout) => {
486-
tracing::error!("Timeout while getting pending V2 sender allocation ids");
486+
tracing::error!(version = "V2", "Timeout while getting pending sender allocation ids");
487487
return Ok(());
488488
}
489489
};
@@ -653,25 +653,29 @@ impl State {
653653
.expect("should be able to fetch unfinalized RAVs V1 from the database");
654654

655655
for row in nonfinal_ravs_sender_allocations_in_db {
656-
let allocation_ids = row
657-
.allocation_ids
658-
.expect("all RAVs V1 should have an allocation_id")
659-
.iter()
660-
.map(|allocation_id| {
661-
AllocationId::Legacy(
662-
Address::from_str(allocation_id)
663-
.expect("allocation_id should be a valid address"),
664-
)
665-
})
666-
.collect::<HashSet<_>>();
667-
let sender_id = Address::from_str(&row.sender_address)
668-
.expect("sender_address should be a valid address");
656+
// Check if allocation_ids is Some before processing,
657+
// as ARRAY_AGG with FILTER can return NULL
658+
if let Some(allocation_id_strings) = row.allocation_ids {
659+
let allocation_ids = allocation_id_strings
660+
.iter()
661+
.map(|allocation_id| {
662+
AllocationId::Legacy(
663+
Address::from_str(allocation_id)
664+
.expect("allocation_id should be a valid address"),
665+
)
666+
})
667+
.collect::<HashSet<_>>();
669668

670-
// Accumulate allocations for the sender
671-
unfinalized_sender_allocations_map
672-
.entry(sender_id)
673-
.or_default()
674-
.extend(allocation_ids);
669+
if !allocation_ids.is_empty() {
670+
let sender_id = Address::from_str(&row.sender_address)
671+
.expect("sender_address should be a valid address");
672+
673+
unfinalized_sender_allocations_map
674+
.entry(sender_id)
675+
.or_default()
676+
.extend(allocation_ids);
677+
}
678+
}
675679
}
676680
unfinalized_sender_allocations_map
677681
}
@@ -746,25 +750,29 @@ impl State {
746750
.expect("should be able to fetch unfinalized V2 RAVs from the database");
747751

748752
for row in nonfinal_ravs_sender_allocations_in_db {
749-
let allocation_ids = row
750-
.allocation_ids
751-
.expect("all RAVs V2 should have an allocation_id")
752-
.iter()
753-
.map(|allocation_id| {
754-
AllocationId::Legacy(
755-
Address::from_str(allocation_id)
756-
.expect("allocation_id should be a valid address"),
757-
)
758-
})
759-
.collect::<HashSet<_>>();
760-
let sender_id =
761-
Address::from_str(&row.payer).expect("sender_address should be a valid address");
753+
// Check if allocation_ids is Some before processing,
754+
// as ARRAY_AGG with FILTER can return NULL
755+
if let Some(allocation_id_strings) = row.allocation_ids {
756+
let allocation_ids = allocation_id_strings // Use the unwrapped Vec<String>
757+
.iter()
758+
.map(|allocation_id| {
759+
AllocationId::Legacy(
760+
Address::from_str(allocation_id)
761+
.expect("allocation_id should be a valid address"),
762+
)
763+
})
764+
.collect::<HashSet<_>>();
762765

763-
// Accumulate allocations for the sender
764-
unfinalized_sender_allocations_map
765-
.entry(sender_id)
766-
.or_default()
767-
.extend(allocation_ids);
766+
if !allocation_ids.is_empty() {
767+
let sender_id = Address::from_str(&row.payer)
768+
.expect("sender_address should be a valid address");
769+
770+
unfinalized_sender_allocations_map
771+
.entry(sender_id)
772+
.or_default()
773+
.extend(allocation_ids);
774+
}
775+
}
768776
}
769777
unfinalized_sender_allocations_map
770778
}

0 commit comments

Comments
 (0)