]> woffs.de Git - fd/haskell-amqp-utils.git/blob - konsum.hs
manpages
[fd/haskell-amqp-utils.git] / konsum.hs
1 -- SPDX-FileCopyrightText: 2022 Frank Doepper
2 --
3 -- SPDX-License-Identifier: GPL-3.0-only
4
5 -- generic amqp consumer
6 import           Control.Concurrent
7 import qualified Control.Exception             as X
8 import qualified Data.Text                     as T
9 import           Data.Time
10 import           Data.Version                  (showVersion)
11 import           Network.AMQP
12 import           Network.AMQP.Utils.Connection
13 import           Network.AMQP.Utils.Helpers
14 import           Network.AMQP.Utils.Options
15 import           Paths_amqp_utils              (version)
16 import           System.Environment
17
18 main :: IO ()
19 main = do
20   hr "starting"
21   tid <- myThreadId
22   args <- getArgs >>= parseargs 'k'
23   let addiArgs = reverse $ additionalArgs args
24   printparam "client version" ["amqp-utils", showVersion version]
25   (conn, chan) <- connect args
26   addChannelExceptionHandler chan (X.throwTo tid)
27   -- set prefetch
28   printparam "prefetch" $ preFetch args
29   qos chan 0 (preFetch args) False
30   -- attach to given queue? or build exclusive queue and bind it?
31   queue <-
32     maybe
33       (tempQueue chan (tmpQName args) (bindings args))
34       (return)
35       (fmap T.pack (qName args))
36   printparam "queue name" queue
37   printparam "shown body chars" $ anRiss args
38   printparam "temp dir" $ tempDir args
39   printparam "callback" $ fileProcess args
40   printparam "callback args" $ addiArgs
41   printparam "cleanup temp file" $
42     maybe Nothing (\_ -> Just (cleanupTmpFile args)) (fileProcess args)
43   -- subscribe to the queue
44   ctag <-
45     consumeMsgs
46       chan
47       queue
48       (if ack args
49          then Ack
50          else NoAck)
51       (myCallback args addiArgs tid)
52   printparam "consumer tag" ctag
53   printparam "send acks" $ ack args
54   printparam "requeue if rejected" $ (ack args) && (requeuenack args)
55   hr "entering main loop"
56   sleepingBeauty >>= printparam "exception"
57   closeConnection conn
58   hr "connection closed"
59
60 -- | exclusive temp queue
61 tempQueue :: Channel -> String -> [(String, String)] -> IO T.Text
62 tempQueue chan tmpqname bindlist = do
63   (q, _, _) <-
64     declareQueue
65       chan
66       newQueue {queueExclusive = True, queueName = T.pack tmpqname}
67   mapM_
68     (\(xchange, bkey) ->
69        bindQueue chan q (T.pack xchange) (T.pack bkey) >>
70        printparam "binding" [xchange, bkey])
71     bindlist
72   return q
73
74 -- | process received message
75 myCallback :: Args -> [String] -> ThreadId -> (Message, Envelope) -> IO ()
76 myCallback a addi tid m@(_, envi) = do
77   let numstring = show $ envDeliveryTag envi
78   hr $ "BEGIN " ++ numstring
79   now <- getZonedTime
80   (callbackoptions, callbackenv) <-
81     X.catch
82       (printmsg Nothing m (anRiss a) now)
83       (\x -> X.throwTo tid (x :: X.IOException) >> return ([], []))
84   either (\e -> printparam "ERROR" (e :: X.IOException) >> reje envi a) return =<<
85     X.try
86       (optionalFileStuff
87          m
88          callbackoptions
89          addi
90          numstring
91          a
92          tid
93          Nothing
94          callbackenv)
95   hr $ "END " ++ numstring