On Wed, Feb 3, 2010 at 8:27 AM, James Reeves <weavejes...@googlemail.com> wrote:
> Hi folks,
>
> Mark McGranaghan and I have recently been working on new functionality
> for Ring, a web application library for Clojure. Ring is similar to
> Rack on Ruby, and provides a simple, functional interface for handling
> HTTP requests.
>
> We've recently added support for urlencoded parameters and cookies,
> and next we plan on adding session support to the mix. What we'd like
> is to get some feedback from the Clojure community on how best to
> implement session support.
>
> Currently we have two possible designs:
>
> Design 1:
> The session is stored as an mutable atom map in (request :session). To
> update the session, use the standard Clojure swap! function, e.g.
>
>  (defn handler [request]
>   (let [session (request :session)
>         counter (@session :counter)]
>     (swap! session assoc :counter (inc counter))
>     {:status 200
>      :headers {}
>      :body (str "You've visited this page " counter " times!")}))
>
> The reasoning behind this approach is that sessions are mutable maps
> associated with the request, and thus the most natural way to
> represent them is via an (atom {}) on the request.
>
> Design 2:
> The session is an immutable map in (request :session). To update the
> session, add the updated session to the response, e.g.
>
>  (defn handler [request]
>   (let [session (request :session)
>         counter (session :counter)]
>     {:status 200
>      :headers {}
>      :session (assoc session :counter (inc counter))
>      :body (str "You've visited this page " counter " times!")}))
>
> The reasoning behind this approach is that a more functional design
> has more in common with other parts of Ring, and allows handlers to be
> pure functions, even if they use sessions.
>
> I favour design 1, whilst Mark favours design 2.
>
> I've also had an email suggesting that instead of the session being
> completely replaced by the session map on the response, it is instead
> only updated. This could be achieved by adding an update function to
> the :session key, or perhaps to merge the response session with the
> existing session, removing any key with a value of nil.
>
> Please let us know what you think is the best approach listed here, or
> if you have an entirely new design we've not thought of.
>

The last idea is on the right track. In any case, any reference type
surrounding the session data isn't really  the session data of record,
it will be backed by something else (cookies/db etc), so such use of
references is not right.

OTOH, the Clojure model of sending change into state can help
encapsulate how it is stored, and possibly avoid some
read-modify-write and last-one-wins issues.

One idea is to pass commute-like and deref-like functions to the
handling code for sending change to, and accessing, the session state.
The state will be an immutable value as usual. This encapsulates
everything about the session data.

A second option is the request has the 'current' session state value,
and people can (functionally) append to the response session-commuting
fns and args, to be applied to the session state on successful
response.

In either case, moving to a commute model is a good idea, even if not
all backends can support it (in which case they devolve to
last-one-wins).

Rich

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to