服务器端会话 [还] 不是 Snap 框架的一部分。有没有办法添加某种服务器端状态?
假设我想为每个 HTTP 请求增加一个计数器。我该怎么做?
服务器端会话 [还] 不是 Snap 框架的一部分。有没有办法添加某种服务器端状态?
假设我想为每个 HTTP 请求增加一个计数器。我该怎么做?
就目前而言,上述答案是正确的,但它并没有解决一些实际问题。
首先是服务器重启。如果您的存储不仅仅是缓存,它需要在服务器重新启动时保持持久性。
其次是代码重载。Snap 的未来版本,从 0.3 开始(可能在 12 月初到期)将在开发使用中动态重新加载代码。这在开发速度方面是一个巨大的优势,但它使服务器本地状态成为一种有趣的心理锻炼。如果程序员更改了服务器本地状态的类型/初始化/任何内容,则需要重新初始化。那里有一些巨大的工程挑战。
当我为 0.3 编写动态重新加载代码时,我为这个问题苦苦挣扎了一段时间。然后我看了看其他平台。php?在外部存储所有内容(数据库、内存缓存等)。完全没有内存中的交叉请求存储。Ruby on Rails?相同的。
结合第一个问题中固有的挑战,我得出的结论是,除了可能的缓存优化之外,服务器应该是无状态的。为为其设计的库/外部流程留下持久性问题。
所以我设计了生产和开发加载器使用的通用接口(一个使用静态加载,另一个使用动态加载)来获取 3 个函数:一个初始化函数、一个清理函数和一个使用初始化函数返回的状态的处理程序。在生产模式下,编译为在服务器启动时调用初始化,并在服务器关闭时进行清理。在开发模式下,它编译为:对于每个请求,动态加载所有 3 个,然后运行 init、handler、cleanup。显然,没有一个州能以这种方式在交叉请求中幸存下来。
然后我的答案就变成了:通过某种具有内置持久性的机制来进行交叉请求存储,并让服务器状态成为它的接口。如果您想在进程内工作,请使用类似 happstack-state 或 sqlite 的东西,如果您想在本地进程之外工作,请使用数据库或其他一些外部存储。
作为补充说明,由于添加了 MonadSnap 接口,在 Snap 0.3 中管理“全局”资源(如连接池等)也容易得多。
最简单的方法是将状态放在 mvar 后面:
fooHandler :: MVar Int -> Snap ()
fooHandler mvar = do
x <- liftIO $ modifyMVar mvar $ \y -> let y'=y+1 in (y',y')
writeBS $ S.pack $ "Incremented counter to: " ++ show x
初始化站点时初始化 mvar。希望这可以帮助。
I found two session-related packages:
snap-auth is made by the the Snap Framework team, or at least by one of its authors/contirbutor (Ozgun Ataman). It targets authentication and session management. The session management is done using a map of ByteString to ByteString, implying you can only store data that has already been serialized to a ByteString:
type Session = Map ByteString ByteString
On the other hand, mysnapsession allows you to use an arbitrary type to model your session. There is however some helper functions for sessions of the Map
type. More details here. The author, Chris Smith, is also part of the Snap Framework project.