-
Notifications
You must be signed in to change notification settings - Fork 1
feat: skip ads where entries cannot be retrieved #23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
3625265
bc75a24
4311a10
a80f971
737f284
b83d774
d9707c4
8c27540
1f06f37
a4d7f3a
efd9da6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -151,7 +151,7 @@ export async function processNextAdvertisement ({ | |||||
assert(state.tail) | ||||||
|
||||||
try { | ||||||
const { previousAdvertisementCid, ...entry } = await fetchAdvertisedPayload( | ||||||
const { previousAdvertisementCid, entriesFetchError, ...entry } = await fetchAdvertisedPayload( | ||||||
providerInfo.providerAddress, | ||||||
state.tail, | ||||||
{ fetchTimeout } | ||||||
|
@@ -169,7 +169,10 @@ export async function processNextAdvertisement ({ | |||||
state.status = `Walking the advertisements from ${state.head}, next step: ${state.tail}` | ||||||
} | ||||||
|
||||||
const indexEntry = entry.pieceCid ? entry : undefined | ||||||
if (entriesFetchError) { | ||||||
state.entriesNotRetrievable = (state.entriesNotRetrievable ?? 0) + 1 | ||||||
} | ||||||
const indexEntry = entry.pieceCid && entry.payloadCid ? entry : undefined | ||||||
bajtos marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
const finished = !state.tail | ||||||
return { | ||||||
newState: state, | ||||||
|
@@ -179,21 +182,26 @@ export async function processNextAdvertisement ({ | |||||
} catch (err) { | ||||||
let reason | ||||||
if (err instanceof Error) { | ||||||
const url = 'url' in err ? err.url : undefined | ||||||
const url = 'url' in err ? err.url : providerInfo.providerAddress | ||||||
if ('serverMessage' in err && err.serverMessage) { | ||||||
reason = err.serverMessage | ||||||
if ('statusCode' in err && err.statusCode) { | ||||||
reason = `${err.statusCode} ${reason}` | ||||||
} | ||||||
} else if ('statusCode' in err && err.statusCode) { | ||||||
reason = `HTTP request to ${url ?? providerInfo.providerAddress} failed: ${err.statusCode}` | ||||||
reason = err.statusCode | ||||||
} else if (err.name === 'TimeoutError') { | ||||||
reason = `HTTP request to ${url ?? providerInfo.providerAddress} timed out` | ||||||
reason = 'operation timed out' | ||||||
} else if ( | ||||||
err.name === 'TypeError' && | ||||||
err.message === 'fetch failed' && | ||||||
err.cause && | ||||||
err.cause instanceof Error | ||||||
) { | ||||||
reason = `HTTP request to ${url ?? providerInfo.providerAddress} failed: ${err.cause.message}` | ||||||
reason = err.cause.message | ||||||
} | ||||||
|
||||||
reason = `HTTP request to ${url} failed: ${reason}` | ||||||
juliangruber marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
} | ||||||
|
||||||
debug( | ||||||
|
@@ -252,23 +260,43 @@ export async function fetchAdvertisedPayload (providerAddress, advertisementCid, | |||||
return { previousAdvertisementCid } | ||||||
} | ||||||
|
||||||
const entriesChunk = | ||||||
const meta = parseMetadata(advertisement.Metadata['/'].bytes) | ||||||
const pieceCid = meta.deal?.PieceCID.toString() | ||||||
|
||||||
try { | ||||||
const entriesChunk = | ||||||
/** @type {{ | ||||||
Entries: { '/' : { bytes: string } }[] | ||||||
}} */( | ||||||
await fetchCid(providerAddress, entriesCid, { fetchTimeout }) | ||||||
) | ||||||
debug('entriesChunk %s %j', entriesCid, entriesChunk.Entries.slice(0, 5)) | ||||||
const entryHash = entriesChunk.Entries[0]['/'].bytes | ||||||
const payloadCid = CID.create(1, 0x55 /* raw */, multihash.decode(Buffer.from(entryHash, 'base64'))).toString() | ||||||
await fetchCid(providerAddress, entriesCid, { fetchTimeout }) | ||||||
) | ||||||
debug('entriesChunk %s %j', entriesCid, entriesChunk.Entries.slice(0, 5)) | ||||||
const entryHash = entriesChunk.Entries[0]['/'].bytes | ||||||
const payloadCid = CID.create(1, 0x55 /* raw */, multihash.decode(Buffer.from(entryHash, 'base64'))).toString() | ||||||
|
||||||
const meta = parseMetadata(advertisement.Metadata['/'].bytes) | ||||||
const pieceCid = meta.deal?.PieceCID.toString() | ||||||
|
||||||
return { | ||||||
previousAdvertisementCid, | ||||||
pieceCid, | ||||||
payloadCid | ||||||
return { | ||||||
previousAdvertisementCid, | ||||||
pieceCid, | ||||||
payloadCid | ||||||
} | ||||||
} catch (err) { | ||||||
if (err && typeof err === 'object' && 'statusCode' in err && err.statusCode === 404) { | ||||||
// The index provider cannot find the advertised entries. We cannot do much about that, | ||||||
// it's unlikely that further request will succeed. Let's skip this advertisement. | ||||||
debug( | ||||||
'Cannot fetch ad %s entries %s: %s %s', | ||||||
advertisementCid, | ||||||
entriesCid, | ||||||
err.statusCode, | ||||||
/** @type {any} */(err).serverMessage ?? '<not found>' | ||||||
) | ||||||
return { | ||||||
|
||||||
entriesFetchError: true, | ||||||
|
entriesFetchError: true, | |
entriesFetchError: String(err.statusCode), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was just looking up this property, as was assuming it's one of these
- an
Error
- an array of entries for which there was a fetch error
- the count of entries for which there was a fetch error
What about entriesFetchError: err
? Or otherwise hasEntriesFetchError: true
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { once } from 'node:events' | ||
import http from 'node:http' | ||
|
||
/** | ||
* @param {http.RequestListener} handler | ||
*/ | ||
export async function givenHttpServer (handler) { | ||
const server = http.createServer((req, res) => { | ||
;(async () => { | ||
await handler(req, res) | ||
})().catch(err => { | ||
juliangruber marked this conversation as resolved.
Show resolved
Hide resolved
|
||
console.log('Unhandled server error:', err) | ||
res.statusCode = 500 | ||
res.write(err.message || err.toString()) | ||
res.end() | ||
}) | ||
}) | ||
|
||
server.listen(0, '127.0.0.1') | ||
server.unref() | ||
await once(server, 'listening') | ||
const serverPort = /** @type {import('node:net').AddressInfo} */(server.address()).port | ||
const serverUrl = `http://127.0.0.1:${serverPort}/` | ||
return { server, serverPort, serverUrl } | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is
entriesFetchError
plural andentry
singular?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me explain how this works:
So, the error happens when we are fetching entries, but then we return only a single entry.