Skip to content

uniqueSet contains race condition #207

Closed
@marekolszewski

Description

@marekolszewski

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.

Metadata

Metadata

Assignees

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions