Skip to content

Commit d6e4b9f

Browse files
committed
fix: add gateway fetch timeout and signal error when upload has no shards
1 parent 430412c commit d6e4b9f

File tree

3 files changed

+30
-16
lines changed

3 files changed

+30
-16
lines changed

src/lib/migrations/gateway.ts

+22-14
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,27 @@ import { LinkIndexer } from 'linkdex'
66
import { carCode } from './constants'
77
import { Shard } from './api'
88

9-
export const fetchCAR = async (root: UnknownLink): Promise<Shard> => {
10-
const res = await fetch(`https://w3s.link/ipfs/${root}?format=car`)
11-
if (!res.ok) throw new Error('failed to get DAG as CAR', { cause: { status: res.status } })
12-
const bytes = new Uint8Array(await res.arrayBuffer())
13-
// Verify CAR is complete
14-
const iterator = await CarBlockIterator.fromBytes(bytes)
15-
const index = new LinkIndexer()
16-
for await (const block of iterator) {
17-
index.decodeAndIndex(block)
18-
}
19-
if (!index.isCompleteDag()) {
20-
throw new Error('CAR does not contain a complete DAG')
9+
export const fetchCAR = async (root: UnknownLink, options?: { timeout?: number }): Promise<Shard> => {
10+
const controller = new AbortController()
11+
const timeoutID = setTimeout(() => controller.abort(), options?.timeout ?? 30_000)
12+
try {
13+
const res = await fetch(`https://w3s.link/ipfs/${root}?format=car`, { signal: controller.signal })
14+
if (!res.ok) throw new Error('failed to get DAG as CAR', { cause: { status: res.status } })
15+
clearTimeout(timeoutID)
16+
17+
const bytes = new Uint8Array(await res.arrayBuffer())
18+
// Verify CAR is complete
19+
const iterator = await CarBlockIterator.fromBytes(bytes)
20+
const index = new LinkIndexer()
21+
for await (const block of iterator) {
22+
index.decodeAndIndex(block)
23+
}
24+
if (!index.isCompleteDag()) {
25+
throw new Error('CAR does not contain a complete DAG')
26+
}
27+
const link = Link.create(carCode, await sha256.digest(bytes))
28+
return { link, size: async () => bytes.length, bytes: async () => bytes }
29+
} finally {
30+
clearTimeout(timeoutID)
2131
}
22-
const link = Link.create(carCode, await sha256.digest(bytes))
23-
return { link, size: async () => bytes.length, bytes: async () => bytes }
2432
}

src/lib/migrations/index.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,15 @@ export const migrate = async ({
104104
}
105105
}
106106

107+
// signal that this upload failed if it has no shards
108+
if (upload.shards.length === 0) {
109+
await onError(new Error('upload has no shards'), upload)
110+
}
111+
107112
// do no register an upload if not all the shards uploaded successfully
108-
if (!allShardsStored) continue
113+
if (!allShardsStored) {
114+
continue
115+
}
109116

110117
try {
111118
const receipt = await UploadCapabilities.add.invoke({

src/lib/migrations/web3-storage.ts

-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ class Reader {
7676

7777
// Add a synthetic shard that is the entire DAG.
7878
// Attempt to download from gateway.
79-
// TODO: fetch from /complete?
8079
if (!shards.length) {
8180
try {
8281
const shard = await fetchCAR(root)

0 commit comments

Comments
 (0)