@@ -3,8 +3,7 @@ use file_store::radio_location_estimates::Entity;
3
3
use helium_crypto:: PublicKeyBinary ;
4
4
use sqlx:: PgPool ;
5
5
use std:: { collections:: HashMap , sync:: Arc } ;
6
- use tokio:: sync:: Mutex ;
7
- use tracing:: info;
6
+ use tokio:: sync:: { Mutex , MutexGuard } ;
8
7
9
8
#[ derive( Debug , Clone , Hash , Eq , PartialEq ) ]
10
9
pub enum LocationCacheKey {
@@ -29,56 +28,57 @@ impl LocationCacheValue {
29
28
}
30
29
}
31
30
31
+ type LocationCacheData = HashMap < LocationCacheKey , LocationCacheValue > ;
32
+
32
33
/// A cache WiFi/Cbrs heartbeat locations
33
34
#[ derive( Clone ) ]
34
35
pub struct LocationCache {
35
36
pool : PgPool ,
36
- data : Arc < Mutex < HashMap < LocationCacheKey , LocationCacheValue > > > ,
37
+ wifi : Arc < Mutex < LocationCacheData > > ,
38
+ cbrs : Arc < Mutex < LocationCacheData > > ,
37
39
}
38
40
39
41
impl LocationCache {
40
42
pub fn new ( pool : & PgPool ) -> Self {
41
- let data = Arc :: new ( Mutex :: new (
42
- HashMap :: < LocationCacheKey , LocationCacheValue > :: new ( ) ,
43
- ) ) ;
44
- let data_clone = data. clone ( ) ;
45
- tokio:: spawn ( async move {
46
- loop {
47
- // Sleep 1 hour
48
- let duration = core:: time:: Duration :: from_secs ( 60 * 60 ) ;
49
- tokio:: time:: sleep ( duration) . await ;
50
-
51
- let now = Utc :: now ( ) ;
52
- // Set the 12-hour threshold
53
- let twelve_hours_ago = now - Duration :: hours ( 12 ) ;
54
-
55
- let mut data = data_clone. lock ( ) . await ;
56
- let size_before = data. len ( ) as f64 ;
57
-
58
- // Retain only values that are within the last 12 hours
59
- data. retain ( |_, v| v. timestamp > twelve_hours_ago) ;
60
-
61
- let size_after = data. len ( ) as f64 ;
62
- info ! ( "cleaned {}" , size_before - size_after) ;
63
- }
64
- } ) ;
43
+ let wifi = Arc :: new ( Mutex :: new ( HashMap :: new ( ) ) ) ;
44
+ let cbrs = Arc :: new ( Mutex :: new ( HashMap :: new ( ) ) ) ;
65
45
// TODO: We could spawn an hydrate from DB here?
66
46
Self {
67
47
pool : pool. clone ( ) ,
68
- data,
48
+ wifi,
49
+ cbrs,
69
50
}
70
51
}
71
52
72
53
pub async fn get ( & self , key : LocationCacheKey ) -> anyhow:: Result < Option < LocationCacheValue > > {
73
54
{
74
- let data = self . data . lock ( ) . await ;
55
+ let data = self . key_to_lock ( & key) . await ;
56
+ if let Some ( & value) = data. get ( & key) {
57
+ return Ok ( Some ( value) ) ;
58
+ }
59
+ }
60
+ match key {
61
+ LocationCacheKey :: WifiPubKey ( pub_key_bin) => {
62
+ self . fetch_wifi_and_insert ( pub_key_bin) . await
63
+ }
64
+ LocationCacheKey :: CbrsId ( id) => self . fetch_cbrs_and_insert ( id) . await ,
65
+ }
66
+ }
67
+
68
+ pub async fn get_recent (
69
+ & self ,
70
+ key : LocationCacheKey ,
71
+ when : Duration ,
72
+ ) -> anyhow:: Result < Option < LocationCacheValue > > {
73
+ {
74
+ let data = self . key_to_lock ( & key) . await ;
75
75
if let Some ( & value) = data. get ( & key) {
76
76
let now = Utc :: now ( ) ;
77
- let twelve_hours_ago = now - Duration :: hours ( 12 ) ;
78
- if value. timestamp > twelve_hours_ago {
79
- return Ok ( None ) ;
80
- } else {
77
+ let before = now - when;
78
+ if value. timestamp > before {
81
79
return Ok ( Some ( value) ) ;
80
+ } else {
81
+ return Ok ( None ) ;
82
82
}
83
83
}
84
84
}
@@ -90,28 +90,41 @@ impl LocationCache {
90
90
}
91
91
}
92
92
93
- pub async fn get_all ( & self ) -> HashMap < LocationCacheKey , LocationCacheValue > {
94
- let data = self . data . lock ( ) . await ;
95
- data. clone ( )
93
+ pub async fn get_all ( & self ) -> LocationCacheData {
94
+ let wifi_data = self . wifi . lock ( ) . await ;
95
+ let mut wifi_data_cloned = wifi_data. clone ( ) ;
96
+
97
+ let cbrs_data = self . cbrs . lock ( ) . await ;
98
+ let cbrs_data_cloned = cbrs_data. clone ( ) ;
99
+
100
+ wifi_data_cloned. extend ( cbrs_data_cloned) ;
101
+ wifi_data_cloned
96
102
}
97
103
98
104
pub async fn insert (
99
105
& self ,
100
106
key : LocationCacheKey ,
101
107
value : LocationCacheValue ,
102
108
) -> anyhow:: Result < ( ) > {
103
- let mut data = self . data . lock ( ) . await ;
109
+ let mut data = self . key_to_lock ( & key ) . await ;
104
110
data. insert ( key, value) ;
105
111
Ok ( ( ) )
106
112
}
107
113
108
114
/// Only used for testing.
109
115
pub async fn remove ( & self , key : LocationCacheKey ) -> anyhow:: Result < ( ) > {
110
- let mut data = self . data . lock ( ) . await ;
116
+ let mut data = self . key_to_lock ( & key ) . await ;
111
117
data. remove ( & key) ;
112
118
Ok ( ( ) )
113
119
}
114
120
121
+ async fn key_to_lock ( & self , key : & LocationCacheKey ) -> MutexGuard < ' _ , LocationCacheData > {
122
+ match key {
123
+ LocationCacheKey :: WifiPubKey ( _) => self . wifi . lock ( ) . await ,
124
+ LocationCacheKey :: CbrsId ( _) => self . cbrs . lock ( ) . await ,
125
+ }
126
+ }
127
+
115
128
async fn fetch_wifi_and_insert (
116
129
& self ,
117
130
pub_key_bin : PublicKeyBinary ,
@@ -134,8 +147,9 @@ impl LocationCache {
134
147
match sqlx_return {
135
148
None => Ok ( None ) ,
136
149
Some ( value) => {
137
- let mut data = self . data . lock ( ) . await ;
138
- data. insert ( LocationCacheKey :: WifiPubKey ( pub_key_bin) , value) ;
150
+ let key = LocationCacheKey :: WifiPubKey ( pub_key_bin) ;
151
+ let mut data = self . key_to_lock ( & key) . await ;
152
+ data. insert ( key, value) ;
139
153
Ok ( Some ( value) )
140
154
}
141
155
}
@@ -147,12 +161,12 @@ impl LocationCache {
147
161
) -> anyhow:: Result < Option < LocationCacheValue > > {
148
162
let sqlx_return: Option < LocationCacheValue > = sqlx:: query_as (
149
163
r#"
150
- SELECT lat, lon, location_validation_timestamp AS timestamp
164
+ SELECT lat, lon, latest_timestamp AS timestamp
151
165
FROM cbrs_heartbeats
152
- WHERE location_validation_timestamp IS NOT NULL
153
- AND location_validation_timestamp >= $1
166
+ WHERE latest_timestamp IS NOT NULL
167
+ AND latest_timestamp >= $1
154
168
AND hotspot_key = $2
155
- ORDER BY location_validation_timestamp DESC
169
+ ORDER BY latest_timestamp DESC
156
170
LIMIT 1
157
171
"# ,
158
172
)
@@ -164,8 +178,9 @@ impl LocationCache {
164
178
match sqlx_return {
165
179
None => Ok ( None ) ,
166
180
Some ( value) => {
167
- let mut data = self . data . lock ( ) . await ;
168
- data. insert ( LocationCacheKey :: CbrsId ( cbsd_id) , value) ;
181
+ let key = LocationCacheKey :: CbrsId ( cbsd_id) ;
182
+ let mut data = self . key_to_lock ( & key) . await ;
183
+ data. insert ( key, value) ;
169
184
Ok ( Some ( value) )
170
185
}
171
186
}
0 commit comments