2014-01-27 4 views
6

Я использую hedis и пытаюсь обработать случай, когда сервер мертв. Согласно документации:Исключения, которые не попадают в «try»

Подключение к серверу потеряно: В случае потери связи, командные функции бросить ConnectionLostException. Его можно поймать только за пределами runRedis.

Поэтому я бы предположил, что хочу поймать ConnectionLostException. Однако, хотя я могу показаться, что поймал его правильно, он, похоже, тоже поднялся на вершину, и я не уверен, почему. Вот код (только работает в GHCI):

:set -XOverloadedStrings 
import Database.Redis 
import Control.Exception 

conn <- connect defaultConnectInfo 
runRedis conn $ ping 

Теперь, если я убить сервер Redis между созданием соединения и выполнить команду, я получаю результат я ожидаю:

& Ланголь; интерактивные и rangle ;: ConnectionLost *** Исключение: ConnectionLost

Так вместо этого я пытаюсь сделать следующее (я добавил >>= evaluate для того, чтобы попытаться заставить оценку ошибки, но это не имеет никакого значения):

let tryR = try :: IO a -> IO (Either ConnectionLostException a) 
tryR . (>>= evaluate) . runRedis conn $ ping 

Это дает мне:

Left Con: ConnectionLost nectionLost

Так я получаю Left результат, как и следовало ожидать, но на полпути, за исключением также предположительно поимки и отображается GHCI. Это проблема с не оцененными вещами?

+3

Я не понимаю. Кажется, что все работает правильно для меня: вы превратили исключение в легко проверяемое значение «Либо». Что бы вы ожидали вместо этого? –

+1

Мне кажется, что redis-пакет печатает строку о том, что соединение теряется в дополнение к исключению. –

+0

@ DanielWagner Я конвертирую исключение, но все же (насколько я могу судить), видя, что он обрабатывается GHCI, как будто его все еще бросают. Если это не так, как говорит JohnL, и redis сам печатает сообщение. – Impredicative

ответ

1

Как Джон намекнул, кажется, что что-то напечатало это сообщение до stderr.

Рассмотрим следующий пример:

{-# LANGUAGE OverloadedStrings #-} 

import Control.Concurrent (threadDelay) 
import Control.Exception 
import Control.Monad 
import Database.Redis 
import System.Mem 

tryR :: IO a -> IO (Either ConnectionLostException a) 
tryR = try 


main :: IO() 
main = do 
    conn <- connect defaultConnectInfo 
    loop conn 
    putStrLn $ "exiting gracefully after counting up some numbers" 
    performGC 
    forM_ [1..10] $ \i -> do 
    print i 
    threadDelay 10000 -- 0.05 seconds 
    where 
    loop conn = do 

     e <- tryR . (>>= evaluate) . runRedis conn $ ping 

     case e of 
     Right x -> do print x 
         threadDelay 1000000 
         loop conn 
     Left err -> do putStrLn $ "tryR caught exception: " ++ show err 

Он печатает:

Right Pong 
Right Pong <-------------- after this I Ctrl-C the redis server 
tryR caught exception: ConnectionLost 
exiting gracefully after counting up some numbers 
1 
test: ConnectionLost 
2 
3 
4 
5 
6 
7 
8 
9 
10 

Это выглядит как-то в стеке печати этот test: ConnectionLost (или test.hs: ConnectionLost если вы используете GHCI/runghc) асинхронно.

Если это GHC, это, вероятно, ошибка, но шансы высоки - это hedis или одна из его зависимостей (я еще не нашел ее в hedis).

+0

Также рассмотрите вопрос об открытии проблемы для [hedis] (https://github.com/informatikr/hedis/issues), чтобы уточнить, является ли это hedis или одной из его зависимостей. – nh2

Смежные вопросы