Snap:在处理程序中捕获 snaplet-postgresql-simple 异常

Snap: catch snaplet-postgresql-simple exception in handler

我正在努力捕捉我的处理程序中的 postgressq 错误。下面是一个简化的例子。

import qualified Control.Monad.CatchIO as CI (try,MonadCatchIO)
import qualified Snap.Snaplet.PostgresqlSimple as D

logConfirmMessages' :: ConfirmLog -> Handler App (AuthManager App) ()
logConfirmMessages' ms = do
  let (s,i,d) = ms
  let log =  T.unpack s ++ "," ++ T.unpack i ++ "," ++ show d ++ ","

  result <- liftIO $ 
              CI.try $ 
                (D.execute "update cr_trades set status=? where email=? and trade_dt=?" ms) 
                  :: Handler App (AuthManager App)  (Either D.SqlError Int64)

  case result of
    Left e -> logTNmsg $ log ++ show e
    Right r -> logTNmsg $ log ++ show r

我得到的错误是:

    * No instance for (D.HasPostgres IO)
        arising from a use of `D.execute'
    * In the second argument of `($)', namely
        `(D.execute
            "update cr_trades set status=? where email=? and trade_dt=?" ms)'
      In the second argument of `($)', namely
        `CI.try
           $ (D.execute
                "update cr_trades set status=? where email=? and trade_dt=?" ms)'
      In a stmt of a 'do' block:
        result <- liftIO
                    $ CI.try
                        $ (D.execute
                             "update cr_trades set status=? where email=? and trade_dt=?" ms) ::
                    Handler App (AuthManager App) (Either D.SqlError Int64)

有什么指点吗?提前致谢。

使用 liftPG' 获取 postgres 连接,以及用于 execute:

的 postgresql-simple 原语
import qualified Data.PostgreSQL.Simple as PG

D.liftPG' $ \conn -> CI.try @PG.SqlError $ PG.execute conn "update blah blah" ms

PG.SqlErrorD.SqlError是同一个实体,只是名称不同。)

你或许可以用一个 HasPostgres 实例来编写一个合适的 exception-y monad,使这个模式更方便。