Параллельный пул соединения с БД в Haskell

При использовании MFC можно использовать управляемый С++ CString

CString nameAge = "";
nameAge.Format("%s%d", "John", 21);

, также имеет строковое средство форматирования .

10
задан Daniel Trebbien 3 October 2011 в 21:21
поделиться

1 ответ

ВОПРОС 2: Я никогда не использовал HDBC, но, вероятно, напишу что-то вроде это.

trySql :: Connection -> (Connection -> IO a) -> IO a
trySql conn f = handleSql catcher $ do
    r <- f conn
    commit conn
    return r
  where catcher e = rollback conn >> throw e

Откройте соединение где-нибудь за пределами функции и не отключайте его внутри функции.

ВОПРОС 1: Хм, пул соединений не кажется таким сложным реализовать ...

import Control.Concurrent
import Control.Exception

data Pool a =
    Pool { poolMin :: Int, poolMax :: Int, poolUsed :: Int, poolFree :: [a] }

newConnPool low high newConn delConn = do
    cs <- handleSqlError . sequence . replicate low newConn
    mPool <- newMVar $ Pool low high 0 cs
    return (mPool, newConn, delConn)

delConnPool (mPool, newConn, delConn) = do
    pool <- takeMVar mPool
    if length (poolFree pool) /= poolUsed pool
      then putMVar mPool pool >> fail "pool in use"
      else mapM_ delConn $ poolFree pool

takeConn (mPool, newConn, delConn) = modifyMVar mPool $ \pool ->
    case poolFree pool of
        conn:cs ->
            return (pool { poolUsed = poolUsed pool + 1, poolFree = cs }, conn)
        _ | poolUsed pool < poolMax pool -> do
            conn <- handleSqlError newConn
            return (pool { poolUsed = poolUsed pool + 1 }, conn)
        _ -> fail "pool is exhausted"

putConn (mPool, newConn, delConn) conn = modifyMVar_ mPool $ \pool ->
    let used = poolUsed pool in
    if used > poolMin conn
      then handleSqlError (delConn conn) >> return (pool { poolUsed = used - 1 })
      else return $ pool { poolUsed = used - 1, poolFree = conn : poolFree pool }

withConn connPool = bracket (takeConn connPool) (putConn conPool)

Тебе, наверное, не стоит воспринимать это дословно, как я не знаю 'Я даже не тестировал его при компиляции (и fail там довольно недружелюбно), но идея состоит в том, чтобы сделать что-то вроде

connPool <- newConnPool 0 50 (connectSqlite3 "user.db") disconnect

и передать connPool по мере необходимости.

9
ответ дан 3 December 2019 в 15:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: