Skip to content

Commit

Permalink
Add content verification + retries for metadata writes (#3436)
Browse files Browse the repository at this point in the history
* Add content verification + retries for metadata writes

* Lint

* Rename

* Typo
  • Loading branch information
dmanjunath committed Jul 15, 2022
1 parent 32f858c commit 74e7679
Showing 1 changed file with 31 additions and 2 deletions.
33 changes: 31 additions & 2 deletions creator-node/src/fileManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const EMPTY_FILE_CID = 'QmbFMke1KXqnYyBBWxB74N4c5SBnJMVAiMNRcGu6x1AwQH' // deter
/**
* Saves file to disk under /multihash name
*/
async function saveFileFromBufferToDisk(req, buffer) {
async function saveFileFromBufferToDisk(req, buffer, numRetries = 5) {
// Make sure user has authenticated before saving file
if (!req.session.cnodeUserUUID) {
throw new Error('User must be authenticated to save a file')
Expand All @@ -39,6 +39,35 @@ async function saveFileFromBufferToDisk(req, buffer) {
const dstPath = DiskManager.computeFilePath(cid)
await fs.writeFile(dstPath, buffer)

// verify that the contents of the file match the file's cid
try {
const fileSize = (await fs.stat(dstPath)).size
const fileIsEmpty = fileSize === 0
// there is one case where an empty file could be valid, check for that CID explicitly
if (fileIsEmpty && cid !== EMPTY_FILE_CID) {
throw new Error(`File has no content, content length is 0: ${cid}`)
}

const expectedCID = await LibsUtils.fileHasher.generateNonImageCid(
dstPath,
genericLogger.child(req.logContext)
)
if (cid !== expectedCID) {
// delete this file because the next time we run sync and we see it on disk, we'll assume we have it and it's correct
throw new Error(
`File contents don't match their expected CID. CID: ${cid} expected CID: ${expectedCID}`
)
}
} catch (e) {
await removeFile(dstPath)
if (numRetries > 0) {
return saveFileFromBufferToDisk(req, buffer, numRetries - 1)
}
throw new Error(
`saveFileFromBufferToDisk - Error during content verification for multihash ${cid} ${e.message}`
)
}

return { cid, dstPath }
}

Expand Down Expand Up @@ -358,7 +387,7 @@ async function saveFileForMultihashToFS(
})
// delete this file because the next time we run sync and we see it on disk, we'll assume we have it and it's correct
throw new Error(
`File contents don't their expected CID. CID: ${multihash} expected CID: ${expectedCid}`
`File contents don't match their expected CID. CID: ${multihash} expected CID: ${expectedCid}`
)
}
decisionTree.push({
Expand Down

0 comments on commit 74e7679

Please sign in to comment.