2
2
// SPDX-License-Identifier: Apache-2.0
3
3
4
4
use std:: collections:: HashSet ;
5
+ use std:: sync:: Mutex as StdMutex ;
5
6
use std:: { collections:: HashMap , str:: FromStr , sync:: Arc } ;
6
7
7
8
use alloy_sol_types:: Eip712Domain ;
@@ -13,7 +14,6 @@ use indexer_common::prelude::{Allocation, SubgraphClient};
13
14
use serde:: Deserialize ;
14
15
use sqlx:: { postgres:: PgListener , PgPool } ;
15
16
use thegraph:: types:: Address ;
16
- use tokio:: sync:: RwLock ;
17
17
use tracing:: { error, warn} ;
18
18
19
19
use crate :: config;
@@ -41,7 +41,7 @@ struct Inner {
41
41
config : & ' static config:: Cli ,
42
42
pgpool : PgPool ,
43
43
/// Map of sender_address to SenderAllocation.
44
- sender_accounts : Arc < RwLock < HashMap < Address , SenderAccount > > > ,
44
+ sender_accounts : Arc < StdMutex < HashMap < Address , Arc < SenderAccount > > > > ,
45
45
indexer_allocations : Eventual < HashMap < Address , Allocation > > ,
46
46
escrow_accounts : Eventual < EscrowAccounts > ,
47
47
escrow_subgraph : & ' static SubgraphClient ,
@@ -57,11 +57,11 @@ impl Inner {
57
57
target_senders : HashSet < Address > ,
58
58
) -> Result < ( ) > {
59
59
let eligible_allocations: HashSet < Address > = indexer_allocations. keys ( ) . copied ( ) . collect ( ) ;
60
- let mut sender_accounts_write = self . sender_accounts . write ( ) . await ;
60
+ let mut sender_accounts_copy = self . sender_accounts . lock ( ) . unwrap ( ) . clone ( ) ;
61
61
62
62
// For all Senders that are not in the target_senders HashSet, set all their allocations to
63
63
// ineligible. That will trigger a finalization of all their receipts.
64
- for ( sender_id, sender_account) in sender_accounts_write . iter_mut ( ) {
64
+ for ( sender_id, sender_account) in sender_accounts_copy . iter ( ) {
65
65
if !target_senders. contains ( sender_id) {
66
66
sender_account. update_allocations ( HashSet :: new ( ) ) . await ;
67
67
}
@@ -70,33 +70,37 @@ impl Inner {
70
70
// Get or create SenderAccount instances for all currently eligible
71
71
// senders.
72
72
for sender_id in & target_senders {
73
- let sender = sender_accounts_write
74
- . entry ( * sender_id)
75
- . or_insert ( SenderAccount :: new (
76
- self . config ,
77
- self . pgpool . clone ( ) ,
78
- * sender_id,
79
- self . escrow_accounts . clone ( ) ,
80
- self . escrow_subgraph ,
81
- self . escrow_adapter . clone ( ) ,
82
- self . tap_eip712_domain_separator . clone ( ) ,
83
- self . sender_aggregator_endpoints
84
- . get ( sender_id)
85
- . ok_or_else ( || {
86
- anyhow ! (
87
- "No sender_aggregator_endpoint found for sender {}" ,
88
- sender_id
89
- )
90
- } ) ?
91
- . clone ( ) ,
92
- ) ) ;
73
+ let sender =
74
+ sender_accounts_copy
75
+ . entry ( * sender_id)
76
+ . or_insert ( Arc :: new ( SenderAccount :: new (
77
+ self . config ,
78
+ self . pgpool . clone ( ) ,
79
+ * sender_id,
80
+ self . escrow_accounts . clone ( ) ,
81
+ self . escrow_subgraph ,
82
+ self . escrow_adapter . clone ( ) ,
83
+ self . tap_eip712_domain_separator . clone ( ) ,
84
+ self . sender_aggregator_endpoints
85
+ . get ( sender_id)
86
+ . ok_or_else ( || {
87
+ anyhow ! (
88
+ "No sender_aggregator_endpoint found for sender {}" ,
89
+ sender_id
90
+ )
91
+ } ) ?
92
+ . clone ( ) ,
93
+ ) ) ) ;
93
94
94
95
// Update sender's allocations
95
96
sender
96
97
. update_allocations ( eligible_allocations. clone ( ) )
97
98
. await ;
98
99
}
99
100
101
+ // Replace the sender_accounts with the updated sender_accounts_copy
102
+ * self . sender_accounts . lock ( ) . unwrap ( ) = sender_accounts_copy;
103
+
100
104
// TODO: remove Sender instances that are finished. Ideally done in another async task?
101
105
102
106
Ok ( ( ) )
@@ -118,7 +122,7 @@ impl SenderAccountsManager {
118
122
let inner = Arc :: new ( Inner {
119
123
config,
120
124
pgpool,
121
- sender_accounts : Arc :: new ( RwLock :: new ( HashMap :: new ( ) ) ) ,
125
+ sender_accounts : Arc :: new ( StdMutex :: new ( HashMap :: new ( ) ) ) ,
122
126
indexer_allocations,
123
127
escrow_accounts,
124
128
escrow_subgraph,
@@ -239,11 +243,11 @@ impl SenderAccountsManager {
239
243
240
244
// Create SenderAccount instances for all senders that have unfinalized allocations and add
241
245
// the allocations to the SenderAccount instances.
242
- let mut sender_accounts_write_lock = inner . sender_accounts . write ( ) . await ;
246
+ let mut sender_accounts = HashMap :: new ( ) ;
243
247
for ( sender_id, allocation_ids) in unfinalized_sender_allocations_map {
244
- let sender = sender_accounts_write_lock
248
+ let sender = sender_accounts
245
249
. entry ( sender_id)
246
- . or_insert ( SenderAccount :: new (
250
+ . or_insert ( Arc :: new ( SenderAccount :: new (
247
251
config,
248
252
inner. pgpool . clone ( ) ,
249
253
sender_id,
@@ -256,7 +260,7 @@ impl SenderAccountsManager {
256
260
. get ( & sender_id)
257
261
. expect ( "should be able to get sender_aggregator_endpoint for sender" )
258
262
. clone ( ) ,
259
- ) ) ;
263
+ ) ) ) ;
260
264
261
265
sender. update_allocations ( allocation_ids) . await ;
262
266
@@ -265,7 +269,8 @@ impl SenderAccountsManager {
265
269
. await
266
270
. expect ( "should be able to recompute unaggregated fees" ) ;
267
271
}
268
- drop ( sender_accounts_write_lock) ;
272
+ // replace the sender_accounts with the updated sender_accounts
273
+ * inner. sender_accounts . lock ( ) . unwrap ( ) = sender_accounts;
269
274
270
275
// Update senders and allocations based on the current state of the network.
271
276
// It is important to do this after creating the Sender and SenderAllocation instances based
@@ -320,7 +325,7 @@ impl SenderAccountsManager {
320
325
/// corresponding SenderAccount.
321
326
async fn new_receipts_watcher (
322
327
mut pglistener : PgListener ,
323
- sender_accounts : Arc < RwLock < HashMap < Address , SenderAccount > > > ,
328
+ sender_accounts : Arc < StdMutex < HashMap < Address , Arc < SenderAccount > > > > ,
324
329
escrow_accounts : Eventual < EscrowAccounts > ,
325
330
) {
326
331
loop {
@@ -354,7 +359,13 @@ impl SenderAccountsManager {
354
359
}
355
360
} ;
356
361
357
- if let Some ( sender_account) = sender_accounts. read ( ) . await . get ( & sender_address) {
362
+ let sender_account = sender_accounts
363
+ . lock ( )
364
+ . unwrap ( )
365
+ . get ( & sender_address)
366
+ . cloned ( ) ;
367
+
368
+ if let Some ( sender_account) = sender_account {
358
369
sender_account
359
370
. handle_new_receipt_notification ( new_receipt_notification)
360
371
. await ;
@@ -492,8 +503,8 @@ mod tests {
492
503
assert ! ( sender_account
493
504
. _inner
494
505
. sender_accounts
495
- . write ( )
496
- . await
506
+ . lock ( )
507
+ . unwrap ( )
497
508
. contains_key( & SENDER . 1 ) ) ;
498
509
499
510
// Remove the escrow account from the escrow_accounts Eventual.
@@ -506,22 +517,20 @@ mod tests {
506
517
assert ! ( sender_account
507
518
. _inner
508
519
. sender_accounts
509
- . read ( )
510
- . await
520
+ . lock ( )
521
+ . unwrap ( )
511
522
. get( & SENDER . 1 )
512
523
. unwrap( )
513
524
. _tests_get_allocations_active( )
514
- . await
515
525
. is_empty( ) ) ;
516
526
assert ! ( sender_account
517
527
. _inner
518
528
. sender_accounts
519
- . read ( )
520
- . await
529
+ . lock ( )
530
+ . unwrap ( )
521
531
. get( & SENDER . 1 )
522
532
. unwrap( )
523
533
. _tests_get_allocations_ineligible( )
524
- . await
525
534
. contains_key( & allocation_id) ) ;
526
535
}
527
536
}
0 commit comments