A Write-Through Cacheing Library for ActiveRecord
A Write-Through Cacheing Library for ActiveRecord
Cache Money is a write-through and read-through caching library for ActiveRecord.
Read-Through: Queries like User.find(:all, :conditions => ...) will first look in Memcached and then look in the database for the results of that query. If there is a cache miss, it will populate the cache.
Write-Through: As objects are created, updated, and deleted, all of the caches are automatically kept up-to-date and coherent.
Many styles of ActiveRecord usage are supported:
User.findUser.find_by_idUser.find(:conditions => {:id => ...})User.find(:conditions => ['id = ?', ...])User.find(:conditions => 'id = ...')User.find(:conditions => 'users.id = ...')As you can see, the find_by_, find_all_by, hash, array, and string forms are all supported.
Queries with joins/includes are unsupported at this time. In general, any query involving just equality (=) and conjunction (AND) is supported by Cache Money. Disjunction (OR) and inequality (!=, 1000
In this example, only queries whose limit and offset are less than 1000 will use the cache.
class User :desc
end
The order declaration will ensure that the index is kept in the correctly sorted order. Only queries with order clauses compatible with the ordering in the index will use the cache:
Message.find(:all, :conditions => {:sender_id => ...}, :order => 'id DESC').Order clauses can be specified in many formats ("messages.id DESC", "messages.id DESC", and so forth), but ordering MUST be on the primary key column.
class Message :asc
end
will support queries like:
Message.find(:all, :conditions => {:sender_id => ...}, :order => 'id ASC')Message.find(:all, :conditions => {:sender_id => ...})Note that ascending order is implicit in index declarations (i.e., not specifying an order is the same as ascending). This is also true of queries (order is not nondeterministic as in MySQL).
class Message 500, :buffer => 100
end
With a limit attribute, indices will only store limit + buffer in the cache. As new objects are created the index will be truncated, and as objects are destroyed, the cache will be refreshed if it has fewer than the limit of items. The buffer is how many "extra" items to keep around in case of deletes.
It is particularly in conjunction with window indices that the :order attribute is useful.
Message.count(:all, :conditions => {:sender_id => ...}) will use the cache rather than the database. This happens for "free" -- no additional declarations are necessary.
class User $cache
end
Queries like User.find(1) will use the cache automatically. For more complex queries you must add indices on the attributes that you will query on. For example, a query like User.find(:all, :conditions => {:name => 'bob'}) will require an index like:
class User {:name => 'bob', :age => 26})`
class User < ActiveRecord::Base
index [:name, :age]
end
WARNING: This is currently a RELEASE CANDIDATE. A version of this code is in production use at Twitter but the extraction and refactoring process may have introduced bugs and/or performance problems. There are no known major defects at this point, but still.
Thanks to
No open issues yet, or sync has not completed.