@@ -8,8 +8,8 @@ use std::{collections::HashMap, str::FromStr};
8
8
use crate :: agent:: sender_allocation:: SenderAllocationMessage ;
9
9
use crate :: lazy_static;
10
10
use alloy_sol_types:: Eip712Domain ;
11
- use anyhow:: anyhow;
12
11
use anyhow:: Result ;
12
+ use anyhow:: { anyhow, bail} ;
13
13
use eventuals:: { Eventual , EventualExt , PipeHandle } ;
14
14
use indexer_common:: escrow_accounts:: EscrowAccounts ;
15
15
use indexer_common:: prelude:: { Allocation , SubgraphClient } ;
@@ -460,58 +460,98 @@ async fn new_receipts_watcher(
460
460
"should be able to deserialize the Postgres Notify event payload as a \
461
461
NewReceiptNotification",
462
462
) ;
463
+ if let Err ( e) = handle_notification (
464
+ new_receipt_notification,
465
+ & escrow_accounts,
466
+ prefix. as_deref ( ) ,
467
+ )
468
+ . await
469
+ {
470
+ error ! ( "{}" , e) ;
471
+ }
472
+ }
473
+ }
463
474
464
- tracing:: debug!(
465
- notification = ?new_receipt_notification,
466
- "New receipt notification detected!"
475
+ async fn handle_notification (
476
+ new_receipt_notification : NewReceiptNotification ,
477
+ escrow_accounts : & Eventual < EscrowAccounts > ,
478
+ prefix : Option < & str > ,
479
+ ) -> Result < ( ) > {
480
+ tracing:: debug!(
481
+ notification = ?new_receipt_notification,
482
+ "New receipt notification detected!"
483
+ ) ;
484
+
485
+ let Ok ( sender_address) = escrow_accounts
486
+ . value ( )
487
+ . await
488
+ . expect ( "should be able to get escrow accounts" )
489
+ . get_sender_for_signer ( & new_receipt_notification. signer_address )
490
+ else {
491
+ // TODO: save the receipt in the failed receipts table?
492
+ bail ! (
493
+ "No sender address found for receipt signer address {}. \
494
+ This should not happen.",
495
+ new_receipt_notification. signer_address
467
496
) ;
497
+ } ;
468
498
469
- let Ok ( sender_address) = escrow_accounts
470
- . value ( )
471
- . await
472
- . expect ( "should be able to get escrow accounts" )
473
- . get_sender_for_signer ( & new_receipt_notification. signer_address )
474
- else {
475
- error ! (
476
- "No sender address found for receipt signer address {}. \
477
- This should not happen.",
478
- new_receipt_notification. signer_address
479
- ) ;
480
- // TODO: save the receipt in the failed receipts table?
481
- continue ;
482
- } ;
483
-
484
- let allocation_id = & new_receipt_notification. allocation_id ;
485
- let allocation_str = & allocation_id. to_string ( ) ;
486
-
487
- let actor_name = format ! (
488
- "{}{sender_address}:{allocation_id}" ,
499
+ let allocation_id = & new_receipt_notification. allocation_id ;
500
+ let allocation_str = & allocation_id. to_string ( ) ;
501
+
502
+ let actor_name = format ! (
503
+ "{}{sender_address}:{allocation_id}" ,
504
+ prefix
505
+ . as_ref( )
506
+ . map_or( String :: default ( ) , |prefix| format!( "{prefix}:" ) )
507
+ ) ;
508
+
509
+ let Some ( sender_allocation) = ActorRef :: < SenderAllocationMessage > :: where_is ( actor_name) else {
510
+ warn ! (
511
+ "No sender_allocation found for sender_address {}, allocation_id {} to process new \
512
+ receipt notification. Starting a new sender_allocation.",
513
+ sender_address, allocation_id
514
+ ) ;
515
+ let sender_account_name = format ! (
516
+ "{}{sender_address}" ,
489
517
prefix
490
518
. as_ref( )
491
519
. map_or( String :: default ( ) , |prefix| format!( "{prefix}:" ) )
492
520
) ;
493
521
494
- if let Some ( sender_allocation) = ActorRef :: < SenderAllocationMessage > :: where_is ( actor_name) {
495
- if let Err ( e) = sender_allocation. cast ( SenderAllocationMessage :: NewReceipt (
496
- new_receipt_notification,
497
- ) ) {
498
- error ! (
499
- "Error while forwarding new receipt notification to sender_allocation: {:?}" ,
500
- e
501
- ) ;
502
- }
503
- } else {
504
- warn ! (
505
- "No sender_allocation found for sender_address {}, allocation_id {} to process new \
506
- receipt notification. This should not happen.",
507
- sender_address,
508
- allocation_id
522
+ let Some ( sender_account) = ActorRef :: < SenderAccountMessage > :: where_is ( sender_account_name)
523
+ else {
524
+ bail ! (
525
+ "No sender_account was found for address: {}." ,
526
+ sender_address
509
527
) ;
510
- }
511
- RECEIPTS_CREATED
512
- . with_label_values ( & [ & sender_address. to_string ( ) , allocation_str] )
513
- . inc ( ) ;
514
- }
528
+ } ;
529
+ sender_account
530
+ . cast ( SenderAccountMessage :: NewAllocationId ( * allocation_id) )
531
+ . map_err ( |e| {
532
+ anyhow ! (
533
+ "Error while sendeing new allocation id message to sender_account: {:?}" ,
534
+ e
535
+ )
536
+ } ) ?;
537
+ return Ok ( ( ) ) ;
538
+ } ;
539
+
540
+ sender_allocation
541
+ . cast ( SenderAllocationMessage :: NewReceipt (
542
+ new_receipt_notification,
543
+ ) )
544
+ . map_err ( |e| {
545
+ anyhow:: anyhow!(
546
+ "Error while forwarding new receipt notification to sender_allocation: {:?}" ,
547
+ e
548
+ )
549
+ } ) ?;
550
+
551
+ RECEIPTS_CREATED
552
+ . with_label_values ( & [ & sender_address. to_string ( ) , allocation_str] )
553
+ . inc ( ) ;
554
+ Ok ( ( ) )
515
555
}
516
556
517
557
#[ cfg( test) ]
@@ -522,6 +562,8 @@ mod tests {
522
562
} ;
523
563
use crate :: agent:: sender_account:: tests:: { MockSenderAllocation , PREFIX_ID } ;
524
564
use crate :: agent:: sender_account:: SenderAccountMessage ;
565
+ use crate :: agent:: sender_accounts_manager:: { handle_notification, NewReceiptNotification } ;
566
+ use crate :: agent:: sender_allocation:: tests:: MockSenderAccount ;
525
567
use crate :: config;
526
568
use crate :: tap:: test_utils:: {
527
569
create_rav, create_received_receipt, store_rav, store_receipt, ALLOCATION_ID_0 ,
@@ -537,6 +579,7 @@ mod tests {
537
579
use sqlx:: postgres:: PgListener ;
538
580
use sqlx:: PgPool ;
539
581
use std:: collections:: { HashMap , HashSet } ;
582
+ use std:: sync:: { Arc , Mutex } ;
540
583
use std:: time:: Duration ;
541
584
542
585
const DUMMY_URL : & str = "http://localhost:1234" ;
@@ -803,4 +846,49 @@ mod tests {
803
846
804
847
new_receipts_watcher_handle. abort ( ) ;
805
848
}
849
+
850
+ #[ tokio:: test]
851
+ async fn test_create_allocation_id ( ) {
852
+ let senders_to_signers = vec ! [ ( SENDER . 1 , vec![ SIGNER . 1 ] ) ] . into_iter ( ) . collect ( ) ;
853
+ let escrow_accounts = EscrowAccounts :: new ( HashMap :: new ( ) , senders_to_signers) ;
854
+ let escrow_accounts = Eventual :: from_value ( escrow_accounts) ;
855
+
856
+ let prefix = format ! (
857
+ "test-{}" ,
858
+ PREFIX_ID . fetch_add( 1 , std:: sync:: atomic:: Ordering :: SeqCst )
859
+ ) ;
860
+
861
+ let last_message_emitted = Arc :: new ( Mutex :: new ( vec ! [ ] ) ) ;
862
+
863
+ let ( sender_account, join_handle) = MockSenderAccount :: spawn (
864
+ Some ( format ! ( "{}:{}" , prefix. clone( ) , SENDER . 1 , ) ) ,
865
+ MockSenderAccount {
866
+ last_message_emitted : last_message_emitted. clone ( ) ,
867
+ } ,
868
+ ( ) ,
869
+ )
870
+ . await
871
+ . unwrap ( ) ;
872
+
873
+ let new_receipt_notification = NewReceiptNotification {
874
+ id : 1 ,
875
+ allocation_id : * ALLOCATION_ID_0 ,
876
+ signer_address : SIGNER . 1 ,
877
+ timestamp_ns : 1 ,
878
+ value : 1 ,
879
+ } ;
880
+
881
+ handle_notification ( new_receipt_notification, & escrow_accounts, Some ( & prefix) )
882
+ . await
883
+ . unwrap ( ) ;
884
+
885
+ tokio:: time:: sleep ( Duration :: from_millis ( 10 ) ) . await ;
886
+
887
+ assert_eq ! (
888
+ last_message_emitted. lock( ) . unwrap( ) . last( ) . unwrap( ) ,
889
+ & SenderAccountMessage :: NewAllocationId ( * ALLOCATION_ID_0 )
890
+ ) ;
891
+ sender_account. stop_and_wait ( None , None ) . await . unwrap ( ) ;
892
+ join_handle. await . unwrap ( ) ;
893
+ }
806
894
}
0 commit comments