@@ -6,7 +6,7 @@ use diesel::{
6
6
} ;
7
7
use std:: {
8
8
collections:: { BTreeMap , HashMap } ,
9
- sync:: { Arc , Mutex } ,
9
+ sync:: { atomic :: AtomicU8 , Arc , Mutex } ,
10
10
} ;
11
11
use std:: { fmt, io:: Write } ;
12
12
use std:: { iter:: FromIterator , time:: Duration } ;
@@ -1147,23 +1147,67 @@ impl SubgraphStoreInner {
1147
1147
}
1148
1148
}
1149
1149
1150
+ const STATE_ENS_NOT_CHECKED : u8 = 0 ;
1151
+ const STATE_ENS_EMPTY : u8 = 1 ;
1152
+ const STATE_ENS_NOT_EMPTY : u8 = 2 ;
1153
+
1154
+ /// EnsLookup reads from a rainbow table store in postgres that needs to be manually
1155
+ /// loaded. To avoid unnecessary database roundtrips, the empty table check is lazy
1156
+ /// and will not be retried. Once the table is checked, any subsequent calls will
1157
+ /// just used the stored result.
1150
1158
struct EnsLookup {
1151
1159
primary : ConnectionPool ,
1160
+ // In order to keep the struct lock free, we'll use u8 for the status:
1161
+ // 0 - Not Checked
1162
+ // 1 - Checked - empty
1163
+ // 2 - Checked - non empty
1164
+ state : AtomicU8 ,
1165
+ }
1166
+
1167
+ impl EnsLookup {
1168
+ pub fn new ( pool : ConnectionPool ) -> Self {
1169
+ Self {
1170
+ primary : pool,
1171
+ state : AtomicU8 :: new ( STATE_ENS_NOT_CHECKED ) ,
1172
+ }
1173
+ }
1174
+
1175
+ fn is_table_empty ( pool : & ConnectionPool ) -> Result < bool , StoreError > {
1176
+ let conn = pool. get ( ) ?;
1177
+ primary:: Connection :: new ( conn) . is_ens_table_empty ( )
1178
+ }
1152
1179
}
1153
1180
1154
1181
impl EnsLookupTrait for EnsLookup {
1155
1182
fn find_name ( & self , hash : & str ) -> Result < Option < String > , StoreError > {
1156
1183
let conn = self . primary . get ( ) ?;
1157
1184
primary:: Connection :: new ( conn) . find_ens_name ( hash)
1158
1185
}
1186
+
1187
+ fn is_table_empty ( & self ) -> Result < bool , StoreError > {
1188
+ match self . state . load ( std:: sync:: atomic:: Ordering :: SeqCst ) {
1189
+ STATE_ENS_NOT_CHECKED => { }
1190
+ STATE_ENS_EMPTY => return Ok ( true ) ,
1191
+ STATE_ENS_NOT_EMPTY => return Ok ( false ) ,
1192
+ _ => unreachable ! ( "unsupported state" ) ,
1193
+ }
1194
+
1195
+ let is_empty = Self :: is_table_empty ( & self . primary ) ?;
1196
+ let new_state = match is_empty {
1197
+ true => STATE_ENS_EMPTY ,
1198
+ false => STATE_ENS_NOT_EMPTY ,
1199
+ } ;
1200
+ self . state
1201
+ . store ( new_state, std:: sync:: atomic:: Ordering :: SeqCst ) ;
1202
+
1203
+ Ok ( is_empty)
1204
+ }
1159
1205
}
1160
1206
1161
1207
#[ async_trait:: async_trait]
1162
1208
impl SubgraphStoreTrait for SubgraphStore {
1163
1209
fn ens_lookup ( & self ) -> Arc < dyn EnsLookupTrait > {
1164
- Arc :: new ( EnsLookup {
1165
- primary : self . mirror . primary ( ) . clone ( ) ,
1166
- } )
1210
+ Arc :: new ( EnsLookup :: new ( self . mirror . primary ( ) . clone ( ) ) )
1167
1211
}
1168
1212
1169
1213
// FIXME: This method should not get a node_id
0 commit comments