popRequestStack :: ImageCache
                -> IO (B.ByteString, Int) -- Return URI and the retry attempt number we're on
popRequestStack ic = do
    let pop = atomically $ do
          requests <- readTVar $ icOutstandingReq ic
          let (requests', maybeURI) = LBM.popNewest requests
          case maybeURI of
              Just (uri, ()) ->
                  do -- Write the stack with the removed top item back
                     writeTVar (icOutstandingReq ic) requests'
                     -- Check if the request is already in the cache
                     cache <- readTVar $ icCacheEntries ic
                     case LBM.lookupNoLRU uri cache of
                         Nothing -> do
                             -- New request, mark fetch status and return URI
                             writeTVar (icCacheEntries ic) .
                                 fst $ LBM.insert uri Fetching cache
                             return $ Just (uri, 0) -- No retries
                         Just (CacheError _ retryAttempt) -> do
                             -- Marked as an error in the cache, update to fetching and
                             -- return current retry attempt
                             writeTVar (icCacheEntries ic) $ LBM.update uri Fetching cache
                             return $ Just (uri, retryAttempt)
                         Just entry -> -- TODO: Maybe just commit transaction and trace instead?
                                       error $ "popRequestStack internal error: '"
                                           ++ B8.unpack uri ++ "' in request queue, but already "
                                           ++ "marked as '" ++ (show entry) ++ "' in cache"
              Nothing        -> retry -- Empty request list, block till it makes sense to retry
    r <- pop
    case r of
        Nothing  -> popRequestStack ic -- Recurse till we get a URI or block on retry
        Just res -> return res

-- File or HTTP?
popRequestStack :: ImageCache
                -> IO (B.ByteString, Int)
popRequestStack ic = do
    let pop = atomically $ do
          requests <- readTVar $ icOutstandingReq ic
          let (requests', maybeURI) = LBM.popNewest requests
          case maybeURI of
              Just (uri, ()) ->
                  do -- Write the stack with the removed top item back
                     writeTVar (icOutstandingReq ic) requests'
                     -- Check if the request is already in the cache
                     cache <- readTVar $ icCacheEntries ic
                     case LBM.lookupNoLRU uri cache of
                         Nothing -> do
                             -- New request, mark fetch status and return URI
                             writeTVar (icCacheEntries ic) .
                                 fst $ LBM.insert uri Fetching cache
                             return $ Just (uri, 0) -- No retries
                         Just (CacheError _ retryAttempt) -> do
                             -- Marked as an error in the cache, update to fetching and
                             -- return current retry attempt
                             writeTVar (icCacheEntries ic) $ LBM.update uri Fetching cache
                             return $ Just (uri, retryAttempt)
                         Just entry -> -- TODO: Maybe just commit transaction and trace instead?
                                       error $ "popRequestStack internal error: '"
                                           ++ B8.unpack uri ++ "' in request queue, but already "
                                           ++ "marked as '" ++ (show entry) ++ "' in cache"
              Nothing        -> retry -- Empty request list, block till it makes sense to retry
    r <- pop
    case r of
        Nothing  -> popRequestStack ic -- Recurse till we get a URI or block on retry
        Just res -> return res

-- File or HTTP?
popRequestStack ic = do
    let pop = atomically $ do
          requests <- readTVar $ icOutstandingReq ic
          let (requests', maybeURI) = LBM.popNewest requests
          case maybeURI of
              Just (uri, ()) ->
                  do -- Write the stack with the removed top item back
                     writeTVar (icOutstandingReq ic) requests'
                     -- Check if the request is already in the cache
                     cache <- readTVar $ icCacheEntries ic
                     case LBM.lookupNoLRU uri cache of
                         Nothing -> do
                             -- New request, mark fetch status and return URI
                             writeTVar (icCacheEntries ic) .
                                 fst $ LBM.insert uri Fetching cache
                             return $ Just (uri, 0) -- No retries
                         Just (CacheError _ retryAttempt) -> do
                             -- Marked as an error in the cache, update to fetching and
                             -- return current retry attempt
                             writeTVar (icCacheEntries ic) $ LBM.update uri Fetching cache
                             return $ Just (uri, retryAttempt)
                         Just entry -> -- TODO: Maybe just commit transaction and trace instead?
                                       error $ "popRequestStack internal error: '"
                                           ++ B8.unpack uri ++ "' in request queue, but already "
                                           ++ "marked as '" ++ (show entry) ++ "' in cache"
              Nothing        -> retry -- Empty request list, block till it makes sense to retry
    r <- pop
    case r of
        Nothing  -> popRequestStack ic -- Recurse till we get a URI or block on retry
        Just res -> return res

-- File or HTTP?