Server State Management

GState not only to use for client side state management, it also able to apply for server state management.

Motivation

Normally server side is stateless, so we don't need server state management. Server only use temporary state to handle requests and destroy the state after send result to client:

  1. Server receive request from client.
  2. Server build temporary state from session storage.
  3. Server fetch more data from data storage to update temporary state.
  4. Then server process temporary state to produce response's result.
  5. Server send the result to client and destroy all temporary state.
  6. Repeat the steps with another requests.

The pattern have downsides:

  • Rebuild state from database is expensive, especially query large dataset.
  • Poor performance when handle large concurrent requests. 1000 concurrent requests will consume 1000 times memory and loads even they are same.
  • Complex data management. Although you don't need state management, large applications required a complex ORM or ODM layer which drive you to crazy.
  • Hard to build real-time applications.

Server State Management with GState

Basic ideas is use gstate as a write-through cache to manage complex application state.

  1. When starting, server fetch all data from database to build a completed gstate's state.
  2. Server receives request from client.
  3. Server uses state.get to retrieve data for client.
  4. Server uses async database functions to persist changes. If actions are successful, server use state.set to update changes. If not, send error to client without update state.
  5. Server send the result, current state still alive for next requests.
  6. Repeat the steps with another requests.

Advantages

  • Rebuild state from database is happened once as long as server not restarted.
  • Handle large concurrent requests is nearly same memory footprint with a single request.
  • It's fast because all data in memory.
  • You don't need complex ORM to handle mutating or fetching relationship data. Everything as simple as manipulate JS objects.
  • GState have watch API to support real-time applications.

Put everything on memory not sound good?

Many of cases, your application's state is small enough to put everything on memory. It not different with use Redis or Memcache to store application's data.

In case your dataset is too big or contain big binary objects, you could use hybrid solution.

 app.get("/docs/:id", function(req, res){
   const doc = state.get(["docs", req.params.id]); // get doc object from server state.
   datastore.getAttachments(doc.attachmentIds).then(// put big attachments from data storage
     data => {
       doc.attachments = data;
       res.send(doc); // send doc object with attachments.
     }
   ); 
 });

 app.post("/docs", function (req, res){
   datastore.storeAttachments(req.body.attachments).then(
     attachmentIds => {
        doc = req.body;
        doc.attachmentIds = attachmentIds;
        return datastore.store(doc).then(
          doc_id => state.set(doc)
        )
     }
   )
 });

But stateful server cannot scale out?

If your application is using single database, consider use multiple stateless servers with single stateful server which interact with your single database.

Another solution is break big stateful applications into several stateful applications.

In extreme case, you could consider distribution server state management pattern

results matching ""

    No results matching ""