background_cache 0.1.4 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +58 -41
- data/background_cache.gemspec +4 -1
- data/bin/background_cache +3 -1
- data/lib/background_cache/client.rb +46 -0
- data/lib/background_cache/daemon.rb +89 -0
- data/lib/background_cache.rb +14 -2
- data/rails/init.rb +4 -6
- metadata +39 -5
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
|
-
|
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
|
16
|
+
Create `lib/background_cache_config.rb` in your Rails app:
|
23
17
|
|
24
|
-
|
25
|
-
BackgroundCache::Config.new do
|
18
|
+
BackgroundCache::Config.new do
|
26
19
|
|
27
|
-
|
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
|
-
#
|
37
|
-
|
38
|
-
|
39
|
-
|
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
|
-
|
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
|
-
|
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
|
52
|
+
Rake Task
|
60
53
|
---------
|
61
54
|
|
62
|
-
Add
|
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
|
-
|
80
|
+
# Manual cache
|
81
|
+
client.cache(:path => "/")
|
data/background_cache.gemspec
CHANGED
@@ -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.
|
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
@@ -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
|
data/lib/background_cache.rb
CHANGED
@@ -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
|
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
|
-
|
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:
|
4
|
+
hash: 23
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
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-
|
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
|