packages feed

prodapi-proxy-0.1.0.0: src/Prod/Proxy/Lookups.hs

module Prod.Proxy.Lookups where

import Control.Monad (when)

import Data.ByteString (ByteString)
import Data.Maybe (isJust)
import Data.Text (Text)
import qualified Data.Text.Encoding as Text
import System.Random.Shuffle (shuffleM)

import Prod.Health (Readiness (..))
import Prod.Proxy.Base

-- | Lookup that always fails.
noBackend :: LookupHostPort
noBackend = const (pure Nothing)

-- | Lookup that always returns the same value.
constBackend :: (Host, Port) -> LookupHostPort
constBackend hp = const (pure $ Just hp)

-- | Lookup the first backend among a generated list.
firstBackend :: IO [(Host, Port)] -> LookupHostPort
firstBackend disc =
    const f
  where
    f :: IO (Maybe (Host, Port))
    f = safeHead <$> disc

    safeHead :: [a] -> Maybe a
    safeHead (x : _) = Just x
    safeHead _ = Nothing

-- | Picks a random backend among a generated list.
randomBackend :: IO [(Host, Port)] -> LookupHostPort
randomBackend disc = firstBackend (disc >>= shuffleM)

-- | Fallbacks to the second lookup function if the first fails.
fallback :: LookupHostPort -> LookupHostPort -> LookupHostPort
fallback l1 l2 = \req -> do
    o1 <- l1 req
    case o1 of
        Nothing -> l2 req
        Just _ -> pure o1

-- | Decorates successful lookups with an action.
decorateSuccessWith :: ((Host, Port) -> IO ()) -> LookupHostPort -> LookupHostPort
decorateSuccessWith f l1 = \req -> do
    o1 <- l1 req
    case o1 of
        Nothing -> pure ()
        Just hp -> f hp
    pure o1