Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
32bc941
Add test_save_radio_threshold tests
kurotych Mar 31, 2025
e8666c0
Add test_delete_radio_threshold
kurotych Mar 31, 2025
baf11be
Add test_verified_radio_thresholds
kurotych Mar 31, 2025
54694b2
Add test_verify_legacy
kurotych Mar 31, 2025
6fed9fd
Remove verify_legacy function
kurotych Mar 31, 2025
31910d4
Add migration. DROP TABLE grandfathered_radio_threshold
kurotych Mar 31, 2025
473b413
DELETE cbsd_id from radio_threshold table and radio_threshold.rs module
kurotych Mar 31, 2025
af95af3
Increace migrations number
kurotych Mar 31, 2025
980c642
Don't need to DELETE FROM cbrs_heartbeats anymore
kurotych Apr 1, 2025
b377c86
Remove cbsd_id selecting from valid radios
kurotych Apr 1, 2025
9b3ee25
Remove cbrs from valid_radios.sql
kurotych Apr 1, 2025
3b83e2a
Add migration. DROP TABLE cbrs_heartbeats
kurotych Apr 1, 2025
217c6a5
Remove cell_type from struct HeartbeatReward
kurotych Apr 1, 2025
e321bb3
Remove redundant cbsd_id from valid_radio.sql
kurotych Apr 1, 2025
b4bcc67
Make distances_to_asserted not optional in HeartbeatReward
kurotych Apr 1, 2025
bb0b097
Add migration: DROP TABLE old_hex_coverage
kurotych Apr 1, 2025
5d4e992
Add migration. DELETE FROM seniority WHERE radio_type = 'cbrs'
kurotych Apr 1, 2025
4136a9d
Add migration. DELETE FROM coverage_objects WHERE radio_type = 'cbrs'
kurotych Apr 1, 2025
d35b68d
verify_report can no longer fail
kurotych Apr 3, 2025
9101622
Refactor fn verified_radio_thresholds. Get rid of RadioThreshold
kurotych Apr 3, 2025
1ab0b25
up migrations
kurotych Apr 3, 2025
f6f9fb8
Refactor tests
kurotych Apr 3, 2025
e6ae2fc
Rework migrations
kurotych Apr 21, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DROP TABLE grandfathered_radio_threshold;
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
DELETE FROM radio_threshold WHERE cbsd_id IS NOT NULL;

DROP INDEX radio_threshold_hotspot_pubkey_cbsd_id_idx;

ALTER TABLE radio_threshold DROP COLUMN cbsd_id;

CREATE UNIQUE INDEX radio_threshold_hotspot_pubkey_idx ON radio_threshold (hotspot_pubkey);
1 change: 1 addition & 0 deletions mobile_verifier/migrations/47_drop_cbrs_heartbeats.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DROP TABLE cbrs_heartbeats;
1 change: 1 addition & 0 deletions mobile_verifier/migrations/48_drop_old_hex_coverage.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DROP TABLE old_hex_coverage;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DELETE FROM seniority WHERE radio_type = 'cbrs';
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DELETE FROM coverage_objects WHERE radio_type = 'cbrs';
68 changes: 48 additions & 20 deletions mobile_verifier/src/heartbeats/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ pub mod last_location;
pub mod wifi;

use crate::{
cell_type::{CellType, CellTypeLabel},
cell_type::CellType,
coverage::{self, CoverageClaimTimeCache, CoverageObjectCache, CoverageObjectMeta},
geofence::GeofenceValidator,
seniority::{Seniority, SeniorityUpdate},
Expand Down Expand Up @@ -205,8 +205,7 @@ impl From<WifiHeartbeatIngestReport> for Heartbeat {
#[derive(Debug, Clone, PartialEq, sqlx::FromRow)]
pub struct HeartbeatReward {
pub hotspot_key: PublicKeyBinary,
pub cell_type: CellType,
pub distances_to_asserted: Option<Vec<i64>>,
pub distances_to_asserted: Vec<i64>,
pub trust_score_multipliers: Vec<Decimal>,
pub coverage_object: Uuid,
}
Expand All @@ -216,11 +215,8 @@ impl HeartbeatReward {
KeyType::Wifi(&self.hotspot_key)
}

pub fn id(&self) -> anyhow::Result<String> {
match self.cell_type.to_label() {
CellTypeLabel::Wifi => Ok(self.hotspot_key.to_string()),
_ => Err(anyhow!("failed to derive label from cell type")),
}
pub fn id(&self) -> String {
self.hotspot_key.to_string()
}

pub fn validated<'a>(
Expand All @@ -234,16 +230,21 @@ impl HeartbeatReward {
.fetch(exec)
}

pub fn iter_distances_and_scores(&self) -> impl Iterator<Item = (i64, Decimal)> {
let fallback: Vec<i64> = std::iter::repeat(0)
.take(self.trust_score_multipliers.len())
.collect();
pub fn iter_distances_and_scores(
&self,
) -> anyhow::Result<impl Iterator<Item = (i64, Decimal)>> {
// This should never happen if valid_radio.sql is not touched
if self.trust_score_multipliers.len() != self.distances_to_asserted.len() {
return Err(anyhow!(
"Mismatched lengths between distances_to_asserted and trust_score_multipliers"
));
}

self.distances_to_asserted
Ok(self
.distances_to_asserted
.clone()
.unwrap_or(fallback)
.into_iter()
.zip(self.trust_score_multipliers.clone())
.zip(self.trust_score_multipliers.clone()))
}
}

Expand Down Expand Up @@ -629,11 +630,6 @@ pub async fn clear_heartbeats(
tx: &mut sqlx::Transaction<'_, sqlx::Postgres>,
timestamp: &DateTime<Utc>,
) -> Result<(), sqlx::Error> {
sqlx::query("DELETE FROM cbrs_heartbeats WHERE truncated_timestamp < $1;")
.bind(timestamp)
.execute(&mut *tx)
.await?;

sqlx::query("DELETE FROM wifi_heartbeats WHERE truncated_timestamp < $1;")
.bind(timestamp)
.execute(&mut *tx)
Expand All @@ -650,6 +646,38 @@ mod test {
use file_store::wifi_heartbeat::WifiHeartbeat;
use proto::SeniorityUpdateReason::*;

#[test]
fn test_iter_distances_and_scores_with_matching_lengths() {
let reward = HeartbeatReward {
hotspot_key: PublicKeyBinary::from(vec![1, 2, 3]),
distances_to_asserted: vec![10, 20, 30],
trust_score_multipliers: vec![dec!(0.25), dec!(0.5), dec!(1.0)],
coverage_object: uuid::Uuid::new_v4(),
};

let result = reward.iter_distances_and_scores();
assert!(result.is_ok(), "Expected successful iteration");

let pairs: Vec<(i64, Decimal)> = result.unwrap().collect();
assert_eq!(pairs.len(), 3, "Expected 3 pairs in the iterator");
assert_eq!(pairs[0], (10, dec!(0.25)));
assert_eq!(pairs[1], (20, dec!(0.5)));
assert_eq!(pairs[2], (30, dec!(1.0)));
}

#[test]
fn test_iter_distances_and_scores_with_mismatched_lengths() {
let reward = HeartbeatReward {
hotspot_key: PublicKeyBinary::from(vec![1, 2, 3]),
distances_to_asserted: vec![10, 20], // Only 2 elements
trust_score_multipliers: vec![dec!(0.25), dec!(0.5), dec!(1.0)], // 3 elements
coverage_object: uuid::Uuid::new_v4(),
};

let result = reward.iter_distances_and_scores();
assert!(result.is_err(), "Expected error due to mismatched lengths");
}

fn heartbeat(timestamp: DateTime<Utc>, coverage_object: Uuid) -> ValidatedHeartbeat {
ValidatedHeartbeat {
cell_type: CellType::CellTypeNone,
Expand Down
81 changes: 14 additions & 67 deletions mobile_verifier/src/heartbeats/valid_radios.sql
Original file line number Diff line number Diff line change
@@ -1,42 +1,6 @@
WITH latest_cbrs_hotspot AS (
SELECT DISTINCT ON (cbsd_id)
cbsd_id,
hotspot_key
FROM
cbrs_heartbeats
WHERE
truncated_timestamp >= $1
AND truncated_timestamp < $2
ORDER BY
cbsd_id,
latest_timestamp DESC
),
heartbeats AS (
SELECT
lch.hotspot_key,
ch.cbsd_id,
ch.cell_type,
CASE WHEN count(*) >= $3 THEN
1.0
ELSE
0.0
END AS heartbeat_multiplier,
NULL as distances_to_asserted,
ARRAY_AGG(ch.location_trust_score_multiplier) as trust_score_multipliers
FROM
cbrs_heartbeats ch
INNER JOIN latest_cbrs_hotspot lch ON ch.cbsd_id = lch.cbsd_id
WHERE
ch.truncated_timestamp >= $1
AND ch.truncated_timestamp < $2
GROUP BY
ch.cbsd_id,
lch.hotspot_key,
ch.cell_type
UNION
WITH heartbeats AS (
SELECT
hotspot_key,
NULL AS cbsd_id,
cell_type,
CASE WHEN count(*) >= $3 THEN
1.0
Expand All @@ -54,44 +18,27 @@ heartbeats AS (
hotspot_key,
cell_type
),
latest_uuids AS (( SELECT DISTINCT ON (hotspot_key,
cbsd_id)
hotspot_key,
cbsd_id,
coverage_object
FROM
cbrs_heartbeats ch
WHERE
truncated_timestamp >= $1
AND truncated_timestamp < $2
ORDER BY
hotspot_key,
cbsd_id,
truncated_timestamp DESC)
UNION ( SELECT DISTINCT ON (hotspot_key)
hotspot_key,
NULL AS cbsd_id,
coverage_object
FROM
wifi_heartbeats wh
WHERE
truncated_timestamp >= $1
AND truncated_timestamp < $2
ORDER BY
hotspot_key,
truncated_timestamp DESC))
latest_uuids AS (
SELECT DISTINCT ON (hotspot_key)
hotspot_key,
coverage_object
FROM
wifi_heartbeats wh
WHERE
truncated_timestamp >= $1
AND truncated_timestamp < $2
ORDER BY
hotspot_key,
truncated_timestamp DESC
)
SELECT
hb.hotspot_key,
hb.cbsd_id,
hb.cell_type,
hb.distances_to_asserted,
hb.trust_score_multipliers,
u.coverage_object
FROM
heartbeats hb
INNER JOIN latest_uuids u ON hb.hotspot_key = u.hotspot_key
AND (hb.cbsd_id = u.cbsd_id
OR (hb.cbsd_id IS NULL
AND u.cbsd_id IS NULL))
WHERE
hb.heartbeat_multiplier = 1.0
Loading