forked from nftstorage/nft.storage-tools
-
Notifications
You must be signed in to change notification settings - Fork 0
/
status.js
113 lines (102 loc) · 3.29 KB
/
status.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/**
* Pretty print the pin status of all the CIDs in the passed pinlist file.
*
* Usage:
* node status.js pinlist.txt
*/
import fs from 'fs'
import ora from 'ora'
import { pipeline } from 'stream/promises'
import dotenv from 'dotenv'
import * as d3 from 'd3-format'
import { NFTStorage } from 'nft.storage'
import batch from 'it-batch'
import split from './lib/split.js'
dotenv.config()
const format = d3.format(',')
const CONCURRENCY = 1000
async function main () {
if (!process.env.API_KEY) {
throw new Error('missing nft.storage API key')
}
const filePath = process.argv[2]
if (!filePath) {
throw new Error('missing path to newline delimited CID list')
}
const endpoint = process.env.ENDPOINT || 'https://api.nft.storage'
console.log(`🔌 Using endpoint: ${endpoint}`)
const store = new NFTStorage({ token: process.env.API_KEY, endpoint })
const spinner = ora()
const start = Date.now()
const totals = { total: 0, queued: 0, pinning: 0, pinned: 0, failed: 0, unknown: 0, requests: 0, reqsPerSec: 0 }
const retryables = { failed: [], unknown: [] }
spinner.start()
try {
await pipeline(
fs.createReadStream(filePath),
split,
cids => batch(cids, CONCURRENCY),
async batchedCids => {
for await (const cids of batchedCids) {
await Promise.all(cids.map(async cid => {
try {
const { pin } = await store.status(cid)
totals[pin.status]++
if (pin.status === 'failed') {
retryables.failed.push(cid)
}
} catch (err) {
if (err.message.contains('not found')) {
totals.unknown++
retryables.unknown.push(cid)
} else {
throw err
}
} finally {
totals.total++
totals.requests++
totals.reqsPerSec = totals.requests / ((Date.now() - start) / 1000)
}
spinner.text = toText('Loading...', totals)
}))
}
}
)
} catch (err) {
spinner.stopAndPersist({ text: toText('Errored', totals) })
spinner.fail(`Error: ${err.message}`)
throw err
}
spinner.succeed(toText('Complete!', totals))
if (retryables.failed.length) {
console.log('\n💀 Failed CIDs:')
retryables.failed.forEach(cid => console.log(cid))
}
if (retryables.unknown.length) {
console.log('\n❓ Unknown CIDs:')
retryables.failed.forEach(cid => console.log(cid))
}
}
const percent = (value, total) => ((value / total) * 100).toFixed()
function toText (prefix, totals) {
const items = [`💖 Total: ${format(totals.total)}`]
if (totals.queued) {
items.push(line('👫 Queued', totals.queued, totals.total))
}
if (totals.pinning) {
items.push(line('⏳ Pinning', totals.pinning, totals.total))
}
if (totals.pinned) {
items.push(line('📌 Pinned', totals.pinned, totals.total))
}
if (totals.failed) {
items.push(line('💀 Failed', totals.failed, totals.total))
}
if (totals.unknown) {
items.push(line('❓ Unknown', totals.unknown, totals.total))
}
items.push(`🔁 Requests/sec: ${totals.reqsPerSec.toFixed(1)}`)
return `${prefix}\n${items.join('\n')}`
}
const line = (prefix, value, total) => `${prefix}: ${value} (${percent(value, total)}%)`
main()