git.iko.soy/typeable/bloodhound
on master help sign in
WIP: add instances and public API
commitb0ba88993707e2aa85d86979ab317bc746e78a8f authorMichael Xavier <michael@michaelxavier.net> dateSun 18 Oct 2015, 20:16 (11 years ago) parent9bc7ebd
2 files changed+139−8
src/Database/Bloodhound/Client.hs+28−4 src/Database/Bloodhound/Types.hs+111−4
src/Database/Bloodhound/Client.hs+28−4
@@ -1,5 +1,5 @@
1−{-# LANGUAGE OverloadedStrings #-}
2−{-# LANGUAGE RecordWildCards #-}
1+{-# LANGUAGE OverloadedStrings #-}
2+{-# LANGUAGE RecordWildCards #-}
33
44-------------------------------------------------------------------------------
55-- |
@@ -24,6 +24,7 @@ module Database.Bloodhound.Client
2424 withBH
2525 , createIndex
2626 , deleteIndex
27+ , updateIndexSettings
2728 , indexExists
2829 , openIndex
2930 , closeIndex
@@ -58,7 +59,7 @@ module Database.Bloodhound.Client
5859 )
5960 where
6061
61−import qualified Blaze.ByteString.Builder as BB
62+import qualified Blaze.ByteString.Builder as BB
6263import Control.Applicative
6364import Control.Monad
6465import Control.Monad.Catch
@@ -66,8 +67,11 @@ import Control.Monad.IO.Class
6667import Data.Aeson
6768import Data.ByteString.Lazy.Builder
6869import qualified Data.ByteString.Lazy.Char8 as L
70+import Data.Foldable (toList)
71+import qualified Data.HashMap.Strict as HM
6972import Data.Ix
70−import qualified Data.List as LS (filter)
73+import qualified Data.List as LS (filter, foldl')
74+import Data.List.NonEmpty (NonEmpty (..))
7175import Data.Maybe (fromMaybe, isJust)
7276import Data.Monoid
7377import Data.Text (Text)
@@ -262,6 +266,26 @@ deleteIndex :: MonadBH m => IndexName -> m Reply
262266deleteIndex (IndexName indexName) =
263267 delete =<< joinPath [indexName]
264268
269+-- | 'updateIndexSettings' will apply a non-empty list of setting updates to an index
270+--
271+-- >>> response <- runBH' $ updateIndexSettings (BlocksWrite False :| []) testIndex
272+-- >>> respIsTwoHunna response
273+-- True
274+updateIndexSettings :: MonadBH m => NonEmpty IndexSettingUpdate -> IndexName -> m Reply
275+updateIndexSettings updates (IndexName indexName) =
276+ bindM2 put url (return body)
277+ where url = joinPath [indexName, "_settings"]
278+ body = Just (encode jsonBody)
279+ jsonBody = Object (deepMerge [u | Object u <- toJSON <$> toList updates])
280+
281+deepMerge :: [Object] -> Object
282+deepMerge = LS.foldl' go mempty
283+ where go acc = LS.foldl' go' acc . HM.toList
284+ go' acc (k, v) = HM.insertWith merge k v acc
285+ merge (Object a) (Object b) = Object (deepMerge [a, b])
286+ merge _ b = b
287+
288+
265289statusCodeIs :: Int -> Reply -> Bool
266290statusCodeIs n resp = NHTS.statusCode (responseStatus resp) == n
267291
src/Database/Bloodhound/Types.hs+111−4
@@ -57,6 +57,14 @@ module Database.Bloodhound.Types
5757 , NullValue(..)
5858 , IndexSettings(..)
5959 , IndexSettingUpdate(..)
60+ , AllocationPolicy(..)
61+ , ReplicaBounds(..)
62+ , Bytes(..)
63+ , FSType(..)
64+ , InitialShardCount(..)
65+ , NodeAttrFilter(..)
66+ , NodeAttrName(..)
67+ , CompoundFormat(..)
6068 , IndexTemplate(..)
6169 , Server(..)
6270 , Reply
@@ -348,6 +356,10 @@ data IndexSettings =
348356defaultIndexSettings :: IndexSettings
349357defaultIndexSettings = IndexSettings (ShardCount 3) (ReplicaCount 2)
350358
359+{-| 'IndexSettingUpdate' is used to update an index' settings piecemeal.
360+
361+ <https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-update-settings.html>
362+-}
351363data IndexSettingUpdate = NumberOfReplicas Int
352364 | AutoExpandReplicas ReplicaBounds
353365 | BlocksReadOnly Bool
@@ -364,17 +376,20 @@ data IndexSettingUpdate = NumberOfReplicas Int
364376 | CacheFilterMaxSize (Maybe Bytes)
365377 | CacheFilterExpire (Maybe NominalDiffTime)
366378 | GatewaySnapshotInterval NominalDiffTime
379+ | RoutingAllocationInclude (NonEmpty NodeAttrFilter)
380+ | RoutingAllocationExclude (NonEmpty NodeAttrFilter)
381+ | RoutingAllocationRequire (NonEmpty NodeAttrFilter)
367382 | RoutingAllocationDisable Bool
368383 | RoutingAllocationDisableNew Bool
369384 | RoutingAllocationDisableReplica Bool
370385 | RoutingAllocationEnable AllocationPolicy
371386 | RoutingAllocationShardsPerNode ShardCount
372− | RecoveryInitialShards --TODO: shard count or quorum specifications
373− | GCDeletes
387+ | RecoveryInitialShards InitialShardCount
388+ | GCDeletes NominalDiffTime
374389 | TTLDisablePurge Bool
375390 | TranslogFSType FSType
376− | TranslogCompoundFormat
377− | TranslogCompoundOnFlush
391+ | IndexCompoundFormat CompoundFormat
392+ | IndexCompoundOnFlush Bool
378393 | WarmerEnabled Bool
379394 --TODO: figure out allocation options
380395
@@ -387,6 +402,28 @@ data ReplicaBounds = ReplicasBounded Int Int
387402 | ReplicasLowerBounded Int
388403 | ReplicasUnbounded
389404
405+newtype Bytes = Bytes Int deriving (Eq, Show, Ord, ToJSON)
406+
407+data FSType = FSSimple
408+ | FSBuffered deriving (Eq, Show, Ord)
409+
410+data InitialShardCount = QuorumShards
411+ | QuorumMinus1Shards
412+ | FullShards
413+ | FullMinus1Shards
414+ | ExplicitShards Int
415+
416+data NodeAttrFilter = NodeAttrFilter { nodeAttrFilterName :: NodeAttrName
417+ , nodeAttrFilterValues :: NonEmpty Text}
418+
419+newtype NodeAttrName = NodeAttrName Text
420+
421+data CompoundFormat = CompoundFileFormat Bool
422+ | MergeSegmentVsTotalIndex Double
423+ -- ^ percentage between 0 and 1 where 0 is false, 1 is true
424+
425+newtype NominalDiffTimeJSON = NominalDiffTimeJSON NominalDiffTime
426+
390427{-| 'Reply' and 'Method' are type synonyms from 'Network.HTTP.Types.Method.Method' -}
391428type Reply = Network.HTTP.Client.Response L.ByteString
392429type Method = NHTM.Method
@@ -2144,6 +2181,76 @@ instance ToJSON IndexSettings where
21442181 ]
21452182 ]
21462183
2184+instance ToJSON IndexSettingUpdate where
2185+ toJSON (NumberOfReplicas x) = oPath ("index" :| ["number_of_replicas"]) x
2186+ toJSON (AutoExpandReplicas x) = oPath ("index" :| ["auto_expand_replicas"]) x
2187+ toJSON (BlocksReadOnly x) = oPath ("blocks" :| ["read_only"]) x
2188+ toJSON (BlocksRead x) = oPath ("blocks" :| ["read"]) x
2189+ toJSON (BlocksWrite x) = oPath ("blocks" :| ["write"]) x
2190+ toJSON (BlocksMetaData x) = oPath ("blocks" :| ["metadata"]) x
2191+ toJSON (RefreshInterval x) = oPath ("index" :| ["refresh_interval"]) (NominalDiffTimeJSON x)
2192+ toJSON (IndexConcurrency x) = oPath ("index" :| ["concurrency"]) x
2193+ toJSON (FailOnMergeFailure x) = oPath ("index" :| ["fail_on_merge_failure"]) x
2194+ toJSON (TranslogFlushThresholdOps x) = oPath ("index" :| ["translog", "flush_threshold_ops"]) x
2195+ toJSON (TranslogFlushThresholdSize x) = oPath ("index" :| ["translog", "flush_threshold_size"]) x
2196+ toJSON (TranslogFlushThresholdPeriod x) = oPath ("index" :| ["translog", "flush_threshold_period"]) (NominalDiffTimeJSON x)
2197+ toJSON (TranslogDisableFlush x) = oPath ("index" :| ["translog", "disable_flush"]) x
2198+ toJSON (CacheFilterMaxSize x) = oPath ("index" :| ["cache", "filter", "max_size"]) x
2199+ toJSON (CacheFilterExpire x) = oPath ("index" :| ["cache", "filter", "expire"]) (NominalDiffTimeJSON <$> x)
2200+ toJSON (GatewaySnapshotInterval x) = oPath ("index" :| ["gateway", "snapshot_interval"]) (NominalDiffTimeJSON x)
2201+ toJSON (RoutingAllocationInclude fs) = oPath ("index" :| ["routing", "allocation", "include"]) (attrFilterJSON fs)
2202+ toJSON (RoutingAllocationExclude fs) = oPath ("index" :| ["routing", "allocation", "exclude"]) (attrFilterJSON fs)
2203+ toJSON (RoutingAllocationRequire fs) = oPath ("index" :| ["routing", "allocation", "require"]) (attrFilterJSON fs)
2204+ toJSON (RoutingAllocationDisable x) = oPath ("index" :| ["routing", "allocation", "disable_allocation"]) x
2205+ toJSON (RoutingAllocationDisableNew x) = oPath ("index" :| ["routing", "allocation", "disable_new_allocation"]) x
2206+ toJSON (RoutingAllocationDisableReplica x) = oPath ("index" :| ["routing", "allocation", "disable_replica_allocation"]) x
2207+ toJSON (RoutingAllocationEnable x) = oPath ("index" :| ["routing", "allocation", "enable"]) x
2208+ toJSON (RoutingAllocationShardsPerNode x) = oPath ("index" :| ["routing", "allocation", "total_shards_per_node"]) x
2209+ toJSON (RecoveryInitialShards x) = oPath ("index" :| ["recovery", "initial_shards"]) x
2210+ toJSON (GCDeletes x) = oPath ("index" :| ["gc_deletes"]) (NominalDiffTimeJSON x)
2211+ toJSON (TTLDisablePurge x) = oPath ("index" :| ["ttl", "disable_purge"]) x
2212+ toJSON (TranslogFSType x) = oPath ("index" :| ["translog", "fs", "type"]) x
2213+ toJSON (IndexCompoundFormat x) = oPath ("index" :| ["compound_format"]) x
2214+ toJSON (IndexCompoundOnFlush x) = oPath ("index" :| ["compound_on_flush"]) x
2215+ toJSON (WarmerEnabled x) = oPath ("index" :| ["warmer", "enabled"]) x
2216+
2217+oPath :: ToJSON a => NonEmpty Text -> a -> Value
2218+oPath (k :| []) v = object [k .= v]
2219+oPath (k:| (h:t)) v = object [k .= oPath (h :| t) v]
2220+
2221+attrFilterJSON :: NonEmpty NodeAttrFilter -> Value
2222+attrFilterJSON fs = object [ n .= T.intercalate "," (toList vs)
2223+ | NodeAttrFilter (NodeAttrName n) vs <- toList fs]
2224+
2225+instance ToJSON ReplicaBounds where
2226+ toJSON (ReplicasBounded a b) = String (showText a <> "-" <> showText b)
2227+ toJSON (ReplicasLowerBounded a) = String (showText a <> "-all")
2228+ toJSON ReplicasUnbounded = Bool False
2229+
2230+instance ToJSON AllocationPolicy where
2231+ toJSON AllocAll = String "all"
2232+ toJSON AllocPrimaries = String "primaries"
2233+ toJSON AllocNewPrimaries = String "new_primaries"
2234+ toJSON AllocNone = String "none"
2235+
2236+instance ToJSON InitialShardCount where
2237+ toJSON QuorumShards = String "quorum"
2238+ toJSON QuorumMinus1Shards = String "quorum-1"
2239+ toJSON FullShards = String "full"
2240+ toJSON FullMinus1Shards = String "full-1"
2241+ toJSON (ExplicitShards x) = toJSON x
2242+
2243+instance ToJSON FSType where
2244+ toJSON FSSimple = "simple"
2245+ toJSON FSBuffered = "buffered"
2246+
2247+instance ToJSON CompoundFormat where
2248+ toJSON (CompoundFileFormat x) = Bool x
2249+ toJSON (MergeSegmentVsTotalIndex x) = toJSON x
2250+
2251+instance ToJSON NominalDiffTimeJSON where
2252+ toJSON (NominalDiffTimeJSON t) = String (showText (round t :: Integer) <> "s")
2253+
21472254instance ToJSON IndexTemplate where
21482255 toJSON (IndexTemplate p s m) = merge
21492256 (object [ "template" .= p