egdmitry
egdmitry

Reputation: 2151

How to open a separate socket connection in Scotty or Yesod?

I am building an application that has to connect to an IRC network (open a socket) and also host a web app. Some data should be shared between an IRC part and Http part. What's the best way to achieve that kind of concurrency in Haskell? Should Control.Monad.STM be used to implement this? Is this something the web framework should support as well or is it possible to fork before starting Scotty?

Upvotes: 1

Views: 139

Answers (1)

egdmitry
egdmitry

Reputation: 2151

I found the following works surprisingly great. I ended up using STM.TQueue.

listen :: SSL.SSL -> IO ()
listen ssl = do
  lines <- BL.lines `fmap` SSL.lazyRead ssl
  mapM_ (processLine ssl . show) lines

processQueue :: SSL.SSL -> TQueue String -> IO ()
processQueue ssl queue = forever $ do newData <- atomically $ readTQueue queue
                                      privmsg ssl newData

web_service :: TQueue String -> IO ()
web_service queue = scotty 25000 $ do
  get "/" $ do
    liftIO $ atomically $ writeTQueue queue "test passed"    
    status ok200

irc_bot :: [AddrInfo] -> TQueue String -> IO ()
irc_bot addrs queue = do ssl <- connectToServer (head addrs)
                         forkIO $ listen ssl
                         processQueue ssl queue

main = withOpenSSL $ do
  let hints = defaultHints { addrSocketType = Stream, addrFamily = AF_INET }
  addrs <- getAddrInfo (Just hints) (Just "irc.freenode.com") (Just "6697")
  queue <- atomically newTQueue
  forkIO $ irc_bot addrs queue
  web_service queue

Upvotes: 1

Related Questions