packages feed

sqsd-local-0.2.0: src/Main.hs

{-# LANGUAGE LambdaCase        #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell   #-}
module Main where

import           Control.Lens
import qualified Data.ByteString.Char8    as BS
import           Data.Text                (Text)
import qualified Data.Text                as Text
import           Network.SQS.Daemon.Local
import           System.Console.GetOpt
import           System.Environment
import           System.IO
import           Text.Printf

import qualified Data.Version             as Version
import           Paths_sqsd_local

data Options
  = Options { _daemonOptions :: DaemonOptions
            , _showHelp      :: Bool
            , _showVersion   :: Bool
            } deriving (Show, Eq, Ord)

makeLenses ''Options

defaultOptions :: Text -> Options
defaultOptions workerQueueName' =
  Options { _daemonOptions = DaemonOptions { _workerUrl = "http://localhost:5000"
                                           , _workerQueueName = workerQueueName'
                                           , _deadLetterQueueName = Nothing
                                           , _httpTimeout = Just 30
                                           , _contentType = BS.pack "application/octet-stream"
                                           , _sqsHost = BS.pack "localhost"
                                           , _sqsPort = 9324
                                           , _forked = False
                                           }
          , _showHelp = False
          , _showVersion = False
          }

readMaybe :: Read a => String -> Maybe a
readMaybe s =
  case reads s of
    [(val, "")] -> Just val
    _           -> Nothing

options :: [OptDescr (Options -> Options)]
options =
  [ Option ['h'] ["help"]
    (NoArg (set showHelp True))
    "Print this help message"
  , Option ['V'] ["version"]
    (NoArg (set showVersion True))
    "Print the CLI version"
  , Option "u" ["worker-url"]
    (ReqArg (set (daemonOptions . workerUrl) . Text.pack) "URL")
    "Specify the worker URL to send POST requests to (default: http://localhost:5000)"
  , Option "d" ["dead-letter-queue-name"]
    (ReqArg (set (daemonOptions . deadLetterQueueName) . Just . Text.pack) "NAME")
    "Name of the SQS queue to send messages to which the worker failed processing (no default)"
  , Option "T" ["http-timeout"]
    (ReqArg (set (daemonOptions . httpTimeout) . readMaybe) "NAME")
    "Timeout in seconds for the HTTP POST request to worker (default: 30)"
  , Option "C" ["content-type"]
    (ReqArg (set (daemonOptions . contentType) . BS.pack) "MEDIA_TYPE")
    "Content-Type header value to use in HTTP POST request to worker (default: application/octet-stream)"
  , Option "" ["sqs-host"]
    (ReqArg (set (daemonOptions . sqsHost) . BS.pack) "MEDIA_TYPE")
    "SQS endpoint host (default: localhost)"
  , Option "" ["sqs-port"]
    (ReqArg (set (daemonOptions . sqsPort) . maybe 9324 id . readMaybe) "MEDIA_TYPE")
    "SQS endpoint port (default: 9324)"
  , Option "" ["forked"]
    (NoArg (set (daemonOptions . forked) True))
    "If messages should be POSTed to the worker concurrently (default: false)"
  ]

usage :: String
usage = "Usage: sqsd-local WORKER_QUEUE_NAME [options]"

help :: String
help = usageInfo (usage ++ "\n\n" ++ "Options:\n") options

parseOptions :: [String] -> IO (Either String Options)
parseOptions argv =
  case getOpt Permute options argv of
    (o, [queueName], []) ->
      return (Right (foldl (&) (defaultOptions (Text.pack queueName)) o))
    (_, _, errs) ->
      return (Left (concat errs ++ help))

runDaemon :: Options -> IO ()
runDaemon =
  \case
    opts | opts ^. showHelp -> hPutStr stderr help
    opts | opts ^. showVersion -> hPutStrLn stderr (Version.showVersion version)
    opts -> startDaemon (opts ^. daemonOptions)

main :: IO ()
main = do
  res <- getArgs >>= parseOptions
  case res of
    Left err   -> hPutStr stderr err
    Right opts -> runDaemon opts