Skip to content
This repository was archived by the owner on Feb 12, 2024. It is now read-only.

Commit 633d870

Browse files
authored
fix: ensure correct progress is reported (#3384)
Fixes a bug where due to parallel file imports, the reported size of ingested bytes was getting mixed up. We now tally imported bytes against the reported file name instead of assuming a sequential import, taking care to not let the tally grow until memory is exhausted.
1 parent 1311160 commit 633d870

File tree

4 files changed

+31
-20
lines changed

4 files changed

+31
-20
lines changed

docs/core-api/FILES.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ An optional object which may have the following keys:
171171
| hashAlg | `String` | `'sha2-256'` | multihash hashing algorithm to use |
172172
| onlyHash | `boolean` | `false` | If true, will not add blocks to the blockstore |
173173
| pin | `boolean` | `true` | pin this object when adding |
174-
| progress | function | `undefined` | a function that will be called with the byte length of chunks as a file is added to ipfs |
174+
| progress | function | `undefined` | a function that will be called with the number of bytes added as a file is added to ipfs and the path of the file being added |
175175
| rawLeaves | `boolean` | `false` | if true, DAG leaves will contain raw file data and not be wrapped in a protobuf |
176176
| trickle | `boolean` | `false` | if true will use the [trickle DAG](https://godoc.org/github.com/ipsn/go-ipfs/gxlibs/github.com/ipfs/go-unixfs/importer/trickle) format for DAG generation |
177177
| wrapWithDirectory | `boolean` | `false` | Adds a wrapping node around the content |
@@ -252,7 +252,7 @@ An optional object which may have the following keys:
252252
| hashAlg | `String` | `'sha2-256'` | multihash hashing algorithm to use |
253253
| onlyHash | `boolean` | `false` | If true, will not add blocks to the blockstore |
254254
| pin | `boolean` | `true` | pin this object when adding |
255-
| progress | function | `undefined` | a function that will be called with the number of bytes added as a file is added to ipfs and the name of the file being added |
255+
| progress | function | `undefined` | a function that will be called with the number of bytes added as a file is added to ipfs and the path of the file being added |
256256
| rawLeaves | `boolean` | `false` | if true, DAG leaves will contain raw file data and not be wrapped in a protobuf |
257257
| shardSplitThreshold | `Number` | `1000` | Directories with more than this number of files will be created as HAMT-sharded directories |
258258
| trickle | `boolean` | `false` | if true will use the [trickle DAG](https://godoc.org/github.com/ipsn/go-ipfs/gxlibs/github.com/ipfs/go-unixfs/importer/trickle) format for DAG generation |

packages/interface-ipfs-core/src/add-all.js

+11-10
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ module.exports = (common, options) => {
140140
})
141141

142142
const emptyDir = (name) => ({ path: `test-folder/${name}` })
143+
const progressSizes = {}
143144

144145
const dirs = [
145146
content('pp.txt'),
@@ -152,20 +153,20 @@ module.exports = (common, options) => {
152153
emptyDir('files/empty')
153154
]
154155

155-
const total = dirs.reduce((i, entry) => {
156-
return i + (entry.content ? entry.content.length : 0)
157-
}, 0)
156+
const total = dirs.reduce((acc, curr) => {
157+
if (curr.content) {
158+
acc[curr.path] = curr.content.length
159+
}
160+
161+
return acc
162+
}, {})
158163

159-
let progCalled = false
160-
let accumProgress = 0
161-
const handler = (p) => {
162-
progCalled = true
163-
accumProgress += p
164+
const handler = (bytes, path) => {
165+
progressSizes[path] = bytes
164166
}
165167

166168
const root = await last(ipfs.addAll(dirs, { progress: handler }))
167-
expect(progCalled).to.be.true()
168-
expect(accumProgress).to.be.at.least(total)
169+
expect(progressSizes).to.deep.equal(total)
169170
expect(root.path).to.equal('test-folder')
170171
expect(root.cid.toString()).to.equal(fixtures.directory.cid)
171172
})

packages/ipfs-core/src/components/add-all/index.js

+17-7
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,19 @@ module.exports = ({ block, gcLock, preload, pin, options: constructorOptions })
6060

6161
delete opts.trickle
6262

63+
const totals = {}
64+
6365
if (opts.progress) {
64-
let total = 0
6566
const prog = opts.progress
6667

67-
opts.progress = (bytes, fileName) => {
68-
total += bytes
69-
prog(total, fileName)
68+
opts.progress = (bytes, path) => {
69+
if (!totals[path]) {
70+
totals[path] = 0
71+
}
72+
73+
totals[path] += bytes
74+
75+
prog(totals[path], path)
7076
}
7177
}
7278

@@ -84,7 +90,12 @@ module.exports = ({ block, gcLock, preload, pin, options: constructorOptions })
8490
const releaseLock = await gcLock.readLock()
8591

8692
try {
87-
yield * iterator
93+
for await (const added of iterator) {
94+
// do not keep file totals around forever
95+
delete totals[added.path]
96+
97+
yield added
98+
}
8899
} finally {
89100
releaseLock()
90101
}
@@ -179,8 +190,7 @@ function pinFile (pin, opts) {
179190
* @property {boolean} [onlyHash=false] - If true, will not add blocks to the
180191
* blockstore.
181192
* @property {boolean} [pin=true] - Pin this object when adding.
182-
* @property {(bytes:number, fileName:string) => void} [progress] - A function that will be
183-
* called with the number of bytes added as a file is added to ipfs and the name of the file being added.
193+
* @property {(bytes:number, path:string) => void} [progress] - a function that will be called with the number of bytes added as a file is added to ipfs and the path of the file being added
184194
* @property {boolean} [rawLeaves=false] - If true, DAG leaves will contain raw
185195
* file data and not be wrapped in a protobuf.
186196
* @property {number} [shardSplitThreshold=1000] - Directories with more than this

packages/ipfs-core/src/components/add.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ module.exports = ({ addAll }) => {
2525
* @property {string} [hashAlg] - multihash hashing algorithm to use (default: `'sha2-256'`)
2626
* @property {boolean} [onlyHash] - If true, will not add blocks to the blockstore (default: `false`)
2727
* @property {boolean} [pin] - pin this object when adding (default: `true`)
28-
* @property {Function} [progress] - a function that will be called with the byte length of chunks as a file is added to ipfs (default: `undefined`)
28+
* @property {(bytes:number, path:string) => void} [progress] - a function that will be called with the number of bytes added as a file is added to ipfs and the path of the file being added
2929
* @property {boolean} [rawLeaves] - if true, DAG leaves will contain raw file data and not be wrapped in a protobuf (default: `false`)
3030
* @property {boolean} [trickle] - if true will use the [trickle DAG](https://godoc.org/github.com/ipsn/go-ipfs/gxlibs/github.com/ipfs/go-unixfs/importer/trickle) format for DAG generation (default: `false`)
3131
* @property {boolean} [wrapWithDirectory] - Adds a wrapping node around the content (default: `false`)

0 commit comments

Comments
 (0)