Haskellでターン制ゲーム用のサーバーを実装しようとしています。私の選択は、管理とメタ情報(ユーザーが参加するゲームなど)にYesodを使用することです。
ゲーム内のデータオーバーヘッドを小さく保つために、Webソケットを使用したいと思います。
ws-chatの例を見ると、ハンドラモナドにアクセスする方法と永続的な方法がわかりません。
それ自体がデータベースを更新し、関連するユーザーに通知する「通常の」ハンドラーにラップされた接続用の簿記コードがあると最適です。
こんな感じだと思います。
{-# LANGUAGE QuasiQuotes, TypeFamilies, GeneralizedNewtypeDeriving, TemplateHaskell, OverloadedStrings, GADTs, FlexibleContexts #-}
module Main where
import Control.Monad.IO.Class (liftIO)
import Data.String (fromString)
import Database.Persist
import Database.Persist.TH
import Database.Persist.Sqlite
import Network.Wai.Application.Static (staticApp, defaultWebAppSettings, defaultFileServerSettings)
import Network.Wai.Handler.Warp (runSettings, defaultSettings, settingsIntercept, settingsPort)
import Network.Wai.Handler.WebSockets (intercept)
import qualified Network.WebSockets as WS
share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistUpperCase|
Person
name String
age Int
deriving Show
|]
ws :: WS.Request -> WS.WebSockets WS.Hybi10 ()
ws r = do
WS.acceptRequest r
liftIO $ runSqlite ":memory:" $ do
runMigration migrateAll
michaelId <- insert $ Person "Michael" 26
michael <- get michaelId
liftIO $ print michael
main :: IO ()
main = runSettings defaultSettings
{ settingsPort = 9160
, settingsIntercept = intercept $ ws
} $ staticApp (defaultFileServerSettings $ fromString ".")
Handler
自分でモナドを実行したい場合は、 runFakeHandlerを使用できます。
Yesod.WebSocketsライブラリを使用していて、次のようなWebソケットアプリケーションでDBにアクセスできました。
voteApp :: WebSocketsT Handler ()
voteApp = do
uuid <- liftIO nextRandom
master <- getYesod
runSqlPool (insert (Session uuid)) $ appConnPool master
-- rest of the handler