60
60
router : R ,
61
61
logger : L ,
62
62
event_handler : E ,
63
- // Lock order: payment_attempts -> invoice_cache
64
- invoice_cache : Mutex < HashMap < PaymentHash , Invoice > > ,
65
- payment_attempts : Mutex < HashMap < PaymentHash , usize > > ,
63
+ invoice_cache : Mutex < HashMap < PaymentHash , ( Invoice , usize ) > > ,
66
64
retry_attempts : usize ,
67
65
}
68
66
@@ -122,7 +120,6 @@ where
122
120
logger,
123
121
event_handler,
124
122
invoice_cache : Mutex :: new ( HashMap :: new ( ) ) ,
125
- payment_attempts : Mutex :: new ( HashMap :: new ( ) ) ,
126
123
retry_attempts : 0 ,
127
124
}
128
125
}
@@ -139,23 +136,15 @@ where
139
136
let mut invoice_cache = self . invoice_cache . lock ( ) . unwrap ( ) ;
140
137
match invoice_cache. entry ( payment_hash) {
141
138
hash_map:: Entry :: Vacant ( entry) => {
142
- self . pay_invoice_internal ( invoice) ?;
143
- entry. insert ( invoice. clone ( ) ) ;
139
+ self . pay_cached_invoice ( invoice) ?;
140
+ entry. insert ( ( invoice. clone ( ) , 0 ) ) ;
144
141
Ok ( ( ) )
145
142
} ,
146
143
hash_map:: Entry :: Occupied ( _) => Err ( PaymentError :: Invoice ( "payment pending" ) ) ,
147
144
}
148
145
}
149
146
150
- fn pay_cached_invoice ( & self , payment_hash : & PaymentHash ) -> Result < ( ) , PaymentError > {
151
- let invoice_cache = self . invoice_cache . lock ( ) . unwrap ( ) ;
152
- match invoice_cache. get ( payment_hash) {
153
- Some ( invoice) => self . pay_invoice_internal ( invoice) ,
154
- None => Err ( PaymentError :: Invoice ( "unknown payment hash" ) ) ,
155
- }
156
- }
157
-
158
- fn pay_invoice_internal ( & self , invoice : & Invoice ) -> Result < ( ) , PaymentError > {
147
+ fn pay_cached_invoice ( & self , invoice : & Invoice ) -> Result < ( ) , PaymentError > {
159
148
let payer = self . payer . node_id ( ) ;
160
149
let payee = invoice. recover_payee_pub_key ( ) ;
161
150
let payee_features = invoice. features ( ) . cloned ( ) ;
@@ -199,40 +188,39 @@ where
199
188
fn handle_event ( & self , event : & Event ) {
200
189
match event {
201
190
Event :: PaymentFailed { payment_hash, rejected_by_dest, .. } => {
202
- let mut attempts_by_payment_hash = self . payment_attempts . lock ( ) . unwrap ( ) ;
203
- let attempts = attempts_by_payment_hash
204
- . entry ( * payment_hash)
205
- . and_modify ( |attempts| * attempts += 1 )
206
- . or_insert ( 1 ) ;
207
- if !rejected_by_dest {
208
- let max_payment_attempts = self . retry_attempts + 1 ;
209
- if * attempts < max_payment_attempts {
210
- if self . pay_cached_invoice ( payment_hash) . is_ok ( ) {
211
- log_trace ! ( self . logger, "Payment {} failed; retrying (attempts: {})" , log_bytes!( payment_hash. 0 ) , attempts) ;
212
- return ;
191
+ let mut invoice_cache = self . invoice_cache . lock ( ) . unwrap ( ) ;
192
+ if let hash_map:: Entry :: Occupied ( mut entry) = invoice_cache. entry ( * payment_hash) {
193
+ let ( invoice, attempts) = entry. get_mut ( ) ;
194
+ * attempts += 1 ;
195
+ if !rejected_by_dest {
196
+ let max_payment_attempts = self . retry_attempts + 1 ;
197
+ if * attempts < max_payment_attempts {
198
+ if self . pay_cached_invoice ( invoice) . is_ok ( ) {
199
+ log_trace ! ( self . logger, "Payment {} failed; retrying (attempts: {})" , log_bytes!( payment_hash. 0 ) , attempts) ;
200
+ return ;
201
+ } else {
202
+ log_trace ! ( self . logger, "Error retrying payment {}; not retrying (attempts: {})" , log_bytes!( payment_hash. 0 ) , attempts) ;
203
+ }
213
204
} else {
214
- log_trace ! ( self . logger, "Error retrying payment {} ; not retrying (attempts: {})" , log_bytes!( payment_hash. 0 ) , attempts) ;
205
+ log_trace ! ( self . logger, "Payment {} failed ; not retrying (attempts: {})" , log_bytes!( payment_hash. 0 ) , attempts) ;
215
206
}
216
207
} else {
217
- log_trace ! ( self . logger, "Payment {} failed ; not retrying (attempts: {})" , log_bytes!( payment_hash. 0 ) , attempts) ;
208
+ log_trace ! ( self . logger, "Payment {} rejected by destination ; not retrying (attempts: {})" , log_bytes!( payment_hash. 0 ) , attempts) ;
218
209
}
210
+
211
+ // Either the payment was rejected, exceeded the maximum attempts, or failed.
212
+ entry. remove ( ) ;
219
213
} else {
220
- log_trace ! ( self . logger, "Payment {} rejected by destination; not retrying (attempts: {} )" , log_bytes!( payment_hash. 0 ) , attempts ) ;
214
+ log_trace ! ( self . logger, "Unknown payment {}; cannot retry )" , log_bytes!( payment_hash. 0 ) ) ;
221
215
}
222
-
223
- // Either the payment was rejected, exceeded the maximum attempts, or failed retry.
224
- self . remove_cached_invoice ( payment_hash) ;
225
- attempts_by_payment_hash. remove ( payment_hash) ;
226
216
} ,
227
217
Event :: PaymentSent { payment_preimage } => {
228
218
let payment_hash = PaymentHash ( Sha256 :: hash ( & payment_preimage. 0 ) . into_inner ( ) ) ;
229
- let mut attempts_by_payment_hash = self . payment_attempts . lock ( ) . unwrap ( ) ;
230
- let attempts = attempts_by_payment_hash
219
+ let mut invoice_cache = self . invoice_cache . lock ( ) . unwrap ( ) ;
220
+ let attempts = invoice_cache
231
221
. remove ( & payment_hash)
232
- . map_or ( 1 , |attempts| attempts + 1 ) ;
222
+ . map_or ( 1 , |( _ , attempts) | attempts + 1 ) ;
233
223
log_trace ! ( self . logger, "Payment {} succeeded (attempts: {})" , log_bytes!( payment_hash. 0 ) , attempts) ;
234
-
235
- self . remove_cached_invoice ( & payment_hash) ;
236
224
} ,
237
225
_ => { } ,
238
226
}
0 commit comments