sinatra-memcache 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,71 @@
1
+ h1. Sinatra-MemCache
2
+
3
+ h2. Dependencies
4
+
5
+ memcache-client
6
+
7
+ zlib
8
+
9
+ h2. Install
10
+
11
+ <pre>
12
+ sudo gem install gioext-sinatra-memcache
13
+ </pre>
14
+
15
+ h2. Example
16
+
17
+ <pre>
18
+ require 'rubygems'
19
+ require 'sinatra'
20
+ require 'sinatra/memcache'
21
+
22
+ # cache
23
+ get '/cache1' do
24
+ cache 'cache1' do
25
+ sleep(5)
26
+ 'Hello Cache1'
27
+ end
28
+ end
29
+
30
+ # args
31
+ get '/cache2' do
32
+ cache 'cache2', :expiry => 10, :compress => true do
33
+ sleep(3)
34
+ 'Hello Cache2'
35
+ end
36
+ end
37
+
38
+ # cache object
39
+ get '/obj' do
40
+ hash = cache 'obj' do
41
+ sleep(2)
42
+ { :a => 'Hello Object' }
43
+ end
44
+ hash[:a]
45
+ end
46
+
47
+ # expire
48
+ get '/expire' do
49
+ expire 'cache1'
50
+ expire /^cache/
51
+ expire //
52
+ 'Hello Expire'
53
+ end
54
+
55
+ # default options
56
+ set :cache_server, "localhost:11211"
57
+ set :cache_namespace, "sinatra-memcache"
58
+ set :cache_enable, true
59
+ set :cache_logging, true
60
+ set :cache_default_expiry, 3600
61
+ set :cache_default_compress, false
62
+ </pre>
63
+
64
+ h2. License
65
+
66
+ Copyright (c) 2009 Kazuki UCHIDA
67
+
68
+ Licensed under the MIT License:
69
+
70
+ - http://www.opensource.org/licenses/mit-license.php
71
+
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'spec/rake/spectask'
3
+
4
+ task :default => :spec
5
+
6
+ desc "Run all specs in spec directory"
7
+ Spec::Rake::SpecTask.new(:spec) do |t|
8
+ t.spec_opts = ['--color', '--format specdoc']
9
+ t.spec_files = FileList['spec/**/*_spec.rb']
10
+ end
@@ -0,0 +1,141 @@
1
+ require 'memcache'
2
+ require 'zlib'
3
+
4
+ class MemCache
5
+ def all_keys
6
+ raise MemCacheError, "No active servers" unless active?
7
+ keys = []
8
+
9
+ @servers.each do |server|
10
+ sock = server.socket
11
+ raise MemCacheError, "No connection to server" if sock.nil?
12
+
13
+ begin
14
+ sock.write "stats items\r\n"
15
+ slabs = {}
16
+ while line = sock.gets
17
+ break if line == "END\r\n"
18
+ slabs[$1] = $2 if line =~ /^STAT items:(\d+):number (\d+)/
19
+ end
20
+
21
+ slabs.each do |k, v|
22
+ sock.write "stats cachedump #{k} #{v}\r\n"
23
+ while line = sock.gets
24
+ break if line == "END\r\n"
25
+ prefix = @namespace.empty? ? '' : "#{@namespace}:"
26
+ r = Regexp.new("^ITEM #{prefix}([^\s]+)")
27
+ keys << $1 if line =~ r
28
+ end
29
+ end
30
+ rescue SocketError, SystemCallError, IOError => err
31
+ server.close
32
+ raise MemCacheError, err.message
33
+ end
34
+ end
35
+
36
+ keys
37
+ end
38
+ end
39
+
40
+ module Sinatra
41
+ module MemCache
42
+ module Helpers
43
+
44
+ #
45
+ #
46
+ #
47
+ def cache(key, params = {}, &block)
48
+ return block.call unless settings.cache_enable
49
+
50
+ opts = {
51
+ :expiry => settings.cache_default_expiry,
52
+ :compress => settings.cache_default_compress
53
+ }.merge(params)
54
+
55
+ value = get(key, opts)
56
+ return value unless block_given?
57
+
58
+ if value
59
+ log "Get: #{key}"
60
+ value
61
+ else
62
+ log "Set: #{key}"
63
+ set(key, block.call, opts)
64
+ end
65
+ rescue => e
66
+ throw e if settings.development? || settings.show_exceptions
67
+ block.call
68
+ end
69
+
70
+ #
71
+ #
72
+ #
73
+ def expire(p)
74
+ return unless settings.cache_enable
75
+
76
+ case p
77
+ when String
78
+ expire_key(p)
79
+ when Regexp
80
+ expire_regexp(p)
81
+ end
82
+ true
83
+ rescue => e
84
+ throw e if settings.development? or settings.show_exceptions
85
+ false
86
+ end
87
+
88
+ private
89
+
90
+ def client
91
+ settings.cache_client ||= ::MemCache.new settings.cache_server,
92
+ :namespace => settings.cache_namespace
93
+ end
94
+
95
+ def log(msg)
96
+ puts "[sinatra-memcache] #{msg}" if settings.cache_logging
97
+ end
98
+
99
+ def get(key, opts)
100
+ v = client[key, true]
101
+ return v unless v
102
+
103
+ v = Zlib::Inflate.inflate(v) if opts[:compress]
104
+ Marshal.load(v)
105
+ end
106
+
107
+ def set(key, value, opts)
108
+ v = Marshal.dump(value)
109
+ v = Zlib::Deflate.deflate(v) if opts[:compress]
110
+ client.set(key, v, opts[:expiry], true)
111
+ value
112
+ end
113
+
114
+ def expire_key(key)
115
+ client.delete(key)
116
+ log "Expire: #{key}"
117
+ end
118
+
119
+ def expire_regexp(re)
120
+ keys = client.all_keys
121
+ keys.each do |key|
122
+ expire_key(key) if key =~ re
123
+ end
124
+ end
125
+ end
126
+
127
+ def self.registered(app)
128
+ app.helpers MemCache::Helpers
129
+
130
+ app.set :cache_client, nil
131
+ app.set :cache_server, "localhost:11211"
132
+ app.set :cache_namespace, "sinatra-memcache"
133
+ app.set :cache_enable, true
134
+ app.set :cache_logging, true
135
+ app.set :cache_default_expiry, 3600
136
+ app.set :cache_default_compress, false
137
+ end
138
+ end
139
+
140
+ register MemCache
141
+ end
@@ -0,0 +1,49 @@
1
+ require 'rubygems'
2
+ require 'sinatra'
3
+ require File.dirname(__FILE__) + '/../lib/sinatra/memcache'
4
+
5
+ get '/' do
6
+ "Hello World"
7
+ end
8
+
9
+ get '/cache' do
10
+ cache "cache" do
11
+ "Hello World"
12
+ end
13
+ end
14
+
15
+ get '/cache2' do
16
+ cache "cache2", :expiry => 1 do
17
+ "Hello World"
18
+ end
19
+ end
20
+
21
+ get '/read' do
22
+ cache 'cache'
23
+ end
24
+
25
+ get '/compress' do
26
+ cache "compress", :compress => true do
27
+ "Hello Compress"
28
+ end
29
+ end
30
+
31
+ get '/object' do
32
+ hash = cache "object" do
33
+ { :a => 'hello a', :b => 'hello b' }
34
+ end
35
+ hash[:a] + ' ' + hash[:b]
36
+ end
37
+
38
+ get '/expire' do
39
+ expire "cache"
40
+ end
41
+
42
+ get '/expire_re' do
43
+ expire //
44
+ end
45
+
46
+ configure do
47
+ set :cache_namespace, "test"
48
+ set :cache_logging, false
49
+ end
@@ -0,0 +1,73 @@
1
+ require File.dirname(__FILE__) + '/fixture'
2
+ require 'rack/test'
3
+
4
+ include Rack::Test::Methods
5
+ def app
6
+ Sinatra::Application
7
+ end
8
+
9
+ describe 'Sinatra-MemCache' do
10
+ before do
11
+ @client = MemCache.new 'localhost:11211', :namespace => "test"
12
+ end
13
+
14
+ it "indexのレスポンスが正しいこと" do
15
+ get '/'
16
+ last_response.ok?.should be_true
17
+ last_response.body.should == "Hello World"
18
+ end
19
+
20
+ it "cacheしたときのレスポンスが正しいこと" do
21
+ get '/cache'
22
+ last_response.ok?.should be_true
23
+ last_response.body.should == "Hello World"
24
+ end
25
+
26
+ it "cacheした内容が正しいこと" do
27
+ get '/cache'
28
+ Marshal.load(@client['cache', true]).should == "Hello World"
29
+ end
30
+
31
+ it "ブロック無しで読み取りのみできること" do
32
+ get '/cache'
33
+ get '/read'
34
+ last_response.ok?.should be_true
35
+ last_response.body.should == "Hello World"
36
+ end
37
+
38
+ it "cacheした内容がexpireされること" do
39
+ get '/cache'
40
+ get '/expire'
41
+ @client['cache'].should be_nil
42
+ end
43
+
44
+ it "cacheが有効時間後にexpireされること" do
45
+ get '/cache2'
46
+ sleep(1)
47
+ @client['cache2'].should be_nil
48
+ end
49
+
50
+ it "compressが有効であること" do
51
+ get '/compress'
52
+ last_response.ok?.should be_true
53
+ last_response.body.should == "Hello Compress"
54
+ @client['compress', true].should == Zlib::Deflate.deflate(Marshal.dump('Hello Compress'))
55
+ end
56
+
57
+ it "オブジェクトがcacheされること" do
58
+ get '/object'
59
+ last_response.ok?.should be_true
60
+ last_response.body.should == "hello a hello b"
61
+ Marshal.load(@client['object', true]).should == { :a => 'hello a', :b => 'hello b' }
62
+ end
63
+
64
+ it "全てのcacheがexpireされること" do
65
+ get '/cache'
66
+ get '/cache2'
67
+ get '/compress'
68
+ get '/expire_re'
69
+ @client['cache'].should be_nil
70
+ @client['cache2'].should be_nil
71
+ @client['compress'].should be_nil
72
+ end
73
+ end
metadata ADDED
@@ -0,0 +1,98 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sinatra-memcache
3
+ version: !ruby/object:Gem::Version
4
+ hash: 25
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 1
10
+ version: 0.1.1
11
+ platform: ruby
12
+ authors:
13
+ - gioext
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-05-30 00:00:00 +02:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: sinatra
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: memcache-client
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :runtime
48
+ version_requirements: *id002
49
+ description:
50
+ email: gioext@gmail.com
51
+ executables: []
52
+
53
+ extensions: []
54
+
55
+ extra_rdoc_files: []
56
+
57
+ files:
58
+ - Rakefile
59
+ - README.textile
60
+ - lib/sinatra/memcache.rb
61
+ - spec/sinatra-memcache_spec.rb
62
+ - spec/fixture.rb
63
+ has_rdoc: true
64
+ homepage: http://github.com/felix/sinatra-memcache
65
+ licenses: []
66
+
67
+ post_install_message:
68
+ rdoc_options: []
69
+
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ hash: 3
78
+ segments:
79
+ - 0
80
+ version: "0"
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ hash: 3
87
+ segments:
88
+ - 0
89
+ version: "0"
90
+ requirements: []
91
+
92
+ rubyforge_project:
93
+ rubygems_version: 1.3.7
94
+ signing_key:
95
+ specification_version: 3
96
+ summary: Cache extension on Sinatra, updated for Sinatra 1.0 by felix
97
+ test_files: []
98
+