Guest User

Untitled

a guest
Feb 19th, 2018
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.39 KB | None | 0 0
  1. merb-cache was rewritten with a few goals in mind:
  2. # make it modulular
  3. # define a public API
  4. # do the heavy lifting on key generation
  5. # 100% thread-safe
  6. # work with multiple caching layers through the same API
  7. # keep it hackable
  8.  
  9. h2. Stores
  10.  
  11. First and foremost, cache stores have been seperated into two families: fundamental stores and strategy stores. A fundamental store is any store that interacts directly with the persistence layer. The @FileStore@, for example, is a fundamental store that reads & writes cache entries to the file system. @MemcachedStore@ is also a fundamental store. They have almost identical functionality to the existing caching technique, only they implement a common API defined by @AbstractStore@.
  12.  
  13. The strategy store is the new kid on the block. A strategy store wraps one or more fundamental stores, acting as a middle man between caching requests. For example, if you need to save memory on your Memcache server, you could wrap your @MemcachedStore@ with a @GzipStore@. This would automatically compress the cached data when put into the cache, and decompressed on the way out. You can even wrap strategy caches with other strategy caches. In the last example, if you key was comprised of sensitive information, like a SSN, you might want to encrypt the key before storage. Wrapping your @GzipStore@ in a @SHA1Store@ would take care of that for you.
  14.  
  15. h2. Public API
  16.  
  17. The @AbstractStore@ class defines 9 methods as the API:
  18.  
  19. # @writable?(key, parameters = {}, conditions = {})@
  20. # @exists?(key, parameters = {})@
  21. # @read(key, parameters = {})@
  22. # @write(key, data = nil, parameters = {}, conditions = {})@
  23. # @write_all(key, data = nil, parameters = {}, conditions = {})@
  24. # @fetch(key, parameters = {}, conditions = {}, &blk)@
  25. # @delete(key, parameters = {})@
  26. # @delete_all@
  27. # @delete_all!@
  28.  
  29. @AbstractStrategyStore@ implements all of these with the exception of @delete_all@. If a strategy store can guarantee that calling @delete_all@ on it's wrapped store(s) will only delete entries populated by the strategy store, it may define the safe version of @delete_all@. However, this is usually not the case, hence @delete_all@ is not part of the public API for @AbstractStrategyStore@.
  30.  
  31. A more detailed documentation on each method can be found here: LINK
  32.  
  33. h2. Less Talk, More Code
  34.  
  35. So here's how you can setup and use merb-cache in your merb app:
  36.  
  37. h3. config/environments/development.rb
  38. <pre>
  39. <code lang='ruby'>
  40. # create a fundamental memcache store named :memcache for localhost
  41. Merb::Cache.setup(:memcache, Merb::Cache::MemcachedStore, {
  42. :namespace => "my_app",
  43. :servers => ["127.0.0.1:11211"]
  44. }
  45.  
  46. # a default FileStore
  47. Merb::Cache.setup(Merb::Cache::FileStore)
  48.  
  49. # another FileStore
  50. Merb::Cache.setup(:tmp_cache, Merb::Cache::FileStore, :dir => "/tmp")
  51. </code>
  52. </pre>
  53.  
  54. Now lets use these in a model:
  55.  
  56. h3. app/models/tag.rb
  57. <pre>
  58. <code lang='ruby'>
  59. class Tag
  60. #...
  61.  
  62. def find(parameters = {})
  63. # poor man's identity map
  64.  
  65. if Merb::Cache[:memcached].exists?("tags", parameters)
  66. Merb::Cache[:memcached].read("tags", parameters)
  67. else
  68. returning(super(parameters)) do |results|
  69. Merb::Cache[:memcached].write("tags", results, parameters)
  70. end
  71. end
  72. end
  73.  
  74. def popularity_rating
  75. # lets keep the popularity rating cached for 30 seconds
  76. # merb-cache will create a key from the model's id & the interval parameter
  77.  
  78. Merb::Cache[:memcache].fetch(self.id, :interval => Time.now.to_i / 30) do
  79. self.run_long_popularity_rating_query
  80. end
  81. end
  82. end
  83. </code>
  84. </pre>
  85.  
  86. Or, if you want to use memcache's built in expire option:
  87. <pre>
  88. <code lang='ruby'>
  89. # expire a cache entry for "bar" (identified by the key "foo" and
  90. # parameters {:baz => :bay}) in two hours
  91. Merb::Cache[:memcache].write("foo", "bar", {:baz => :bay}, :expire_in => 2.hours)
  92.  
  93. # this will fail, because FileStore cannot expire cache entries
  94. Merb::Cache[:default].write("foo", "bar", {:baz => :bay}, :expire_in => 2.hours)
  95.  
  96. # writing to the FileStore will fail, but the MemcachedStore will succeed
  97. Merb::Cache[:default, :memcache].write("foo", "bar", {:baz => :bay}, :expire_in => 2.hours)
  98.  
  99. # this will fail
  100. Merb::Cache[:default, :memcached].write_all("foo", "bar", {:baz => :bay}, :expire_in => 2.hours)
  101. </code>
  102. </pre>
  103.  
  104. h2. Strategy Stores
  105.  
  106. Setting up strategy stores is very similar to fundamental stores:
  107.  
  108. h3. config/environments/development.rb
  109. <pre>
  110. <code lang='ruby'>
  111. # wraps the :memcache store we setup earlier
  112. Merb::Cache.setup(:zipped, Merb::Cache::GzipStore[:memcache])
  113.  
  114. # wrap a strategy store
  115. Merb::Cache.setup(:sha_and_zip, Merb::Cache::SHA1Store[:zipped])
  116.  
  117. # you can even use unnamed fundamental stores
  118. Merb::Cache.setup(:zipped_images, Merb::Cache::GzipStore[Merb::Cache::FileStore],
  119. :dir => Merb.root / "public" / "images")
  120.  
  121.  
  122. # or a combination or strategy & fundamental stores
  123. module Merb::Cache #makes things a bit shorter
  124.  
  125. setup(:secured, SHA1Store[GzipStore[FileStore], FileStore],
  126. :dir => Merb.root / "private")
  127. end
  128. </code>
  129. </pre>
  130.  
  131. You can use these strategy stores exactly like fundamental stores in your app code.
  132.  
  133. h4. Action & Page Caching
  134.  
  135. Action & page caching have been implemented in strategy stores. So instead of manually specifying which type of caching you want for each action, you simply ask merb-cache to cache your action, and merb-cache will use the fastest available cache.
  136.  
  137. First, let's setup our page & action stores:
  138.  
  139. h3. config/environments/development.rb
  140. <pre>
  141. <code lang='ruby'>
  142. # the order that stores are setup is important
  143. # faster stores should be setup first
  144.  
  145. # page cache to the public dir
  146. Merb::Cache.setup(:page_store, Merb::Cache::PageCache[FileStore],
  147. :dir => Merb.root / "public")
  148.  
  149. # action cache to memcache
  150. Merb::Cache.setup(:action_store, Merb::Cache::ActionCache[:sha_and_zip])
  151. </code>
  152. </pre>
  153.  
  154. And now in our controller:
  155. <pre>
  156. <code lang='ruby'>
  157. class Tags < Merb::Controller
  158.  
  159. # index & show will be page cached to the public dir. The index
  160. # action has no parameters, and the show parameter's are part of
  161. # the query string, making them both page-cache'able
  162. cache :index, :show
  163.  
  164. def index
  165. render
  166. end
  167. </code>
  168. </pre>
Add Comment
Please, Sign In to add comment