Skip to content
This repository was archived by the owner on Mar 23, 2023. It is now read-only.

fix: handle concurrent writes on windows #28

Merged
merged 1 commit into from
Sep 9, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const fs = require('fs')
const glob = require('glob')
const mkdirp = require('mkdirp')
const promisify = require('util').promisify
const writeFile = promisify(require('fast-write-atomic'))
const writeAtomic = promisify(require('fast-write-atomic'))
const path = require('path')

const filter = require('interface-datastore').utils.filter
Expand All @@ -22,6 +22,26 @@ const fsUnlink = promisify(fs.unlink || noop)
const Key = IDatastore.Key
const Errors = IDatastore.Errors

async function writeFile (path, contents) {
try {
await writeAtomic(path, contents)
} catch (err) {
if (err.code === 'EPERM' && err.syscall === 'rename') {
// fast-write-atomic writes a file to a temp location before renaming it.
// On Windows, if the final file already exists this error is thrown.
// No such error is thrown on Linux/Mac
// Make sure we can read & write to this file
await fsAccess(path, fs.constants.F_OK | fs.constants.W_OK)

// The file was created by another context - this means there were
// attempts to write the same block by two different function calls
return
}

throw err
}
}

/**
* A datastore backed by the file system.
*
Expand Down
15 changes: 15 additions & 0 deletions test/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,4 +172,19 @@ describe('FsDatastore', () => {
}
})
})

it('can survive concurrent writes', async () => {
const dir = utils.tmpdir()
const fstore = new FsStore(dir)
const key = new Key('CIQGFTQ7FSI2COUXWWLOQ45VUM2GUZCGAXLWCTOKKPGTUWPXHBNIVOY')
const value = Buffer.from('Hello world')

await Promise.all(
new Array(100).fill(0).map(() => fstore.put(key, value))
)

const res = await fstore.get(key)

expect(res).to.deep.equal(value)
})
})