Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Persisting/caching data between requests - common approach

I'm developing an Asp.net (MVC but this doesn't really matter) application. I have a custom IHttpModule that's responsible for the PostAuthenticateRequest to change user principal & identity.

I'm storing UserID and UserName in authentication cookie when user logs-in. I have an IUser (implemented by DAO and Business Objects layer, each with their own additional members) that I need all over Business Service classes. When a user wants anything I have to provide IUser object instance (usually from Business Objects layer) so providing ID from the auth ticket isn't sufficient.

So I'm thinking of how and where would be best to persist logged in user's IUser data?

  1. I don't want to fetch it every time from the DB (based on authentication ticket's UserID data)
  2. I can't store it in Session since I have to work inside PostAuthenticateRequest, where Session isn't ready yet
  3. I want all the functionality to be encapsulated within my custom IHttpModule

Choices that I see:

  • Cache
  • Cookie
  • (Session) - by moving from PostAuthenticateRequest to PostAcquireRequestState event and change principal/identity there, but I'd like to avoid this

Processes that seem to complicate things are:

  1. User logs-in, user data is fetched from the DB and persisted somehow for later requests
  2. User logs-out, user data has to be removed from persisted medium automagically
  3. User changes own profile, user data has to be discarded and reread on next request from the DB

I wan't all these to be handled automatically by HttpModule (if possible) to eliminate developer's errors of forgetting to reset these things.

What I also don't want is to write/read some hardcoded variables/keys and manipulate them in other parts of the application. This would only present technical debt.

Questions

  1. What would you suggest?
  2. How does SO persist user data between requests?
like image 648
Robert Koritnik Avatar asked Aug 11 '09 23:08

Robert Koritnik


People also ask

What is caching and types of caching?

Caching is a mechanism to improve the performance of any type of application. Technically, caching is the process of storing and accessing data from a cache. But wait, what is a cache? A cache is a software or hardware component aimed at storing data so that future requests for the same data can be served faster.

What is caching What is the main requirement of caching?

A cache's primary purpose is to increase data retrieval performance by reducing the need to access the underlying slower storage layer. Trading off capacity for speed, a cache typically stores a subset of data transiently, in contrast to databases whose data is usually complete and durable.

When should you cache data?

Caches are generally used to keep track of frequent responses to user requests. It can also be used in the case of storing results of long computational operations. Caching is storing data in a location different than the main data source such that it's faster to access the data.

What are the different caching techniques available in .NET MVC?

Any (Default)- Content is cached in three locations- the Web Server, any proxy Servers and the Web Browser. Client- Content is cached on the Web Browser. Server- Content is cached on the Web Server. ServerAndClient- Content is cached on the Web Server and the Web Browser.


1 Answers

Given your requirements, I suppose the best solution is to retrieve the ID from the cookie and use it to index into the Http Cache (HttpContext.Current.Cache).

If you want to maintain how users access it, wrap the Cache in a "UserCache" object. The object could be constructed by an HttpModule and stored as a (wait for it...) singleton within the cache itself or, better yet, just constructed when needed to pull from the http cache. This would depend on where you need to access it and whether HttpContext.Current.Cache is directly available. The lazy implementation is below.

Again, this is for clarity and is not how I'd actually implement it.

public class UserCache
{
  public IUser GetUser(object userKey)
  {
    return HttpContext.Current.Cache[userKey];
  }

  public void AddUser(object userKey, IUser user)
  {
    /* this could pull the key from the user object as well. */
    HttpContext.Current.Cache.Add(/* add the object with key and a sliding expiration that is slightly greater than session timeout */);
  }

  public void ExpireUser(object userKey)
  {
    HttpContext.Current.Cache.Remove(userKey);
  }

  /* If you don't want to do SQL cache dependency */
  public void UpdateUser(object userKey, IUser user)
  {
    HttpContext.Current.Cache.Insert(/* ... */);
  }
}

Using the default caching mechanisms (or better yet a caching mechanism supplied by DI so you're not tied to an implementation), you can set an expiration to automatically remove users from the cache as mentioned in the comment. You can setup the cache to be dependent on SQL server updates as well to handle the updates or manually update it as part of the service to save changes.

More information about the default cache is available here. More information about cache dependencies is available here.

In the HttpModule itself, I suppose you could do some magic in the EndRequest event to see if the request is authenticated and then log the user out based on the cookie, but I'm not sure if that would work as I've never tried it. You might want to have a look at this article on MSDN from WAY back in the 1.1 days and see if it answers some of the problems you are trying to solve.

As for the SO architecture and how they do it, I'd imagine they load it when needed because they keep most of the database in RAM at all times (http://highscalability.com/stack-overflow-architecture).

like image 116
andymeadows Avatar answered Oct 13 '22 07:10

andymeadows