on master help sign in
Initial work on async buffer

Need to decide what to do if a message can't be sent to the server. Should we drop it? Throw it back on the queue?

commitb53d122cd21e075c14741c78870a2a62db91bb22 authorMichael Xavier <michael@michaelxavier.net> dateMon 16 Mar 2015, 09:57 (12 years ago) parent45b9512
2 files changed+65−12
katip-elasticsearch/katip-elasticsearch.cabal+10−7 katip-elasticsearch/src/Katip/Scribes/ElasticSearch.hs+55−5
katip-elasticsearch/katip-elasticsearch.cabal+10−7
@@ -1,7 +1,7 @@
11name: katip-elasticsearch
22version: 0.1.0.0
3−-- synopsis:
4−-- description:
3+-- synopsis:
4+-- description:
55license: BSD3
66license-file: LICENSE
77author: Ozgun Ataman
@@ -12,15 +12,18 @@ build-type: Simple
1212cabal-version: >=1.10
1313
1414library
15− exposed-modules:
15+ exposed-modules:
1616 Katip.Scribes.ElasticSearch
17− -- other-modules:
18− -- other-extensions:
19− build-depends:
17+ -- other-modules:
18+ -- other-extensions:
19+ build-depends:
2020 base >=4.6 && <4.7
2121 , katip
2222 , bloodhound >= 0.5 && < 0.6
2323 , random >= 1.0 && < 1.2
2424 , uuid >= 1.3 && < 1.4
25+ , aeson >=0.6 && <0.9
26+ , stm >= 2.4.3 && < 2.5
27+ , async >= 2.0.1.0 && < 2.1
2528 hs-source-dirs: src
26− default-language: Haskell2010
29+ default-language: Haskell2010
katip-elasticsearch/src/Katip/Scribes/ElasticSearch.hs+55−5
@@ -1,8 +1,17 @@
1−module Katip.Scribes.ElasticSearch where
1+module Katip.Scribes.ElasticSearch
2+ ( mkEsScribe
3+ , mkDocId
4+ , EsQueueSize
5+ , mkEsQueueSize
6+ ) where
27
38
49-------------------------------------------------------------------------------
10+import Control.Applicative
11+import Control.Concurrent.Async
12+import Control.Concurrent.STM
513import Control.Monad
14+import Data.Aeson
615import Data.UUID
716import Database.Bloodhound
817import System.Random
@@ -16,13 +25,18 @@ mkEsScribe
1625 :: Server
1726 -> IndexName
1827 -> MappingName
28+ -> EsQueueSize
1929 -> Severity
2030 -> Verbosity
2131 -> IO Scribe
22−mkEsScribe server ix mapping sev verb = return $ Scribe $ \ i -> do
23− did <- mkDocId
24− when (_itemSeverity i >= sev) $
25− void $ indexDocument server ix mapping (itemJson verb i) did
32+mkEsScribe server ix mapping qs sev verb = do
33+ q <- newTBQueueIO $ unEsQueueSize qs
34+ worker <- startWorker server ix mapping q
35+ link worker
36+
37+ return $ Scribe $ \ i ->
38+ when (_itemSeverity i >= sev) $
39+ void $ atomically $ tryWriteTBQueue q (itemJson verb i)
2640
2741
2842-------------------------------------------------------------------------------
@@ -30,8 +44,44 @@ mkDocId :: IO DocId
3044mkDocId = (DocId . toString) `fmap` randomIO
3145
3246
47+-------------------------------------------------------------------------------
48+newtype EsQueueSize = EsQueueSize {
49+ unEsQueueSize :: Int
50+ } deriving (Show, Eq, Ord, Bounded)
3351
3452
53+mkEsQueueSize :: Int -> Maybe EsQueueSize
54+mkEsQueueSize n
55+ | n >= 0 = Just $ EsQueueSize n
56+ | otherwise = Nothing
3557
3658
59+-------------------------------------------------------------------------------
60+startWorker
61+ :: Server
62+ -> IndexName
63+ -> MappingName
64+ -> TBQueue Value
65+ -> IO (Async ())
66+startWorker server ix mapping q = async $ forever $ do
67+ v <- atomically $ readTBQueue q
68+ res <- waitCatch =<< async (sendLog v)
69+ when (isLeft res) $ inCaseOfEmergency
70+ where
71+ sendLog v = void $ indexDocument server ix mapping v =<< mkDocId
72+ --TODO reenqueue? drop? would be nice to log but we don't have that context
73+ inCaseOfEmergency = return ()
3774
75+
76+-------------------------------------------------------------------------------
77+tryWriteTBQueue :: TBQueue a -> a -> STM Bool
78+tryWriteTBQueue q v = do
79+ ok <- not <$> isFullTBQueue q
80+ when ok $ writeTBQueue q v
81+ return ok
82+
83+
84+-------------------------------------------------------------------------------
85+isLeft :: Either a b -> Bool
86+isLeft (Left _) = True
87+isLeft _ = False