fetchImage :: ImageCache -> Double -> B.ByteString -> IO (Maybe CacheEntry)
fetchImage ic tick uri = do
    r <- atomically $ do
        cache <- readTVar (icCacheEntries ic)
        case LBM.lookup uri cache of
            (_,      Nothing) -> addRequest >> return Nothing -- New image, add request
            (cache', e@(Just (CacheError retryTick _))) -> do
                when (tick > retryTick)
                    -- Time to retry this failed fetch, add to fetch queue. Note that we don't
                    -- remove the error from the cache, we want to keep the retry count around
                    addRequest
                writeTVar (icCacheEntries ic) cache' -- Update LRU
                return e
            (cache', e) -> -- Hit, just update LRU
                           writeTVar (icCacheEntries ic) cache' >> return e
    case r of
        Just _  -> incCacheMemHits ic
        Nothing -> return ()
    return r
  where addRequest = modifyTVar' (icOutstandingReq ic) (fst . LBM.insert uri ())
fetchImage :: ImageCache -> Double -> B.ByteString -> IO (Maybe CacheEntry)
fetchImage ic tick uri = do
    r <- atomically $ do
        cache <- readTVar (icCacheEntries ic)
        case LBM.lookup uri cache of
            (_,      Nothing) -> addRequest >> return Nothing -- New image, add request
            (cache', e@(Just (CacheError retryTick _))) -> do
                when (tick > retryTick)
                    -- Time to retry this failed fetch, add to fetch queue. Note that we don't
                    -- remove the error from the cache, we want to keep the retry count around
                    addRequest
                writeTVar (icCacheEntries ic) cache' -- Update LRU
                return e
            (cache', e) -> -- Hit, just update LRU
                           writeTVar (icCacheEntries ic) cache' >> return e
    case r of
        Just _  -> incCacheMemHits ic
        Nothing -> return ()
    return r
  where addRequest = modifyTVar' (icOutstandingReq ic) (fst . LBM.insert uri ())
fetchImage ic tick uri = do
    r <- atomically $ do
        cache <- readTVar (icCacheEntries ic)
        case LBM.lookup uri cache of
            (_,      Nothing) -> addRequest >> return Nothing -- New image, add request
            (cache', e@(Just (CacheError retryTick _))) -> do
                when (tick > retryTick)
                    -- Time to retry this failed fetch, add to fetch queue. Note that we don't
                    -- remove the error from the cache, we want to keep the retry count around
                    addRequest
                writeTVar (icCacheEntries ic) cache' -- Update LRU
                return e
            (cache', e) -> -- Hit, just update LRU
                           writeTVar (icCacheEntries ic) cache' >> return e
    case r of
        Just _  -> incCacheMemHits ic
        Nothing -> return ()
    return r
  where addRequest = modifyTVar' (icOutstandingReq ic) (fst . LBM.insert uri ())