Skip to content

Instantly share code, notes, and snippets.

@snoyberg
Created January 7, 2012 21:34
Show Gist options
  • Select an option

  • Save snoyberg/1576120 to your computer and use it in GitHub Desktop.

Select an option

Save snoyberg/1576120 to your computer and use it in GitHub Desktop.
{-# LANGUAGE FlexibleContexts #-}
import Database.Persist.Sqlite
import Control.Concurrent.MVar
import Control.Concurrent.Chan
import Control.Concurrent.Lifted (fork)
import Control.Monad.Base (liftBase)
import Control.Monad.Trans.Control (MonadBaseControl)
import Control.Monad (forever)
import Control.Monad.IO.Class (MonadIO)
newtype Future a = Future (MVar a)
readFuture (Future m) = readMVar m
newtype ActionQueue m = ActionQueue (Chan (SqlPersist m ()))
startActionThread :: (MonadIO m, MonadBaseControl IO m)
=> Connection
-> m (ActionQueue m)
startActionThread conn = do
chan <- liftBase newChan
fork $ flip runSqlConn conn $ forever $ do
action <- liftBase $ readChan chan
action
return $ ActionQueue chan
addAction :: MonadBaseControl IO m
=> ActionQueue m
-> SqlPersist m a
-> m (Future a)
addAction (ActionQueue chan) action = do
mvar <- liftBase newEmptyMVar
let fullAction = do
x <- action
liftBase $ putMVar mvar x
liftBase $ writeChan chan fullAction
return $ Future mvar
@meteficha

Copy link
Copy Markdown

Why not forever $ flip runSqlConn conn $ do?

@snoyberg

snoyberg commented Jan 8, 2012

Copy link
Copy Markdown
Author

Doh! I meant to put in exactly that! Of course that's a much better idea, since you don't constantly destroy and creating the same monad. Though I'm not sure how inefficient that is with ReaderT, it's definitely worth fixing. Can you mention this to Rian on the list?

@meteficha

Copy link
Copy Markdown

What do you mean by "destroy and create"? Using forever on the outside will call runSqlConn many times instead of just once. I just thought that when an error occurs, you can't just catch the exception and continue, you need another transaction. So with a single runSqlConn it would stop working after the first DB error.

@snoyberg

snoyberg commented Jan 8, 2012

Copy link
Copy Markdown
Author

I'm completely turned around here, sorry, my comment made absolutely no sense. I'm a bit more awake now.

Yes, you're correct, we should flip the order so we get proper transaction handling and exception cleanup. I was getting at the fact that doing so is less efficient, but clearly is necessary in that case.

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