Coder Social home page Coder Social logo

cachy's Introduction

Caching library to simplify and organize caching.

  • I18n (seperate caches by locale / expires all locales)
  • Generation based (your able expire all caches of one type)
  • Simultanouse caching (handle multiple processes trying to write same expensive cache at once)
  • Dependent caches (x caches result of cache z+y -> z changes -> x changes)
  • Hashed keys (optional -> short/unreadable)
  • Global cache_version (expire everything Cachy cached, but not e.g. sessions)
  • ...
  • works out of the box with Rails
  • works with pure Memcache, Redis and Moneta(-> Tokyo Cabinet / CouchDB / S3 / Berkeley DB / DataMapper / Memory store)

Install

gem install cachy

Usage

Cachy.cache

result = Cachy.cache(:a_key) { expensive() }
result = Cachy.cache(:a_key, expires_in: 1.minute) { expensive() }
result = Cachy.cache(:a_key, 'something else', Date.today.day) { expensive() }

Cache expensive operation that is run many times by many processes

Example: at application startup 20 processes try to set the same cache -> 20 heavy database requests -> database timeout -> cache still empty -> ... -> death

# 19 Processes get [], 1 makes the request -- when cached all get the same result
result = Cachy.cache(:a_key, while_running: []) { block_db_for_5_seconds }

Seperate version for each key

Expire all caches of one kind when code inside the cache has been updated

100.times{ Cachy.cache(:a_key, rand(100000) ) { expensive() } }
Cachy.increment_key(:a_key) # --> everything expired

Uses I18n.locale if available

Cachy.cache(:a_key) { 'English' }
I18n.locale = :de
Cachy.cache(:a_key) { 'German' } != 'English'

Explicitly not use I18n.locale

Cachy.cache(:a_key, witout_locale: true) { 'English' }
I18n.locale = :de
Cachy.cache(:a_key, witout_locale: true) { 'German' } == 'English'

Caching results of other caches

When inner cache is expired outer cache would normally still shows old results.
--> expire outer cache when inner cache is expired.

a = Cachy.cache(:a, expires_in: 1.day) { expensive() }
b = Cachy.cache(:b, expires_in: 1.week) { expensive_2() }
Cachy.cache(:surrounding, expires_in: 5.hours, keys: [:a, :b]) { a + b * c }
Cachy.increment_key(:b) # -->  expires :b and :surrounding

Hashing keys

In case they get to long for your caching backend, makes them short but unreadable.

Cachy.hash_keys = true  # global
Cachy.cache(:a_key, hash_key: true) { expensive } # per call

Uses .cache_key when available

E.g. ActiveRecord objects are stored in the key with their updated_at timestamp.
When they are updated the cache is automatically expired.

Cachy.cache(:my_key, User.first) { expensive }

Uses CACHE_VERSION if defined

Use a global CACHE_VERSION=1 so that all caches can be expired when something big changes. The cache server does not need to be restarted and session data(Rails) is saved.

Does not cache nil

If you want to cache a falsy result, use false (same goes for :while_running)

Cachy.cache(:x){ expensive || false }
Cachy.cache(:x, while_running: false) { expensive }

Cachy.cache_if

Only caches if condition is fulfilled

Cachy.cache_if(condition, :foo, 'bar', expires_in: 1.minute) {do_something}

Cachy.expire / .expire_view

Expires all locales of a key

Cachy.locales = [:de, :en] # by default filled with I18n.available_locales
Cachy.expire(:my_key) # --> expires for :de, :en and no-locale

#expire "views/#{key}" (counterpart for Rails-view-caching)
Cachy.expire_view(:my_key)
Cachy.expire(:my_key, prefix: 'views/')

Cachy.key

Use to cache e.g. Erb output

<% cache Cachy.key(:a_key), expires_in: 1.hour do %>
  More html ...
<% end %>

Cachy.cache_store

No ActionController::Base.cache_store ?
Give me something that responds to read/write(Rails style) or [] / store (Moneta) or get / set (Memcached)

Cachy.cache_store = some_cache

Cachy.locales

No I18n.available_locales ?

Cachy.locales = [:de, :en, :fr]

Memcache timeout protection

If Memcache timeouts keep killing your pages -> catch MemCache timeouts

TODO

  • optionally store dependent keys (keys: xxx), so that they can be setup up once and do not need to be remembered

Authors

Contributors

Michael Grosser
[email protected]
License: MIT
Build Status

cachy's People

Contributors

araishikeiwai avatar ggpeti avatar grosser avatar mindreframer avatar philly-mac avatar psychocandy avatar reneklacan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

cachy's Issues

expires_in does not work with Moneta cache store

It seems like Cachy does not expire the cache even after timeout (or may be I am using it incorrectly).

Look at this test that I added to existing tests for Cachy using Moneta cache store which is failing.

rajatjindal@8f1bde6

Your feedback will be highly appreciated.

It fails as follows:

C02PRUQFG8WP:cachy rjindal$ rake
rspec spec/
...............F.........................................*.................

Pending:
Cachy key_versions merges in old when setting new
# !!!!!
# ./spec/cachy_spec.rb:275

Failures:

  1. Cachy::MonetaWrapper expires on timeout
    Failure/Error: Cachy.cache(:timeout_key) { 'newkey' }.should_not == 'original'
    expected not: == "original"
    got: "original"

    ./spec/cachy/moneta_wrapper_spec.rb:63:in `block (2 levels) in <top (required)>'

Finished in 3.14 seconds
75 examples, 1 failure, 1 pending

Failed examples:

rspec ./spec/cachy/moneta_wrapper_spec.rb:60 # Cachy::MonetaWrapper expires on timeout

what am I doing wrong?

puts Cachy.cache(:hey, expires_in: 1) { Random.rand(100) }
sleep 5
puts Cachy.cache(:hey, expires_in: 1) { Random.rand(100) }

I expect to see two different numbers. However, I see the same numbers. Why the first one is not expired?

@grosser please, help me understand...

Possible to use File class as cache store with Cachy?

Is it possible to use a File class with the cache store? This line:

    121     @cache_store = wrap_cache(cache)
    122     @cache_store.write HEALTH_CHECK_KEY, 'yes'

causes wrong number of arguments for .write

/usr/local/rvm/gems/ruby-2.1.5/gems/cachy-0.4.1/lib/cachy.rb:122:in `write': wrong number of arguments (2 for 1) (ArgumentError)
	from /usr/local/rvm/gems/ruby-2.1.5/gems/cachy-0.4.1/lib/cachy.rb:122:in `cache_store='
	from ./tlaloc.rb:48:in `<main>'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.