yesodweb / yesodweb/persistent
insertBy is not atomic
Nobody has claimed this yet.
- Dominant language
- Haskell
- Stars
- 486
- Forks
- 306
- PR merge metrics
- No merged PRs in 30d
Description
I'm using postgres 11.
insertBy function is supposed to return Left old in case where row with given unique key already exists, or Right new in case where given new record has been inserted. But in some cases, where insertBy is applied from different threads - it just not working this way, it's throwing runtime exception instead, because insert part of insertBy always assumes that record does not exist, which might be not true in case of mutithreading where second thread did insert right after first thread checked row existence. The problem there is that insertBy is not atomic, it's sequential composition of 2 functions - select and then maybe insert:
insertBy val = do
res <- getByValue val
case res of
Nothing -> Right `liftM` insert val
Just z -> return $ Left z
For some databases like postgres atomicity of inserts can be achieved with expressions like ON CONFLICT. Actually it's already used for atomic upsert function. Can insertBy be improved similar way? Or maybe there is working alternative already?
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading the existing insertBy implementation and the upsert implementation, then compare their behavior under concurrent PostgreSQL inserts. Check how getByValue, insert, and PostgreSQL ON CONFLICT interact, and define the expected Left/Right result for competing threads. Done means insertBy handles an existing or concurrently inserted unique key without a runtime exception.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- haskell, postgresql
- Domain
- databases
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100