13
13
} ,
14
14
state:: oracle:: Oracle ,
15
15
} ,
16
- anyhow:: Result ,
16
+ anyhow:: { Context , Result } ,
17
17
solana_account_decoder:: UiAccountEncoding ,
18
18
solana_client:: {
19
19
nonblocking:: {
67
67
) ) ) ;
68
68
69
69
if config. oracle . subscriber_enabled {
70
+ let number_of_workers = 100 ;
71
+ let channel_size = 1000 ;
72
+ let ( sender, receiver) = tokio:: sync:: mpsc:: channel ( channel_size) ;
73
+ let max_elapsed_time = Duration :: from_secs ( 30 ) ;
74
+ let sleep_time = Duration :: from_secs ( 1 ) ;
75
+
70
76
handles. push ( tokio:: spawn ( async move {
71
77
loop {
72
78
let current_time = Instant :: now ( ) ;
@@ -75,17 +81,34 @@ where
75
81
network,
76
82
state. clone ( ) ,
77
83
key_store. pyth_oracle_program_key ,
84
+ sender. clone ( ) ,
78
85
)
79
86
. await
80
87
{
81
- tracing:: error!( err = ?err, "Subscriber exited unexpectedly. " ) ;
82
- if current_time. elapsed ( ) < Duration :: from_secs ( 30 ) {
83
- tracing:: warn!( "Subscriber restarting too quickly. Sleeping for 1 second. " ) ;
84
- tokio:: time:: sleep ( Duration :: from_secs ( 1 ) ) . await ;
88
+ tracing:: error!( ?err, "Subscriber exited unexpectedly" ) ;
89
+ if current_time. elapsed ( ) < max_elapsed_time {
90
+ tracing:: warn!( ?sleep_time , "Subscriber restarting too quickly. Sleeping" ) ;
91
+ tokio:: time:: sleep ( sleep_time ) . await ;
85
92
}
86
93
}
87
94
}
88
95
} ) ) ;
96
+
97
+ let receiver = Arc :: new ( tokio:: sync:: Mutex :: new ( receiver) ) ;
98
+ for _ in 0 ..number_of_workers {
99
+ let receiver = receiver. clone ( ) ;
100
+ handles. push ( tokio:: spawn ( async move {
101
+ loop {
102
+ let mut receiver = receiver. lock ( ) . await ;
103
+ if let Some ( task) = receiver. recv ( ) . await {
104
+ drop ( receiver) ;
105
+ if let Err ( err) = task. await {
106
+ tracing:: error!( %err, "error running price update" ) ;
107
+ }
108
+ }
109
+ }
110
+ } ) ) ;
111
+ }
89
112
}
90
113
91
114
handles
@@ -102,6 +125,7 @@ async fn subscriber<S>(
102
125
network : Network ,
103
126
state : Arc < S > ,
104
127
program_key : Pubkey ,
128
+ sender : tokio:: sync:: mpsc:: Sender < tokio:: task:: JoinHandle < ( ) > > ,
105
129
) -> Result < ( ) >
106
130
where
107
131
S : Oracle ,
@@ -129,14 +153,17 @@ where
129
153
Some ( account) => {
130
154
let pubkey: Pubkey = update. value . pubkey . as_str ( ) . try_into ( ) ?;
131
155
let state = state. clone ( ) ;
132
- tokio:: spawn ( async move {
133
- if let Err ( err) =
134
- Oracle :: handle_price_account_update ( & * state, network, & pubkey, & account)
135
- . await
136
- {
137
- tracing:: error!( err = ?err, "Failed to handle account update." ) ;
138
- }
139
- } ) ;
156
+ sender
157
+ . send ( tokio:: spawn ( async move {
158
+ if let Err ( err) =
159
+ Oracle :: handle_price_account_update ( & * state, network, & pubkey, & account)
160
+ . await
161
+ {
162
+ tracing:: error!( ?err, "Failed to handle account update" ) ;
163
+ }
164
+ } ) )
165
+ . await
166
+ . context ( "sending handle_price_account_update task to worker" ) ?;
140
167
}
141
168
142
169
None => {
0 commit comments