app state in HTTP

2009-09-18 @ 20:37#

i've been contemplating application state recently. for a number of reasons. mostly due to my work in (re)building a simple text-base adventure game using HTTP/REST. anyway, my thinking on application state has e/de-volved recently.

app state for a client

in my latest work, app state is managed per client. in other words, each client that begins an interaction with the web service has its own application state. othe clients that come along have different app state. each client has app state the reflects the sum of their interactions with the web service.

shared app state

it turns out there is some app state that is shared by all clients. most of this is configuration information that only the server is interested in. while it _is_ app state, it's server-side only; only the server cares. client's don't need to know anything about this.

storing app state

the app state that is shared by all clients is stored in a durable storage medium. config files, database rows, even in the resource/representation template themselves.

the client-centric app state is also stored on the server; in a durable medium, too. this state is available for each client interaction via the URL. i most often use URI patterns to indicate client state. might be part of the path (/app-name/state-pointer/resource-name) or part of the query string (/app-name/resource-name?state-pointer=a1s2d3f4g5h6j7k8l9). sometimes the pointer to the server-side instance of the client's app state is stored in a cookie:

GET /app-name/resource-name HTTP/1.1
Cookies: state-pointer=a1s2d3f4g5h6j7k8l9
...

so i store client app state on the server

is this a bad thing? no. is this stateless? well...

if the app state pointer is part of the URI, then it's easy to see this is a stateless pattern. any link that contains the state pointer can be stored and (theoretically) presented at some future date and work just fine. there are some practicalities along the way (do i want to try to remember all the app state from all the clients forever?), but the pattern is sound.

maybe it's better if the client-centric app state is stored on the client directly. that means the server doesn't need to worry about keeping the state collection around forever - the client does. but is that the way to go? no, IMO. the client can be reasonably expected to store a pointer (most likely via a URI), but not the state itself. esp. if the state si constantly updated (i.e. each interaction modifies the app state for this particular client).

client-centric app state == private vars

i now think of client app state as the HTTP equivalent of private variables in a local program. each client generates their own collection of values. used throughout the life of the application. that collection is the app state. whether it is kept on the server or the client is not the exciting part. the exciting part is that i now have a familiar model for thinking about app state. it's all just the client's private variable values.

now my application design has a simple, recognizable pattern: managing client app-state. there's a collection of stuff for each client. this stuff is stored in a durable medium. this stuff can be accessed in a safe/shared manner. if it's a small pile, i might store it in the URI itself. if it's a bit large for the URI, i might store it in the Cookie header. if it can get rather large, i'll store it on the server w/ a pointer stored w/ the client (URI or Cookie). it might even be available as a resource (/app-name/user-id/state-pointer).

but i always know where it is. i always know how to get it; how to update it; how to delete it. i can manage client-centric app state without mucking up server app state or some other client's state.

the next big thing

app state is just the variable pile, not the state engine instance. just what a client can do at each stage of the interaction is dependent on both client-centric and server-side state. at the end of each interaction (request/response), the server can evaluate the client's app state and determine what interactions are valid next. that means the server can supply the client with the "next steps" that are valid. and that's done using links.

but that's another post, right?

code