Refactor the publishing and introduce logging
This commit is contained in:
parent
21013d7e40
commit
c9a7d79bcf
53
src/MyLib.hs
53
src/MyLib.hs
@ -5,6 +5,7 @@
|
|||||||
{-# LANGUAGE NumericUnderscores #-}
|
{-# LANGUAGE NumericUnderscores #-}
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE TypeOperators #-}
|
{-# LANGUAGE TypeOperators #-}
|
||||||
|
{-# LANGUAGE LambdaCase #-}
|
||||||
module MyLib (defaultMain) where
|
module MyLib (defaultMain) where
|
||||||
|
|
||||||
import Control.Concurrent (threadDelay)
|
import Control.Concurrent (threadDelay)
|
||||||
@ -43,6 +44,8 @@ import Network.AMQP
|
|||||||
import Network.Reddit (RedditId(RedditId), publishEntries)
|
import Network.Reddit (RedditId(RedditId), publishEntries)
|
||||||
import Network.Wreq.Session (newSession)
|
import Network.Wreq.Session (newSession)
|
||||||
import Publish (Publish(..))
|
import Publish (Publish(..))
|
||||||
|
import Text.Printf (printf)
|
||||||
|
import Data.ByteString.Lazy (ByteString)
|
||||||
|
|
||||||
data MessageType = Create | Update
|
data MessageType = Create | Update
|
||||||
deriving stock (Show, Eq, Generic)
|
deriving stock (Show, Eq, Generic)
|
||||||
@ -57,17 +60,23 @@ data Message = Message
|
|||||||
deriving (ToJSON, FromJSON)
|
deriving (ToJSON, FromJSON)
|
||||||
via AesonCodec (Field (CamelCase <<< DropPrefix "message")) Message
|
via AesonCodec (Field (CamelCase <<< DropPrefix "message")) Message
|
||||||
|
|
||||||
toMessage :: Value -> Message
|
|
||||||
toMessage entry = Message Create (RedditId (entry ^. key "id" . _String)) entry
|
|
||||||
|
|
||||||
sqlRecorder :: SQL.Connection -> Publish IO RedditId
|
toMessage :: SQL.Connection -> Publish IO (Maybe Message) -> Publish IO Value
|
||||||
sqlRecorder conn = Publish $ Membership.recordSeen conn
|
toMessage sqlConn (Publish p) = Publish $ \entry -> do
|
||||||
|
case RedditId <$> (entry ^? key "id" . _String) of
|
||||||
|
Nothing -> p Nothing
|
||||||
|
Just redditId -> do
|
||||||
|
event <- bool Create Update <$> Membership.isSeen sqlConn redditId
|
||||||
|
p $ Just $ Message event redditId entry
|
||||||
|
|
||||||
amqpPublisher :: SQL.Connection -> Channel -> Text -> Publish IO Message
|
sqlRecorder :: SQL.Connection -> Publish IO (Maybe RedditId)
|
||||||
amqpPublisher sqlConn channel exchange = Publish $ \msg -> do
|
sqlRecorder conn = Publish $ maybe (pure ()) (Membership.recordSeen conn)
|
||||||
seen <- Membership.isSeen sqlConn (messageIdentifier msg)
|
|
||||||
let msg' = msg{messageType = bool Create Update seen}
|
amqpPublisher :: Channel -> Text -> Publish IO (Maybe ByteString)
|
||||||
void $ publishMsg channel exchange routingKey (message (A.encode msg'))
|
amqpPublisher channel exchange = Publish $ \case
|
||||||
|
Nothing -> pure ()
|
||||||
|
Just lbs ->
|
||||||
|
void $ publishMsg channel exchange routingKey (message lbs)
|
||||||
where
|
where
|
||||||
routingKey = "doesn't matter on fanout"
|
routingKey = "doesn't matter on fanout"
|
||||||
message lbs = newMsg
|
message lbs = newMsg
|
||||||
@ -75,6 +84,23 @@ amqpPublisher sqlConn channel exchange = Publish $ \msg -> do
|
|||||||
, msgDeliveryMode = Just Persistent
|
, msgDeliveryMode = Just Persistent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stdoutPublisher :: Publish IO String
|
||||||
|
stdoutPublisher = Publish putStrLn
|
||||||
|
|
||||||
|
data Fetch
|
||||||
|
= Fetch Fetcher
|
||||||
|
| PublishMessage Message
|
||||||
|
| ParseFailed
|
||||||
|
|
||||||
|
fetchToLog :: Fetch -> String
|
||||||
|
fetchToLog (Fetch fetcher) = printf "Refreshing %s" (show $ fetcherSubreddit fetcher)
|
||||||
|
fetchToLog ParseFailed = printf "Failed parsing"
|
||||||
|
fetchToLog (PublishMessage msg) = messageToLog msg
|
||||||
|
where
|
||||||
|
messageToLog :: Message -> String
|
||||||
|
messageToLog m = printf "Publishing %s as type %s" (show $ messageIdentifier m) (show $ messageType m)
|
||||||
|
|
||||||
|
|
||||||
defaultMain :: FilePath -> IO ()
|
defaultMain :: FilePath -> IO ()
|
||||||
defaultMain path = do
|
defaultMain path = do
|
||||||
conf <- readConfig path
|
conf <- readConfig path
|
||||||
@ -90,13 +116,14 @@ defaultMain path = do
|
|||||||
chan <- openChannel conn
|
chan <- openChannel conn
|
||||||
declareExchange chan newExchange { exchangeName = "reddit_posts", exchangeType = "fanout" }
|
declareExchange chan newExchange { exchangeName = "reddit_posts", exchangeType = "fanout" }
|
||||||
sess <- newSession
|
sess <- newSession
|
||||||
let encoder = amqpPublisher sqlConn chan "reddit_posts"
|
let encoder = amqpPublisher chan "reddit_posts"
|
||||||
recorder = sqlRecorder sqlConn
|
recorder = sqlRecorder sqlConn
|
||||||
publisher = encoder <> (messageIdentifier >$< recorder)
|
publisher = (fmap A.encode >$< encoder) <> (fmap messageIdentifier >$< recorder) <> (maybe ParseFailed PublishMessage >$< logger)
|
||||||
|
logger = fetchToLog >$< stdoutPublisher
|
||||||
forever $ do
|
forever $ do
|
||||||
for_ (conf ^. fetchers) $ \fetcher -> do
|
for_ (conf ^. fetchers) $ \fetcher -> do
|
||||||
print fetcher
|
publish logger (Fetch fetcher)
|
||||||
publishEntries (toMessage >$< publisher) sess fetcher
|
publishEntries (toMessage sqlConn publisher) sess fetcher
|
||||||
threadDelay (15 * 60_000_000)
|
threadDelay (15 * 60_000_000)
|
||||||
|
|
||||||
getPassword :: Password -> IO Text
|
getPassword :: Password -> IO Text
|
||||||
|
Loading…
Reference in New Issue
Block a user