sinatra-memcache 0.1.1

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.
@@ -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
+