在HTTP请求之间保持状态

时间:2018-10-27 18:20:10

标签: haskell functional-programming

假设我有一个基于Scotty的http服务器

SELECT table1_studentname, table2_studentname, etc
( CASE WHEN :variable IN
     (SELECT student_id from Table 2) 
      THEN
      ......
      ELSE
     ...
    END) as table3_studentname

然后我有一个要保持状态scottyServer :: IO () scottyServer = do print ("Starting Server at port " ++ show port) scotty port routes routes :: ScottyM() routes = do get "/service" responseService get "/users" responseUsers

的断路器
CircuitBreakerType

使用Haskell如何在Scootty的请求/响应之间保持CircuitBreakerType的状态

我做过的所有状态机示例都是通过IO monad相互传递状态,但是对于Http服务器,我不知道如何保持状态。希望与数据库持久性无关,因为性能会降低。

致谢

1 个答案:

答案 0 :(得分:3)

在这种局部应用程序中,您是您的朋友。在C语言中可能使用有罪的全局变量的地方,您可以改为在父(主)例程中显式声明您的值(引用),然后将其通过部分应用程序传递给Web路由处理程序。

{-# LANGUAGE OverloadedStrings #-}
import Web.Scotty
import Control.Monad.IO.Class
import Data.IORef

port = 8080

scottyServer :: IO ()
scottyServer = do
    print ("Starting Server at port " ++ show port)
    ref <- newState initialState
    scotty port (routes ref)

routes :: MyStateRef -> ScottyM()
routes ref = get "/users" (responseUsers ref)

responseUsers :: MyStateRef -> ActionM ()
responseUsers ref = do x <- statefulStuff ref
                       json (show x)

--------------------------------------------------------------------------------
--  Stateful things

initialState :: Int
initialState = 0
type MyState = Int
type MyStateRef = IORef Int -- Could be TVar, MVar, DB address, etc

newState :: MonadIO m => MyState -> m MyStateRef
newState = liftIO . newIORef

statefulStuff :: MonadIO m => MyStateRef -> m MyState
statefulStuff ref =
 do x <- liftIO (readIORef ref)
    -- N.B. lack of atomicity - that isn't the point of this answer
    let y = x + 1
    y `seq` liftIO (writeIORef ref y)
    pure y