1
- import { decodeBase64 , decodeVarint } from '../vendor/deno-deps.js'
1
+ import { decodeBase64 , decodeVarint , pRetry , assertOkResponse } from '../vendor/deno-deps.js'
2
2
3
3
/**
4
4
*
@@ -9,23 +9,25 @@ import { decodeBase64, decodeVarint } from '../vendor/deno-deps.js'
9
9
* provider?: { address: string; protocol: string };
10
10
* }> }
11
11
*/
12
- export async function queryTheIndex ( cid , providerId ) {
13
- const url = `https://cid.contact/cid/${ encodeURIComponent ( cid ) } `
14
-
12
+ export async function queryTheIndex ( cid , providerId ) {
15
13
let providerResults
16
14
try {
17
- const res = await fetch ( url )
18
- if ( ! res . ok ) {
19
- console . error ( 'IPNI query failed, HTTP response: %s %s' , res . status , ( await res . text ( ) ) . trimEnd ( ) )
20
- return { indexerResult : `ERROR_${ res . status } ` }
21
- }
22
-
23
- const result = await res . json ( )
24
- providerResults = result . MultihashResults . flatMap ( r => r . ProviderResults )
25
- console . log ( 'IPNI returned %s provider results: %o' , providerResults . length , providerResults )
15
+ providerResults = await pRetry ( ( ) => getRetrievalProviders ( cid ) , {
16
+ retries : 5 ,
17
+ shouldRetry : ( error ) => {
18
+ return error . statusCode && error . statusCode >= 500
19
+ } ,
20
+ onFailedAttempt : ( error ) => {
21
+ console . error ( error )
22
+ console . error ( 'IPNI query failed, retrying...' )
23
+ } ,
24
+ } )
25
+ console . log ( 'IPNI returned %s provider results' , providerResults . length )
26
26
} catch ( err ) {
27
27
console . error ( 'IPNI query failed.' , err )
28
- return { indexerResult : 'ERROR_FETCH' }
28
+ return {
29
+ indexerResult : typeof err . statusCode === 'number' ? `ERROR_${ err . statusCode } ` : 'ERROR_FETCH' ,
30
+ }
29
31
}
30
32
31
33
let graphsyncProvider
@@ -37,7 +39,7 @@ export async function queryTheIndex (cid, providerId) {
37
39
0x900 : 'bitswap' ,
38
40
0x910 : 'graphsync' ,
39
41
0x0920 : 'http' ,
40
- 4128768 : 'graphsync'
42
+ 4128768 : 'graphsync' ,
41
43
} [ protocolCode ]
42
44
43
45
const address = p . Provider . Addrs [ 0 ]
@@ -47,14 +49,14 @@ export async function queryTheIndex (cid, providerId) {
47
49
case 'http' :
48
50
return {
49
51
indexerResult : 'OK' ,
50
- provider : { address, protocol }
52
+ provider : { address, protocol } ,
51
53
}
52
54
53
55
case 'graphsync' :
54
56
if ( ! graphsyncProvider ) {
55
57
graphsyncProvider = {
56
58
address : `${ address } /p2p/${ p . Provider . ID } ` ,
57
- protocol
59
+ protocol,
58
60
}
59
61
}
60
62
}
@@ -63,10 +65,19 @@ export async function queryTheIndex (cid, providerId) {
63
65
console . log ( 'HTTP protocol is not advertised, falling back to Graphsync.' )
64
66
return {
65
67
indexerResult : 'HTTP_NOT_ADVERTISED' ,
66
- provider : graphsyncProvider
68
+ provider : graphsyncProvider ,
67
69
}
68
70
}
69
71
70
72
console . log ( 'All advertisements are from other miners or for unsupported protocols.' )
71
73
return { indexerResult : 'NO_VALID_ADVERTISEMENT' }
72
74
}
75
+
76
+ async function getRetrievalProviders ( cid ) {
77
+ const url = `https://cid.contact/cid/${ encodeURIComponent ( cid ) } `
78
+ const res = await fetch ( url )
79
+ await assertOkResponse ( res )
80
+
81
+ const result = await res . json ( )
82
+ return result . MultihashResults . flatMap ( ( r ) => r . ProviderResults )
83
+ }
0 commit comments