Varun Jain
Varun Jain

Reputation: 1911

Updating 'notifications' for a user with memcached

I have an application with user 'Notifications' think SO or facebook or twitter. However, as notifications won't necessarily change on every page view I decided to save them in memcached.

   def get_notification
     if current_user
       mc = Dalli::Client.new('localhost:11211')
       require_dependency 'notification.rb'
             @new_notification = mc.get(current_user.id.to_s+'new_notification')
             if  @new_notification == nil
              @new_notification = Notification.getNew(current_user.id)
              mc.set(current_user.id.to_s+'notification',@new_notification)
            end
     end
   end

I overlooked the obvious flaw in this implementation. Once the notifications are loaded they would never be refreshed until the user logs out or the cache entry expires. One way to do this is to negate the user's cache entry when a event for a new notification occurs. This would force a new request to the db. Is there any other way to implement this?

Upvotes: 0

Views: 661

Answers (1)

CuriousMind
CuriousMind

Reputation: 34155

  1. Currently you are manually connecting to Memchaced, check if key exists, store content, expire it. But as you may notice this gets tedious & repetitive very soon.
  2. However, Rails Provides you with few patterns that you can use to accomplish this but more easily.

First using Cache Stores option you can instruct rails to use Memchached

config.cache_store = :mem_cache_store, "example.com"

This cache store uses memcached server to provide a centralized cache for your application. Rails uses the bundled dalli gem by default. This is currently the most popular cache store for production websites. It can be used to provide a single, shared cache cluster with very a high performance and redundancy.

When initializing the cache, you need to specify the addresses for all memcached servers in your cluster. If none is specified, it will assume memcached is running on the local host on the default port, but this is not an ideal set up for larger sites.

The write and fetch methods on this cache accept two additional options that take advantage of features specific to memcached. You can specify :raw to send a value directly to the server with no serialization. The value must be a string or number. You can use memcached direct operation like increment and decrement only on raw values. You can also specify :unless_exist if you don't want memcached to overwrite an existing entry.

Using rails Cache store instead of directly using Dalli allows you to use the following Nicer API

Rails.cache.read('key')
Rails.cache.write('key', value)
Rails.cache.fetch('key') { value }

Now, rails for actually caching. you can use Declarative Etags or Fragment Caching to cache the notifications. here is an example using Declarative Etags

def get_notification
     if current_user
       @new_notification = Notification.getNew(current_user.id)
     end
    refresh_when @new_notification 
end

Now the way declarative E-tags works is Template is not rendered when request sends a matching ETag & cache copy is sent. However, when @new_notification changes the E-tag value will change too. Thus causing the cache to expire. Now, Caching is a vast topic to cover & there are variously techniques to do it. so probally I won't give you a full answers but I would point to the following resources so you can learn more:

Happy Caching ;-)

Upvotes: 1

Related Questions