@@ -226,31 +226,61 @@ func (s *dhStore) RemoveProviderContext(providerID peer.ID, contextID []byte) er
226
226
hvk := dhash .SHA256 (vk , nil )
227
227
b58hvk := "/" + base58 .Encode (hvk )
228
228
229
+ errs := make (chan error , len (s .metaDeleteURLs ))
229
230
for _ , u := range s .metaDeleteURLs {
230
- req , err := http .NewRequestWithContext (ctx , http .MethodDelete , u + b58hvk , nil )
231
- if err != nil {
232
- return err
233
- }
234
- req .Header .Set ("Content-Type" , "application/json" )
231
+ go func (dhURL string ) {
232
+ err := s .sendDelContextRequest (ctx , dhURL )
233
+ if err != nil && ctx .Err () == nil {
234
+ log .Errorw ("Failed metadata delete, retrying" , "err" , err , "provider" , providerID )
235
+ // If ctx is still ok, then try once more with the specific
236
+ // dhstore that returned the error. This avoids having to retry
237
+ // sending everything to all dhstores again.
238
+ time .Sleep (50 * time .Millisecond )
239
+ err = s .sendDelContextRequest (ctx , dhURL )
240
+ if err != nil {
241
+ log .Errorw ("Failed metadata delete retry" , "err" , err , "provider" , providerID )
242
+ }
243
+ }
244
+ errs <- err
245
+ }(u + b58hvk )
246
+ }
235
247
236
- start := time . Now ()
237
- rsp , err := s . httpClient . Do ( req )
248
+ for i := 0 ; i < len ( s . metaDeleteURLs ); i ++ {
249
+ err := <- errs
238
250
if err != nil {
251
+ // Return first error. Goroutines will complete because errs
252
+ // channel is buffered to allow them all to write.
239
253
return err
240
254
}
241
- io .Copy (io .Discard , rsp .Body )
242
- rsp .Body .Close ()
255
+ // No need to check context, because goroutines will exit if canceled.
256
+ }
257
+ log .Infow ("Sent metadata delete to all dhstores" , "dhstores" , len (s .metaDeleteURLs ), "provider" , providerID )
258
+ return nil
259
+ }
243
260
244
- if rsp .StatusCode != http .StatusOK {
245
- return fmt .Errorf ("failed to delete metadata at %s: %s" , u , http .StatusText (rsp .StatusCode ))
246
- }
261
+ func (s * dhStore ) sendDelContextRequest (ctx context.Context , dhURL string ) error {
262
+ req , err := http .NewRequestWithContext (ctx , http .MethodDelete , dhURL , nil )
263
+ if err != nil {
264
+ return err
265
+ }
266
+ req .Header .Set ("Content-Type" , "application/json" )
247
267
248
- stats .RecordWithOptions (context .Background (),
249
- stats .WithTags (tag .Insert (metrics .Method , "delete" )),
250
- stats .WithMeasurements (metrics .DHMetadataLatency .M (metrics .MsecSince (start ))))
268
+ start := time .Now ()
269
+ rsp , err := s .httpClient .Do (req )
270
+ if err != nil {
271
+ return err
272
+ }
273
+ io .Copy (io .Discard , rsp .Body )
274
+ rsp .Body .Close ()
251
275
252
- log .Infow ("Sent metadata delete to dhstore" , "url" , u , "provider" , providerID )
276
+ if rsp .StatusCode != http .StatusOK {
277
+ return fmt .Errorf ("failed to delete metadata at %s: %s" , dhURL , http .StatusText (rsp .StatusCode ))
253
278
}
279
+
280
+ stats .RecordWithOptions (context .Background (),
281
+ stats .WithTags (tag .Insert (metrics .Method , "delete" )),
282
+ stats .WithMeasurements (metrics .DHMetadataLatency .M (metrics .MsecSince (start ))))
283
+
254
284
return nil
255
285
}
256
286
@@ -378,7 +408,15 @@ func (s *dhStore) sendDHDeleteIndexRequest(ctx context.Context, merges []client.
378
408
errs := make (chan error , len (s .indexDeleteURLs ))
379
409
for _ , u := range s .indexDeleteURLs {
380
410
go func (dhURL string ) {
381
- errs <- s .sendDelRequest (ctx , dhURL , data )
411
+ err := s .sendDelRequest (ctx , dhURL , data )
412
+ if err != nil && ctx .Err () == nil {
413
+ // If ctx is still ok, then try once more with the specific
414
+ // dhstore that returned the error. This avoids having to retry
415
+ // sending everything to all dhstores again.
416
+ time .Sleep (50 * time .Millisecond )
417
+ err = s .sendDelRequest (ctx , dhURL , data )
418
+ }
419
+ errs <- err
382
420
}(u )
383
421
}
384
422
0 commit comments