module Database.CQL.IO.Settings where
import Control.Lens hiding ((<|))
import Control.Retry hiding (retryPolicy)
import Data.List.NonEmpty (NonEmpty (..), (<|))
import Data.Monoid
import Data.Time
import Data.Word
import Database.CQL.Protocol
import Database.CQL.IO.Connection
import Database.CQL.IO.Cluster.Policies (Policy, random)
import Database.CQL.IO.Connection as C
import Database.CQL.IO.Pool as P
import Database.CQL.IO.Types (Milliseconds (..))
import Network.Socket (PortNumber (..))
import OpenSSL.Session (SSLContext)
import Prelude
data PrepareStrategy
= EagerPrepare
| LazyPrepare
deriving (Eq, Ord, Show)
data RetrySettings = RetrySettings
{ _retryPolicy :: !(forall m. Monad m => RetryPolicyM m)
, _reducedConsistency :: !(Maybe Consistency)
, _sendTimeoutChange :: !Milliseconds
, _recvTimeoutChange :: !Milliseconds
}
data Settings = Settings
{ _poolSettings :: !PoolSettings
, _connSettings :: !ConnectionSettings
, _retrySettings :: !RetrySettings
, _protoVersion :: !Version
, _portnumber :: !PortNumber
, _contacts :: !(NonEmpty String)
, _policyMaker :: !(IO Policy)
, _prepStrategy :: !PrepareStrategy
}
makeLenses ''RetrySettings
makeLenses ''Settings
defSettings :: Settings
defSettings = Settings
P.defSettings
C.defSettings
noRetry
V3
(fromInteger 9042)
("localhost" :| [])
random
LazyPrepare
setProtocolVersion :: Version -> Settings -> Settings
setProtocolVersion v = set protoVersion v
setContacts :: String -> [String] -> Settings -> Settings
setContacts v vv = set contacts (v :| vv)
addContact :: String -> Settings -> Settings
addContact v = over contacts (v <|)
setPortNumber :: PortNumber -> Settings -> Settings
setPortNumber v = set portnumber v
setPolicy :: IO Policy -> Settings -> Settings
setPolicy v = set policyMaker v
setPrepareStrategy :: PrepareStrategy -> Settings -> Settings
setPrepareStrategy v = set prepStrategy v
setIdleTimeout :: NominalDiffTime -> Settings -> Settings
setIdleTimeout v = set (poolSettings.idleTimeout) v
setMaxConnections :: Int -> Settings -> Settings
setMaxConnections v = set (poolSettings.maxConnections) v
setPoolStripes :: Int -> Settings -> Settings
setPoolStripes v s
| v < 1 = error "cql-io settings: stripes must be greater than 0"
| otherwise = set (poolSettings.poolStripes) v s
setMaxTimeouts :: Int -> Settings -> Settings
setMaxTimeouts v = set (poolSettings.maxTimeouts) v
setCompression :: Compression -> Settings -> Settings
setCompression v = set (connSettings.compression) v
setMaxStreams :: Int -> Settings -> Settings
setMaxStreams v s = case s^.protoVersion of
V2 | v < 1 || v > 128 -> error "cql-io settings: max. streams must be within [1, 128]"
V3 | v < 1 || v > 32768 -> error "cql-io settings: max. streams must be within [1, 32768]"
_ -> set (connSettings.maxStreams) v s
setConnectTimeout :: NominalDiffTime -> Settings -> Settings
setConnectTimeout v = set (connSettings.connectTimeout) (Ms $ round (1000 * v))
setSendTimeout :: NominalDiffTime -> Settings -> Settings
setSendTimeout v = set (connSettings.sendTimeout) (Ms $ round (1000 * v))
setResponseTimeout :: NominalDiffTime -> Settings -> Settings
setResponseTimeout v = set (connSettings.responseTimeout) (Ms $ round (1000 * v))
setKeyspace :: Keyspace -> Settings -> Settings
setKeyspace v = set (connSettings.defKeyspace) (Just v)
setRetrySettings :: RetrySettings -> Settings -> Settings
setRetrySettings v = set retrySettings v
setMaxRecvBuffer :: Int -> Settings -> Settings
setMaxRecvBuffer v = set (connSettings.maxRecvBuffer) v
setSSLContext :: SSLContext -> Settings -> Settings
setSSLContext v = set (connSettings.tlsContext) (Just v)
noRetry :: RetrySettings
noRetry = RetrySettings (RetryPolicyM $ const (return Nothing)) Nothing 0 0
retryForever :: RetrySettings
retryForever = RetrySettings mempty Nothing 0 0
maxRetries :: Word -> RetrySettings -> RetrySettings
maxRetries v s =
s { _retryPolicy = limitRetries (fromIntegral v) <> _retryPolicy s }
adjustConsistency :: Consistency -> RetrySettings -> RetrySettings
adjustConsistency v = set reducedConsistency (Just v)
constDelay :: NominalDiffTime -> RetrySettings -> RetrySettings
constDelay v = setDelayFn constantDelay v v
expBackoff :: NominalDiffTime
-> NominalDiffTime
-> RetrySettings
-> RetrySettings
expBackoff = setDelayFn exponentialBackoff
fibBackoff :: NominalDiffTime
-> NominalDiffTime
-> RetrySettings
-> RetrySettings
fibBackoff = setDelayFn fibonacciBackoff
adjustSendTimeout :: NominalDiffTime -> RetrySettings -> RetrySettings
adjustSendTimeout v = set sendTimeoutChange (Ms $ round (1000 * v))
adjustResponseTimeout :: NominalDiffTime -> RetrySettings -> RetrySettings
adjustResponseTimeout v = set recvTimeoutChange (Ms $ round (1000 * v))
setDelayFn :: (Int -> RetryPolicy)
-> NominalDiffTime
-> NominalDiffTime
-> RetrySettings
-> RetrySettings
setDelayFn f v w s =
let a = round (1000000 * w)
b = round (1000000 * v)
in
s { _retryPolicy = capDelay a (f b) <> _retryPolicy s }