Сохранить состояние между запросом http - PullRequest
0 голосов
/ 27 октября 2018

Допустим, у меня есть http-сервер на базе Scotty

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

data CircuitBreakerType
  = Close {users::[User], error:: Integer}
  | Open {users::[User], error:: Integer}
  | HalfOpen {users::[User], error:: Integer}
  deriving (Show)

responseUsers :: ActionM ()
responseUsers = do users <- liftAndCatchIO $ searchAllCassandraUsersCB $ Close [] 0
                   json (show users)

searchAllCassandraUsersCB :: CircuitBreakerType ->  IO CircuitBreakerType
searchAllCassandraUsersCB (Close users errors)= do result <- selectAllCassandraUserCB $ Close users errors
                                                   return result

Используя Haskell, как я могу сохранить состояние CircuitBreakerType между запросом / ответом Scootty

Все примеры конечного автомата, которые я делал, передавали состояние в монаде ввода-вывода друг другу, но с Http-сервером я не представляю, как сохранить состояние. Надеемся, что ничего не связано с постоянством в базе данных, так как производительность будет плохой.

Привет

1 Ответ

0 голосов
/ 27 октября 2018

В подобных ситуациях это частичное приложение - ваш друг.Там, где вы могли бы в C использовать греховную глобальную переменную, вы могли бы вместо этого объявить свое значение (ссылку) явно в родительской (основной) подпрограмме, а затем передать его через частичное приложение вашим обработчикам веб-маршрутов.

{-# 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...