我有一个中等大小的应用程序,Data.Acid用于持久性,我遇到了一种情况,我需要Update为下一版本的服务器更新我的一个事件的实现.即我有类似的东西
myUpdate :: Update MyState ()
myUpdate = <some outdated implementation>
Run Code Online (Sandbox Code Playgroud)
现在,显然我不能随意改变实现,因为它会破坏我的交易历史,所以我想知道人们通常如何处理这个问题.我看到它的方式是我的选择:
停止服务器.createCheckpoint为我而奔跑AcidState.更新Event实施,然后重新启动服务器.由于我们从新快照加载,因此更改Update不应该触发旧事件.
Update使用新名称(如myUpdate_v2)创建一个新的,并将我的服务器逻辑更新为仅使用myUpdate_v2到处而不是原始名称myUpdate.
我认为这两种选择都有其优点.(1)更好,因为我不需要在我的代码库中保留旧功能,但必须非常仔细地为我更新的每个服务器完成,否则我可能会破坏数据.(2)更安全(特别是如果我myUpdate从我的模块的导出中删除旧的,所以我可以确定我不小心在任何地方使用旧的实现),但它感觉有点难看.
有没有更好的方法来做到这一点?我认为这是我在一个长期项目中一定会遇到的事情,所以我希望有一个良好的标准工作流程来应用对事件实现的更改.
我在一个项目中使用酸状态,我非常喜欢它.我喜欢在没有太多样板的情况下为简单的Haskell数据类型添加持久性是多么容易.
根据我的理解,酸状态记录事件的日志,而不是在每次更新时写出整个新状态.我正在寻找的是一种让我从应用程序中查看状态最近更改日志的方法,作为(只读)列表.(有点像git log,虽然我不需要分支或能够回到较旧的提交.)
当然,我可以写入我自己的单独日志文件,其中包含所有状态更改的详细信息,甚至可以将我的数据建模为差异列表,但我更喜欢自动的东西,并允许我尽可能使用纯数据类型.
是否存在类似于酸状态的库,或者可能用于酸性状态的某些内部功能?
data Foo = Foo {
_bar :: Map String Integer
} deriving (Eq, Ord, Read, Show, Data, Typeable)
$(deriveSafeCopy 0 'base 'Foo)
$(makeLenses ''Foo)
Run Code Online (Sandbox Code Playgroud)
鉴于上述代码,我认为应该可以这样做:
addEntry :: String -> Update Foo ()
addEntry s = zoom bar $ modify $ insert s 0
Run Code Online (Sandbox Code Playgroud)
但GHC会抱怨:
src/Backend.hs:39:20:
No instance for (Functor
(Control.Lens.Internal.Zoom.Zoomed (Update Foo) ()))
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?
我在努力acid-state.该文件指出,Update st是的一个实例MonadState st.我尝试不同的东西,但我的编译器不希望看到的是:(我试过HelloWorld.hs从实例,但得到了同样的问题:
HelloWorld.hs:26:7:
No instance for (MonadState
HelloWorldState (Update HelloWorldState))
arising from a use of `put'
Possible fix:
add an instance declaration for
(MonadState HelloWorldState (Update HelloWorldState))
In the expression: put (HelloWorldState newValue)
In an equation for `writeState':
writeState newValue = put (HelloWorldState newValue)
HelloWorld.hs:29:43:
No instance for (MonadReader
HelloWorldState (Query HelloWorldState))
arising from a use of `ask'
Possible fix:
add an instance declaration for
(MonadReader HelloWorldState …Run Code Online (Sandbox Code Playgroud) 能够Network.WebSockets从 snaplet 内部使用该模块会很好,但我不知道如何实际操作。
使用它的runWebSocketsSnap :: MonadSnap m => ServerApp -> m ()函数Network.WebSockets.Snap很容易在我的应用程序中包含一个简单的无状态 websocket 服务器:
routes :: [(ByteString, Handler App App ())]
routes = [ ("/ws", runWebSocketsSnap wsApp) ]
wsApp :: PendingConnection -> IO () -- this is the ServerApp type
wsApp pending = do
conn <- acceptRequest pending
forever $ do
msg <- receiveData conn
sendTextData conn ("Echo " `mappend` msg :: Text)
Run Code Online (Sandbox Code Playgroud)
但我的目标是维护 webscket 服务器的状态(例如,已连接客户端的列表,如http://jaspervdj.be/websockets/example.html)。或者,进入 snaplet 的酸状态存储会很好。
我的第一个想法是liftIO将 websocket …
我正在使用warp,wai和acid-state在haskell中编写一个Web服务.截至目前,我有两个需要数据库交互的处理函数,后者给我带来了麻烦.
第一个是注册:
registerUser :: AcidState UserDatabase -> Maybe (Map.Map String String) -> Response
registerUser db maybeUserMap =
case maybeUserMap of
(Just u) -> let _ = fmap (\id -> update db (StoreUser (toString id) u)) (nextRandom)
in resPlain status200 "User Created."
Nothing -> resPlain status401 "Invalid user JSON."
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,我设法IO通过执行更新来避免感染响应let _ = ...
在登录功能(目前只返回用户地图)中,我无法避免IO,因为我需要在响应中实际发回结果:
loginUser :: AcidState UserDatabase -> String -> Response
loginUser db username = do
maybeUserMap <- (query db (FetchUser username))
case maybeUserMap …Run Code Online (Sandbox Code Playgroud) 我是Haskell的新手,想尝试使用酸状态库,但在尝试安装它时会得到以下输出:
>cabal install acid-state
Resolving dependencies...
Configuring acid-state-0.7.5...
Building acid-state-0.7.5...
Preprocessing library acid-state-0.7.5...
[ 1 of 15] Compiling Data.Acid.CRC ( src\Data\Acid\CRC.hs, dist\build\Data\Ac
id\CRC.o )
[ 2 of 15] Compiling Paths_acid_state ( dist\build\autogen\Paths_acid_state.hs,
dist\build\Paths_acid_state.o )
[ 3 of 15] Compiling Data.Acid.Archive ( src\Data\Acid\Archive.hs, dist\build\Da
ta\Acid\Archive.o )
[ 4 of 15] Compiling FileIO ( src-win32\FileIO.hs, dist\build\FileIO.o
)
src-win32\FileIO.hs:43:5:
Not in scope: `catchIO'
Perhaps you meant `catch' (imported from Prelude)
src-win32\FileIO.hs:55:6:
Not in scope: `tryE'
Perhaps you meant `try' (imported from Control.Exception.Extensible)
src-win32\FileIO.hs:56:6: …Run Code Online (Sandbox Code Playgroud) 我有这样的文件结构:
--- Database.hs ---
data Database = ...
...
--- User.hs ---
import Database
addUser :: Update Database ()
...
--- Post.hs
import Database
addPost :: Update Database ()
...
Run Code Online (Sandbox Code Playgroud)
问题是,我要叫makeAcidic ''Database [...]两个User.hs,并Post.hs让自己的职能酸性,但makeAcidic在同一时间产生IsAcidic的实例为Database这样GHC抱怨重复实例声明.
acid-state ×8
haskell ×8
cabal ×1
ghc ×1
haskell-lens ×1
haskell-wai ×1
persistence ×1
warp ×1
websocket ×1