background_cache 0.1.4 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -3,62 +3,79 @@ BackgroundCache
3
3
 
4
4
  Bust caches before your users do (in your Rails app).
5
5
 
6
+ Works with [memcache-client](https://github.com/mperham/memcache-client), [Dalli](https://github.com/mperham/dalli), or [memcached](https://github.com/fauna/memcached).
7
+
6
8
  Requirements
7
9
  ------------
8
10
 
9
- <pre>
10
- sudo gem install background_cache
11
- </pre>
12
-
13
- ### config/environment.rb
14
-
15
- <pre>
16
- config.gem 'background_cache'
17
- </pre>
11
+ gem install background_cache
18
12
 
19
13
  Dynamic Configuration
20
14
  ---------------------
21
15
 
22
- Create *lib/background\_cache\_config.rb*:
16
+ Create `lib/background_cache_config.rb` in your Rails app:
23
17
 
24
- <pre>
25
- BackgroundCache::Config.new do
18
+ BackgroundCache::Config.new do
26
19
 
27
- # Configure a background cache in one call
28
-
29
- Tag::League.find(:all).each do |tag|
30
- cache(
31
- # Route params
32
- :controller => 'sections',
33
- :action => 'teams',
34
- :tag => tag.permalink,
20
+ # Configure using block methods
35
21
 
36
- # Background cache options
37
- :group => 'every_hour',
38
- :layout => false,
39
- :only => "sections_teams_#{tag.permalink}"
40
- )
41
- end
42
-
43
- # Configure using block methods
44
-
45
- group('every_hour').layout(false).only("sections_teams_#{tag.permalink}") do
46
- Tag::League.find(:all).each do |tag|
47
- cache("/#{tag.permalink}")
48
- end
49
- end
50
- end
51
- </pre>
22
+ group('every_hour').layout(false).only("sections_teams_#{tag.permalink}") do
23
+ Tag::League.find(:all).each do |tag|
24
+ cache(:path => "/#{tag.permalink}")
25
+ end
26
+ end
52
27
 
53
- The <code>cache</code> method takes route parameters or a path.
28
+ # Configure using options
29
+
30
+ Tag::League.find(:all).each do |tag|
31
+ cache(
32
+ # Route params
33
+ :controller => 'sections',
34
+ :action => 'teams',
35
+ :tag => tag.permalink,
54
36
 
55
- The <code>only</code> and <code>except</code> methods/options take fragment ids or arrays of fragment ids.
37
+ # Or specify a path
38
+ :path => "/#{tag.permalink}",
39
+
40
+ # Background cache options
41
+ :group => 'every_hour',
42
+ :layout => false,
43
+ :only => "sections_teams_#{tag.permalink}"
44
+ )
45
+ end
46
+ end
47
+
48
+ The `only` and `except` options take cache fragment ids or arrays of cache fragment ids.
56
49
 
57
50
  If no fragment is specified, all of the action's caches will regenerate.
58
51
 
59
- Rake task
52
+ Rake Task
60
53
  ---------
61
54
 
62
- Add <code>rake background_cache</code> to cron. All cache configurations are busted every time it is run.
55
+ Add `rake background_cache` to cron. All cache configurations are busted every time it is run.
56
+
57
+ To run a specific group of caches, run `rake background_cache[every_hour]` (as per the example above).
58
+
59
+ Daemon Mode
60
+ -----------
61
+
62
+ Create `config/background_cache.yml` in your Rails app:
63
+
64
+ redis: localhost:6379/0
65
+
66
+ Start a `background_cache` daemon from your Rails app:
67
+
68
+ $ cd path/to/app
69
+ $ background_cache
70
+
71
+ Run caches via Ruby:
72
+
73
+ require 'background_cache'
74
+
75
+ client = BackgroundCache::Client.new('/path/to/app')
76
+
77
+ # Cache group
78
+ client.cache(:group => "every_hour")
63
79
 
64
- To run a specific group of caches, run <code>rake background\_cache[every\_hour]</code> (as per the example above).
80
+ # Manual cache
81
+ client.cache(:path => "/")
@@ -6,7 +6,7 @@ $:.unshift lib unless $:.include?(lib)
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "background_cache"
9
- s.version = '0.1.4'
9
+ s.version = '0.2.0'
10
10
  s.platform = Gem::Platform::RUBY
11
11
  s.authors = [ "Winton Welsh" ]
12
12
  s.email = [ "mail@wintoni.us" ]
@@ -22,4 +22,7 @@ Gem::Specification.new do |s|
22
22
  s.add_development_dependency "rack-test", "= 0.5.3"
23
23
  s.add_development_dependency "rails", "= 2.3.10"
24
24
  s.add_development_dependency "rspec", "~> 1.0"
25
+
26
+ s.add_dependency "redis", "~> 2.2.2"
27
+ s.add_dependency "yajl-ruby", "~> 1.0.0"
25
28
  end
data/bin/background_cache CHANGED
@@ -1,3 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require File.expand_path("../../lib/background_cache", __FILE__)
3
+ require File.expand_path("../../lib/background_cache/daemon", __FILE__)
4
+
5
+ BackgroundCache::Daemon.new(Dir.pwd)
@@ -0,0 +1,46 @@
1
+ module BackgroundCache
2
+ class Client
3
+
4
+ attr_reader :redis_1, :redis_2
5
+
6
+ def initialize(root)
7
+ if File.exists?(yaml = "#{root}/config/background_cache.yml")
8
+ options = YAML.load(File.read(yaml))
9
+ else
10
+ puts "\nFAIL: config/background_cache.yml not found"
11
+ shutdown
12
+ end
13
+
14
+ @redis_1 = Redis.connect(:url => "redis://#{options['redis']}")
15
+ @redis_2 = Redis.connect(:url => "redis://#{options['redis']}")
16
+ end
17
+
18
+ def cache(options)
19
+ wait = options.delete(:wait)
20
+ subscribe_to = options[:channel] = Digest::SHA1.hexdigest("#{rand}")
21
+ options = Yajl::Encoder.encode(options)
22
+ response = nil
23
+
24
+ if wait != false
25
+ Timeout.timeout(60) do
26
+ @redis_1.subscribe("background_cache:response:#{subscribe_to}") do |on|
27
+ on.subscribe do |channel, subscriptions|
28
+ @redis_2.rpush "background_cache:request", options
29
+ end
30
+
31
+ on.message do |channel, message|
32
+ if message.include?('[SUCCESS]')
33
+ response = true
34
+ @redis_1.unsubscribe
35
+ end
36
+ end
37
+ end
38
+ end
39
+ else
40
+ @redis_1.rpush "background_cache:request", options
41
+ end
42
+
43
+ response
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,89 @@
1
+ require 'rubygems'
2
+
3
+ require "digest/sha1"
4
+ require "timeout"
5
+ require "yaml"
6
+
7
+ gem "yajl-ruby", "~> 1.0.0"
8
+ require "yajl"
9
+
10
+ gem "redis", "~> 2.2.2"
11
+ require "redis"
12
+
13
+ module BackgroundCache
14
+ class Daemon
15
+
16
+ def initialize(root)
17
+ if File.exists?(yaml = "#{root}/config/background_cache.yml")
18
+ options = YAML.load(File.read(yaml))
19
+ else
20
+ puts "\nFAIL: config/background_cache.yml not found"
21
+ shutdown
22
+ end
23
+
24
+ puts "\nStarting background cache server (redis @ #{options['redis']})..."
25
+
26
+ require "#{root}/config/environment.rb"
27
+ require File.expand_path("../../background_cache", __FILE__)
28
+
29
+ instance = BackgroundCache.boot
30
+ redis = Redis.connect(:url => "redis://#{options['redis']}")
31
+ retries = 0
32
+
33
+ begin
34
+ while true
35
+ request = redis.lpop('background_cache:request')
36
+ if request
37
+ Timeout.timeout(60) do
38
+ request = Yajl::Parser.parse(request)
39
+ channel = request.delete('channel')
40
+
41
+ cache_key = request.to_a.sort { |a, b| a.first <=> b.first }.inspect
42
+
43
+ request.keys.each do |key|
44
+ request[(key.to_sym rescue key) || key] = request.delete(key)
45
+ end
46
+
47
+ unless redis.get(cache_key)
48
+ redis.set(cache_key, 1)
49
+
50
+ # Timeout incase execution fails
51
+ redis.expire(cache_key, 5 * 60)
52
+
53
+ if request[:group]
54
+ BackgroundCache.cache!(request[:group], instance)
55
+ else
56
+ BackgroundCache.manual(
57
+ BackgroundCache::Config.build_cache(request),
58
+ instance
59
+ )
60
+ end
61
+
62
+ redis.del(cache_key)
63
+ redis.publish(
64
+ "background_cache:response:#{channel}",
65
+ "[SUCCESS]"
66
+ )
67
+ end
68
+ end
69
+ end
70
+
71
+ sleep(1.0 / 1000.0)
72
+ end
73
+ rescue Interrupt
74
+ shut_down
75
+ rescue Exception => e
76
+ puts "\nError: #{e.message}"
77
+ puts "\t#{e.backtrace.join("\n\t")}"
78
+ retries += 1
79
+ shut_down if retries >= 10
80
+ retry
81
+ end
82
+ end
83
+
84
+ def shut_down
85
+ puts "\nShutting down background cache server..."
86
+ exit
87
+ end
88
+ end
89
+ end
@@ -1,10 +1,20 @@
1
+ require 'rubygems'
2
+
1
3
  gem 'rack-test', '=0.5.3'
2
4
 
5
+ gem "yajl-ruby", "~> 1.0.0"
6
+ require "yajl"
7
+
8
+ gem "redis", "~> 2.2.2"
9
+ require "redis"
10
+
3
11
  require 'digest/sha2'
4
12
  require 'rack/test'
13
+ require 'yaml'
5
14
 
6
15
  $:.unshift File.dirname(__FILE__)
7
16
 
17
+ require 'background_cache/client'
8
18
  require 'background_cache/config'
9
19
  require 'background_cache/controller'
10
20
  require 'background_cache/helper'
@@ -24,8 +34,10 @@ module BackgroundCache
24
34
  BackgroundCache::Config.current_cache
25
35
  end
26
36
 
27
- def self.cache!(group=nil)
28
- instance = self.boot
37
+ def self.cache!(group=nil, instance=nil)
38
+ unless instance
39
+ instance = self.boot
40
+ end
29
41
  BackgroundCache::Config.load!(group)
30
42
  caches = BackgroundCache::Config.caches
31
43
  caches.each do |cache|
data/rails/init.rb CHANGED
@@ -1,10 +1,8 @@
1
- begin
2
- require 'memcache'
3
- rescue LoadError
4
- end
5
-
6
1
  require File.expand_path('../../lib/background_cache.rb', __FILE__)
7
2
 
8
3
  ActionController::Base.send(:include, BackgroundCache::Controller)
9
4
  ActionView::Helpers::CacheHelper.send(:include, BackgroundCache::Helper)
10
- ::MemCache.send(:include, BackgroundCache::Memcache) if defined?(::MemCache)
5
+
6
+ ::Dalli::Client.send(:include, BackgroundCache::Memcache) if defined?(::Dalli::Client)
7
+ ::MemCache.send(:include, BackgroundCache::Memcache) if defined?(::MemCache)
8
+ ::Memcached::Rails.send(:include, BackgroundCache::Memcache) if defined?(::Memcached::Rails)
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: background_cache
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 23
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 1
9
- - 4
10
- version: 0.1.4
8
+ - 2
9
+ - 0
10
+ version: 0.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Winton Welsh
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-10-20 00:00:00 Z
18
+ date: 2011-10-24 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: rack-test
@@ -64,6 +64,38 @@ dependencies:
64
64
  version: "1.0"
65
65
  type: :development
66
66
  version_requirements: *id003
67
+ - !ruby/object:Gem::Dependency
68
+ name: redis
69
+ prerelease: false
70
+ requirement: &id004 !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ hash: 3
76
+ segments:
77
+ - 2
78
+ - 2
79
+ - 2
80
+ version: 2.2.2
81
+ type: :runtime
82
+ version_requirements: *id004
83
+ - !ruby/object:Gem::Dependency
84
+ name: yajl-ruby
85
+ prerelease: false
86
+ requirement: &id005 !ruby/object:Gem::Requirement
87
+ none: false
88
+ requirements:
89
+ - - ~>
90
+ - !ruby/object:Gem::Version
91
+ hash: 23
92
+ segments:
93
+ - 1
94
+ - 0
95
+ - 0
96
+ version: 1.0.0
97
+ type: :runtime
98
+ version_requirements: *id005
67
99
  description: Bust caches before your users do.
68
100
  email:
69
101
  - mail@wintoni.us
@@ -83,8 +115,10 @@ files:
83
115
  - bin/background_cache
84
116
  - init.rb
85
117
  - lib/background_cache.rb
118
+ - lib/background_cache/client.rb
86
119
  - lib/background_cache/config.rb
87
120
  - lib/background_cache/controller.rb
121
+ - lib/background_cache/daemon.rb
88
122
  - lib/background_cache/helper.rb
89
123
  - lib/background_cache/mem_cache.rb
90
124
  - rails/init.rb