Самый элегантный способ запустить несколько серверов Скотти в одном приложении?

Есть ли стандартный способ запустить два сервера Скотти в одном приложении? В игрушечном проекте я пытаюсь:

main :: IO ()
main = do
  scotty 3000 $ do
    get "/" $ do
      text "hello"
  scotty 4000 $ do
    post "/" $ do
      text "world"

Первый сервер запускается, а второй нет. Это также может быть недостатком в том, как я понимаю Haskell IO. Спасибо!


person Mike    schedule 19.02.2020    source источник


Ответы (2)


Процедура scotty не возвращает управление, она берет на себя управление и постоянно обслуживает запросы к веб-маршрутам. Если бы он вернулся, у вас возникла бы проблема с потоком управления - как бы вы оставили порт открытым, когда придет запрос?

Одним из решений является размещение каждого вызова scotty в отдельном потоке. Например:

#!/usr/bin/env cabal
{- cabal:
     build-depends: base, scotty
-}
{-# LANGUAGE OverloadedStrings #-}

import Control.Concurrent
import Web.Scotty

main :: IO ()
main = do
  forkIO $ scotty 3000 $ do
    get "/" $ do
      text "hello"
  scotty 4000 $ do
    post "/" $ do
      text "world"

При эксплуатации:

% curl -XPOST localhost:4000
world%
% curl -XGET localhost:3000
hello%
person Thomas M. DuBuisson    schedule 19.02.2020

Я бы использовал async:

import Control.Concurrent.Async

main :: IO ()
main = do
  a1 <- async $ scotty 3000 $ do
    get "/" $ do
      text "hello"
  a2 <- async $ scotty 4000 $ do
    post "/" $ do
      text "world"
  waitAnyCatchCancel [a1, a2]
person mithrandi    schedule 19.02.2020