Closed
Description
Do you want to request a feature or report a bug?
Bug
What is the current behavior?
When using uniqueSet to set some data at a path, the current code checks first that the path is not set, and then writes to the path using a regular set. Unfortunately, there is a chance that the path gets written two by another client between the check and write, thus creating a race condition.
What is the expected behavior?
There should be no race condition. I believe this code should solve the race condition but I have not tested it:
const uniqueSet = (path, value, onComplete) =>
rootRef.child(path)
.transaction(currentData => {
// Try to set the value if it's currently unset.
if (currentData === null) {
return value
// Otherwise, abort the transaction.
} else {
return undefined
}
}, (error, commited, snapshot) => {
if (!onComplete) return
if (!commited) {
const newError = new Error('Path already exists.')
onComplete(newError)
} else {
onComplete(error)
}
})
.then(({ commited, snapshot }) => {
if (!commited) {
const newError = new Error('Path already exists.')
return Promise.reject(newError)
}
})
Note that there is a bit of fiddling required to return the "Path already exists" error that is currently being returned.