Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make thread-safe wrapper around getStmtConn. #982

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

merijn
Copy link
Contributor

@merijn merijn commented Nov 5, 2019

Refer to #981.

, stmtQuery = \x -> do
liftIO $ do
active <- readIORef iactive
when (not active) . throwIO $ StatementAlreadyFinalized sql
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check is basically useless, we can instead rely on the MVar to track if the query is alive and "refresh" it if someone tries to use it again, but this complicates the Acquire logic and I'm too tired to fix it right now.

@merijn
Copy link
Contributor Author

merijn commented Nov 5, 2019

Running concurrent queries is threadsafe and works with this PR, but concurrent inserts result in utter garbage due to the two stage ROWID based method of returning the key that was just inserted (for SQLite and presumably the same of MySQL).

@parsonsmatt
Copy link
Collaborator

Thanks for all the work on this stuff. I'll try to get to it soon!

@parsonsmatt
Copy link
Collaborator

This change in behavior is complicated enough that I'd want to gate it behind a major version bump, which means I also want to collect other breaking changes into a big release.

I could be convinced to release it as a patch version, but only with sufficient testing or correctness guarantees. I'd hate to release a version and have someone's application deadlock unexpectedly. However, if there application would have otherwise blown up or done something bad, then I might be okay with it too.

@merijn
Copy link
Contributor Author

merijn commented Dec 28, 2019

Yeah, this PR was/is more of a proof-of-concept/starting point

@parsonsmatt parsonsmatt added this to the 2.11 milestone Jan 28, 2020
@parsonsmatt
Copy link
Collaborator

@merijn Now that it's the new year, how are you feeling about this? I've reviewed it a few times and I feel good about the change.

@merijn
Copy link
Contributor Author

merijn commented Jan 28, 2020

I think this one is still a bit dicy, since as I commented before concurrent inserts basically corrupt the "safe" keys you get back. I think it can be made to work, but it might require overhauling the way inserts are done in all the SQL backend, so that's quite some work.

@parsonsmatt
Copy link
Collaborator

@merijn Do you think you'll have time to do this in the next week or two?

I'm happy to accept an improvement to the status quo, even if it doesn't completely solve the problem, provided that the remaining issues can be documented.

@ygale
Copy link

ygale commented Mar 31, 2020

I am opposed to merging this PR.

This is a breaking change for all persistent users to implement a backend-specific feature. Please implement this as part of the SQLite backend, not as part of persistent.

@merijn
Copy link
Contributor Author

merijn commented Mar 31, 2020

This PR (as is) can't be merged, since it doesn't actually work on any backend and I don't have time to get things working anytime soon. That said, this is also wrong:

to implement a backend-specific feature.

I haven't tested to confirm, but I can't see a way the current implementation isn't broken for all persistent backends. Now, admittedly the other backends rely on connection pools more, so are less likely to run into breakage as they don't run into issues with concurrent queries from separate threads. However, that's not all that's broken, running multiple queries in a conduit from the same thread is also horribly broken, and half the ConduitT based API in persistent will happily leak unfinished queries wasting memory in the database.

@ygale
Copy link

ygale commented Mar 31, 2020

You are referring to the selectSource family of methods, I suppose. Hmm, those are indeed problematic. But the prepared statement cache is not the issue for most backends, and changing it won't help. There needs to be a way to block re-use of a connection until the active query finishes. This is not a simple problem.

EDIT: Moving discussion back to the issue.

@parsonsmatt parsonsmatt modified the milestones: 2.11, 3.0 Sep 18, 2020
@codygman
Copy link
Contributor

codygman commented Mar 3, 2021

There needs to be a way to block re-use of a connection until the active query finishes. This is not a simple problem.

My team is affected by this and it results in the postgres error:

libpq: failed (another command is already in progress

From code like:

withDB1
  . Conduit.runConduit
  $ (Persist.selectSource [] [] .| Conduit.mapM_
      (\stuff ->
        runMyMonadT env . withDB2 . void $ Persist.upsert myModel)
    )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants