module Database.CQL.IO.Settings where
import Control.Lens hiding ((<|))
import Control.Retry
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 (..))
data RetrySettings = RetrySettings
{ _retryPolicy :: RetryPolicy
, _reducedConsistency :: Maybe Consistency
, _sendTimeoutChange :: Milliseconds
, _recvTimeoutChange :: Milliseconds
}
data Settings = Settings
{ _poolSettings :: PoolSettings
, _connSettings :: ConnectionSettings
, _retrySettings :: RetrySettings
, _protoVersion :: Version
, _portnumber :: PortNumber
, _contacts :: NonEmpty String
, _maxWaitQueue :: Maybe Word64
, _policyMaker :: IO Policy
}
makeLenses ''RetrySettings
makeLenses ''Settings
defSettings :: Settings
defSettings = Settings
P.defSettings
C.defSettings
noRetry
V3
(fromInteger 9042)
("localhost" :| [])
Nothing
random
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
setMaxWaitQueue :: Word64 -> Settings -> Settings
setMaxWaitQueue v = set maxWaitQueue (Just 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
noRetry :: RetrySettings
noRetry = RetrySettings (RetryPolicy $ const Nothing) Nothing 0 0
retryForever :: RetrySettings
retryForever = RetrySettings mempty Nothing 0 0
maxRetries :: Word -> RetrySettings -> RetrySettings
maxRetries v = over retryPolicy (mappend (limitRetries $ fromIntegral v))
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 d v w = over retryPolicy
(mappend $ capDelay (round (1000000 * w)) $ d (round (1000000 * v)))