redis-rack 1.6.0 → 2.0.0.pre
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.
- checksums.yaml +4 -4
- data/.travis.yml +3 -1
- data/Gemfile +1 -1
- data/README.md +48 -12
- data/lib/rack/session/redis.rb +40 -12
- data/lib/redis/rack/version.rb +1 -1
- data/redis-rack.gemspec +3 -2
- data/test/rack/session/redis_test.rb +252 -171
- data/test/redis/rack/version_test.rb +1 -1
- metadata +28 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 96a69ed4c43926e06dcf69e386e4de732d50015b
|
4
|
+
data.tar.gz: fe4d17f25dacea679c05bffd32d336b7b1c3d985
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fe09f61db9f21f3f7632dabf04cf1e88e0d30590d2bca9f285f874bc552046677c49631688ba077654a7ca89a6b9f3060545a771486e4ba8ac341698986286c8
|
7
|
+
data.tar.gz: 9ab90da88c6a1e56b5aa6e7d1c62bd773b33db189a41f0be5efe523f985aa30ec3c4d3821673f715c82a987dd036020f9470f934addfa6bb3d868700cb965725
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,14 +1,37 @@
|
|
1
|
-
# Redis
|
1
|
+
# Redis session store for Rack
|
2
2
|
|
3
|
-
__`redis-rack`__ provides a Redis
|
3
|
+
__`redis-rack`__ provides a Redis-backed session store for __Rack__.
|
4
|
+
|
5
|
+
See the main [redis-store readme] for general guidelines.
|
6
|
+
|
7
|
+
**NOTE:** This is not [redis-rack-cache][], the library for using Redis
|
8
|
+
as a backend store for the `Rack::Cache` HTTP cache. All this gem does
|
9
|
+
is store the Rack session within Redis.
|
10
|
+
|
11
|
+
[](http://travis-ci.org/jodosha/redis-rack?branch=master)
|
12
|
+
[](https://codeclimate.com/github/redis-store/redis-rack)
|
13
|
+
[](http://badge.fury.io/rb/redis-rack)
|
4
14
|
|
5
15
|
## Installation
|
6
16
|
|
17
|
+
Install with Bundler by adding the following to Gemfile:
|
18
|
+
|
7
19
|
```ruby
|
8
|
-
# Gemfile
|
9
20
|
gem 'redis-rack'
|
10
21
|
```
|
11
22
|
|
23
|
+
Then, run:
|
24
|
+
|
25
|
+
```shell
|
26
|
+
$ bundle install
|
27
|
+
```
|
28
|
+
|
29
|
+
Or, you can install it manually using RubyGems:
|
30
|
+
|
31
|
+
```shell
|
32
|
+
$ gem install redis-rack
|
33
|
+
```
|
34
|
+
|
12
35
|
## Usage
|
13
36
|
|
14
37
|
If you are using redis-store with Rails, consider using the [redis-rails gem](https://github.com/redis-store/redis-rails) instead. For standalone usage:
|
@@ -21,22 +44,35 @@ require 'rack/session/redis'
|
|
21
44
|
use Rack::Session::Redis
|
22
45
|
```
|
23
46
|
|
24
|
-
##
|
47
|
+
## Development
|
48
|
+
|
49
|
+
To install this gem for development purposes:
|
25
50
|
|
26
51
|
```shell
|
27
|
-
gem install bundler
|
28
|
-
git clone git://github.com/redis-store/redis-rack.git
|
29
|
-
cd redis-rack
|
30
|
-
bundle install
|
31
|
-
bundle exec rake
|
52
|
+
$ gem install bundler # note: you don't need to do this if you already have it installed
|
53
|
+
$ git clone git://github.com/redis-store/redis-rack.git
|
54
|
+
$ cd redis-rack
|
55
|
+
$ bundle install
|
32
56
|
```
|
33
57
|
|
34
|
-
|
58
|
+
## Running tests
|
35
59
|
|
36
|
-
|
60
|
+
To run tests:
|
37
61
|
|
38
|
-
|
62
|
+
```shell
|
63
|
+
$ bundle exec rake
|
64
|
+
```
|
65
|
+
|
66
|
+
If you are on **Snow Leopard** you have to run the following command to
|
67
|
+
build this software:
|
68
|
+
|
69
|
+
```shell
|
70
|
+
$ env ARCHFLAGS="-arch x86_64" bundle exec rake
|
71
|
+
```
|
39
72
|
|
40
73
|
## Copyright
|
41
74
|
|
42
75
|
2009 - 2013 Luca Guidi - [http://lucaguidi.com](http://lucaguidi.com), released under the MIT license
|
76
|
+
|
77
|
+
[redis-rack-cache]: https://github.com/redis-store/redis-rack-cache
|
78
|
+
[redis-store readme]: https://github.com/redis-store/redis-store
|
data/lib/rack/session/redis.rb
CHANGED
@@ -14,38 +14,58 @@ module Rack
|
|
14
14
|
super
|
15
15
|
|
16
16
|
@mutex = Mutex.new
|
17
|
-
@pool =
|
17
|
+
@pool = if @default_options[:pool]
|
18
|
+
raise "pool must be an instance of ConnectionPool" unless @default_options[:pool].is_a?(ConnectionPool)
|
19
|
+
@pooled = true
|
20
|
+
@default_options[:pool]
|
21
|
+
elsif [:pool_size, :pool_timeout].any? { |key| @default_options.has_key?(key) }
|
22
|
+
pool_options = {}
|
23
|
+
pool_options[:size] = options[:pool_size] if options[:pool_size]
|
24
|
+
pool_options[:timeout] = options[:pool_timeout] if options[:pool_timeout]
|
25
|
+
@pooled = true
|
26
|
+
::ConnectionPool.new(pool_options) { ::Redis::Store::Factory.create(@default_options[:redis_server]) }
|
27
|
+
else
|
28
|
+
@default_options.has_key?(:redis_store) ?
|
29
|
+
@default_options[:redis_store] :
|
30
|
+
::Redis::Store::Factory.create(@default_options[:redis_server])
|
31
|
+
|
32
|
+
end
|
18
33
|
end
|
19
34
|
|
20
|
-
def
|
35
|
+
def generate_unique_sid(session)
|
21
36
|
loop do
|
22
|
-
sid =
|
23
|
-
|
37
|
+
sid = generate_sid
|
38
|
+
first = with do |c|
|
39
|
+
[*c.setnx(sid, session, @default_options)].first
|
40
|
+
end
|
41
|
+
break sid if [1, true].include?(first)
|
24
42
|
end
|
25
43
|
end
|
26
44
|
|
27
45
|
def get_session(env, sid)
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
46
|
+
if env['rack.session.options'][:skip]
|
47
|
+
[generate_sid, {}]
|
48
|
+
else
|
49
|
+
with_lock(env, [nil, {}]) do
|
50
|
+
unless sid and session = with { |c| c.get(sid) }
|
51
|
+
session = {}
|
52
|
+
sid = generate_unique_sid(session)
|
33
53
|
end
|
54
|
+
[sid, session]
|
34
55
|
end
|
35
|
-
[sid, session]
|
36
56
|
end
|
37
57
|
end
|
38
58
|
|
39
59
|
def set_session(env, session_id, new_session, options)
|
40
60
|
with_lock(env, false) do
|
41
|
-
|
61
|
+
with { |c| c.set session_id, new_session, options }
|
42
62
|
session_id
|
43
63
|
end
|
44
64
|
end
|
45
65
|
|
46
66
|
def destroy_session(env, session_id, options)
|
47
67
|
with_lock(env) do
|
48
|
-
|
68
|
+
with { |c| c.del(session_id) }
|
49
69
|
generate_sid unless options[:drop]
|
50
70
|
end
|
51
71
|
end
|
@@ -63,6 +83,14 @@ module Rack
|
|
63
83
|
@mutex.unlock if @mutex.locked?
|
64
84
|
end
|
65
85
|
|
86
|
+
def with(&block)
|
87
|
+
if @pooled
|
88
|
+
@pool.with(&block)
|
89
|
+
else
|
90
|
+
block.call(@pool)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
66
94
|
end
|
67
95
|
end
|
68
96
|
end
|
data/lib/redis/rack/version.rb
CHANGED
data/redis-rack.gemspec
CHANGED
@@ -19,13 +19,14 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
20
|
s.require_paths = ["lib"]
|
21
21
|
|
22
|
-
s.add_runtime_dependency 'redis-store', '~> 1.2.0'
|
23
|
-
s.add_runtime_dependency 'rack', '
|
22
|
+
s.add_runtime_dependency 'redis-store', '~> 1.2.0.pre'
|
23
|
+
s.add_runtime_dependency 'rack', '> 1.5', '< 3'
|
24
24
|
|
25
25
|
s.add_development_dependency 'rake', '~> 10'
|
26
26
|
s.add_development_dependency 'bundler', '~> 1.3'
|
27
27
|
s.add_development_dependency 'mocha', '~> 0.14.0'
|
28
28
|
s.add_development_dependency 'minitest', '~> 5'
|
29
29
|
s.add_development_dependency 'redis-store-testing'
|
30
|
+
s.add_development_dependency 'connection_pool', '~> 1.2.0'
|
30
31
|
end
|
31
32
|
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
require 'rack/mock'
|
3
3
|
require 'thread'
|
4
|
+
require 'connection_pool'
|
4
5
|
|
5
6
|
describe Rack::Session::Redis do
|
6
7
|
session_key = Rack::Session::Redis::DEFAULT_OPTIONS[:key]
|
@@ -22,6 +23,10 @@ describe Rack::Session::Redis do
|
|
22
23
|
env['rack.session.options'][:defer] = true
|
23
24
|
incrementor.call(env)
|
24
25
|
end
|
26
|
+
skip_session = proc do |env|
|
27
|
+
env['rack.session.options'][:skip] = true
|
28
|
+
incrementor.call(env)
|
29
|
+
end
|
25
30
|
|
26
31
|
# # test Redis connection
|
27
32
|
# Rack::Session::Redis.new(incrementor)
|
@@ -32,6 +37,36 @@ describe Rack::Session::Redis do
|
|
32
37
|
# }.must_raise(Exception)
|
33
38
|
# end
|
34
39
|
|
40
|
+
it "can create it's own pool" do
|
41
|
+
session_store = Rack::Session::Redis.new(incrementor, pool_size: 5, pool_timeout: 10)
|
42
|
+
session_store.pool.class.must_equal ::ConnectionPool
|
43
|
+
session_store.pool.instance_variable_get(:@size).must_equal 5
|
44
|
+
end
|
45
|
+
|
46
|
+
it "can create it's own pool using default Redis server" do
|
47
|
+
session_store = Rack::Session::Redis.new(incrementor, pool_size: 5, pool_timeout: 10)
|
48
|
+
session_store.with { |connection| connection.to_s.must_match(/127\.0\.0\.1:6379 against DB 0 with namespace rack:session$/) }
|
49
|
+
end
|
50
|
+
|
51
|
+
it "can create it's own pool using provided Redis server" do
|
52
|
+
session_store = Rack::Session::Redis.new(incrementor, redis_server: 'redis://127.0.0.1:6380/1', pool_size: 5, pool_timeout: 10)
|
53
|
+
session_store.with { |connection| connection.to_s.must_match(/127\.0\.0\.1:6380 against DB 1$/) }
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
it "can use a supplied pool" do
|
58
|
+
session_store = Rack::Session::Redis.new(incrementor, pool: ::ConnectionPool.new(size: 1, timeout: 1) { ::Redis::Store::Factory.create("redis://127.0.0.1:6380/1")})
|
59
|
+
session_store.pool.class.must_equal ::ConnectionPool
|
60
|
+
session_store.pool.instance_variable_get(:@size).must_equal 1
|
61
|
+
end
|
62
|
+
|
63
|
+
it "uses the specified Redis store when provided" do
|
64
|
+
store = ::Redis::Store::Factory.create('redis://127.0.0.1:6380/1')
|
65
|
+
pool = Rack::Session::Redis.new(incrementor, :redis_store => store)
|
66
|
+
pool.pool.to_s.must_match(/127\.0\.0\.1:6380 against DB 1$/)
|
67
|
+
pool.pool.must_equal(store)
|
68
|
+
end
|
69
|
+
|
35
70
|
it "uses the default Redis server and namespace when not provided" do
|
36
71
|
pool = Rack::Session::Redis.new(incrementor)
|
37
72
|
pool.pool.to_s.must_match(/127\.0\.0\.1:6379 against DB 0 with namespace rack:session$/)
|
@@ -48,139 +83,162 @@ describe Rack::Session::Redis do
|
|
48
83
|
end
|
49
84
|
|
50
85
|
it "creates a new cookie" do
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
86
|
+
with_pool_management(incrementor) do |pool|
|
87
|
+
res = Rack::MockRequest.new(pool).get("/")
|
88
|
+
res["Set-Cookie"].must_include("#{session_key}=")
|
89
|
+
res.body.must_equal('{"counter"=>1}')
|
90
|
+
end
|
55
91
|
end
|
56
92
|
|
57
93
|
it "determines session from a cookie" do
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
94
|
+
with_pool_management(incrementor) do |pool|
|
95
|
+
req = Rack::MockRequest.new(pool)
|
96
|
+
res = req.get("/")
|
97
|
+
cookie = res["Set-Cookie"]
|
98
|
+
req.get("/", "HTTP_COOKIE" => cookie).
|
99
|
+
body.must_equal('{"counter"=>2}')
|
100
|
+
req.get("/", "HTTP_COOKIE" => cookie).
|
101
|
+
body.must_equal('{"counter"=>3}')
|
102
|
+
end
|
66
103
|
end
|
67
104
|
|
68
105
|
it "determines session only from a cookie by default" do
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
106
|
+
with_pool_management(incrementor) do |pool|
|
107
|
+
req = Rack::MockRequest.new(pool)
|
108
|
+
res = req.get("/")
|
109
|
+
sid = res["Set-Cookie"][session_match, 1]
|
110
|
+
req.get("/?rack.session=#{sid}").
|
111
|
+
body.must_equal('{"counter"=>1}')
|
112
|
+
req.get("/?rack.session=#{sid}").
|
113
|
+
body.must_equal('{"counter"=>1}')
|
114
|
+
end
|
77
115
|
end
|
78
116
|
|
79
117
|
it "determines session from params" do
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
118
|
+
with_pool_management(incrementor, :cookie_only => false) do |pool|
|
119
|
+
req = Rack::MockRequest.new(pool)
|
120
|
+
res = req.get("/")
|
121
|
+
sid = res["Set-Cookie"][session_match, 1]
|
122
|
+
req.get("/?rack.session=#{sid}").
|
123
|
+
body.must_equal('{"counter"=>2}')
|
124
|
+
req.get("/?rack.session=#{sid}").
|
125
|
+
body.must_equal('{"counter"=>3}')
|
126
|
+
end
|
88
127
|
end
|
89
128
|
|
90
129
|
it "survives nonexistant cookies" do
|
91
130
|
bad_cookie = "rack.session=blarghfasel"
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
131
|
+
with_pool_management(incrementor) do |pool|
|
132
|
+
res = Rack::MockRequest.new(pool).
|
133
|
+
get("/", "HTTP_COOKIE" => bad_cookie)
|
134
|
+
res.body.must_equal('{"counter"=>1}')
|
135
|
+
cookie = res["Set-Cookie"][session_match]
|
136
|
+
cookie.wont_match(/#{bad_cookie}/)
|
137
|
+
end
|
98
138
|
end
|
99
139
|
|
100
140
|
it "maintains freshness" do
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
141
|
+
with_pool_management(incrementor, :expire_after => 3) do |pool|
|
142
|
+
res = Rack::MockRequest.new(pool).get('/')
|
143
|
+
res.body.must_include('"counter"=>1')
|
144
|
+
cookie = res["Set-Cookie"]
|
145
|
+
sid = cookie[session_match, 1]
|
146
|
+
res = Rack::MockRequest.new(pool).get('/', "HTTP_COOKIE" => cookie)
|
147
|
+
res["Set-Cookie"][session_match, 1].must_equal(sid)
|
148
|
+
res.body.must_include('"counter"=>2')
|
149
|
+
puts 'Sleeping to expire session' if $DEBUG
|
150
|
+
sleep 4
|
151
|
+
res = Rack::MockRequest.new(pool).get('/', "HTTP_COOKIE" => cookie)
|
152
|
+
res["Set-Cookie"][session_match, 1].wont_equal(sid)
|
153
|
+
res.body.must_include('"counter"=>1')
|
154
|
+
end
|
114
155
|
end
|
115
156
|
|
116
157
|
it "does not send the same session id if it did not change" do
|
117
|
-
|
118
|
-
|
158
|
+
with_pool_management(incrementor) do |pool|
|
159
|
+
req = Rack::MockRequest.new(pool)
|
119
160
|
|
120
|
-
|
121
|
-
|
122
|
-
|
161
|
+
res0 = req.get("/")
|
162
|
+
cookie = res0["Set-Cookie"]
|
163
|
+
res0.body.must_equal('{"counter"=>1}')
|
123
164
|
|
124
|
-
|
125
|
-
|
126
|
-
|
165
|
+
res1 = req.get("/", "HTTP_COOKIE" => cookie)
|
166
|
+
res1["Set-Cookie"].must_be_nil
|
167
|
+
res1.body.must_equal('{"counter"=>2}')
|
127
168
|
|
128
|
-
|
129
|
-
|
130
|
-
|
169
|
+
res2 = req.get("/", "HTTP_COOKIE" => cookie)
|
170
|
+
res2["Set-Cookie"].must_be_nil
|
171
|
+
res2.body.must_equal('{"counter"=>3}')
|
172
|
+
end
|
131
173
|
end
|
132
174
|
|
133
175
|
it "deletes cookies with :drop option" do
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
176
|
+
with_pool_management(incrementor) do |pool|
|
177
|
+
req = Rack::MockRequest.new(pool)
|
178
|
+
drop = Rack::Utils::Context.new(pool, drop_session)
|
179
|
+
dreq = Rack::MockRequest.new(drop)
|
180
|
+
|
181
|
+
res1 = req.get("/")
|
182
|
+
session = (cookie = res1["Set-Cookie"])[session_match]
|
183
|
+
res1.body.must_equal('{"counter"=>1}')
|
184
|
+
|
185
|
+
res2 = dreq.get("/", "HTTP_COOKIE" => cookie)
|
186
|
+
res2["Set-Cookie"].must_be_nil
|
187
|
+
res2.body.must_equal('{"counter"=>2}')
|
188
|
+
|
189
|
+
res3 = req.get("/", "HTTP_COOKIE" => cookie)
|
190
|
+
res3["Set-Cookie"][session_match].wont_equal(session)
|
191
|
+
res3.body.must_equal('{"counter"=>1}')
|
192
|
+
end
|
150
193
|
end
|
151
194
|
|
152
195
|
it "provides new session id with :renew option" do
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
196
|
+
with_pool_management(incrementor) do |pool|
|
197
|
+
req = Rack::MockRequest.new(pool)
|
198
|
+
renew = Rack::Utils::Context.new(pool, renew_session)
|
199
|
+
rreq = Rack::MockRequest.new(renew)
|
200
|
+
|
201
|
+
res1 = req.get("/")
|
202
|
+
session = (cookie = res1["Set-Cookie"])[session_match]
|
203
|
+
res1.body.must_equal('{"counter"=>1}')
|
204
|
+
|
205
|
+
res2 = rreq.get("/", "HTTP_COOKIE" => cookie)
|
206
|
+
new_cookie = res2["Set-Cookie"]
|
207
|
+
new_session = new_cookie[session_match]
|
208
|
+
new_session.wont_equal(session)
|
209
|
+
res2.body.must_equal('{"counter"=>2}')
|
210
|
+
|
211
|
+
res3 = req.get("/", "HTTP_COOKIE" => new_cookie)
|
212
|
+
res3.body.must_equal('{"counter"=>3}')
|
213
|
+
|
214
|
+
# Old cookie was deleted
|
215
|
+
res4 = req.get("/", "HTTP_COOKIE" => cookie)
|
216
|
+
res4.body.must_equal('{"counter"=>1}')
|
217
|
+
end
|
174
218
|
end
|
175
219
|
|
176
220
|
it "omits cookie with :defer option" do
|
177
|
-
|
178
|
-
|
179
|
-
|
221
|
+
with_pool_management(incrementor) do |pool|
|
222
|
+
defer = Rack::Utils::Context.new(pool, defer_session)
|
223
|
+
dreq = Rack::MockRequest.new(defer)
|
224
|
+
|
225
|
+
res0 = dreq.get("/")
|
226
|
+
res0["Set-Cookie"].must_be_nil
|
227
|
+
res0.body.must_equal('{"counter"=>1}')
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
it "does not hit with :skip option" do
|
232
|
+
with_pool_management(incrementor) do |pool|
|
233
|
+
skip = Rack::Utils::Context.new(pool, skip_session)
|
234
|
+
sreq = Rack::MockRequest.new(skip)
|
235
|
+
|
236
|
+
pool.instance_variable_set('@pool', MiniTest::Mock.new)
|
180
237
|
|
181
|
-
|
182
|
-
|
183
|
-
|
238
|
+
res0 = sreq.get("/")
|
239
|
+
res0.body.must_equal('{"counter"=>1}')
|
240
|
+
assert pool.pool.verify
|
241
|
+
end
|
184
242
|
end
|
185
243
|
|
186
244
|
it "updates deep hashes correctly" do
|
@@ -194,17 +252,18 @@ describe Rack::Session::Redis do
|
|
194
252
|
end
|
195
253
|
[200, {}, [session.inspect]]
|
196
254
|
end
|
197
|
-
|
198
|
-
|
255
|
+
with_pool_management(hash_check) do |pool|
|
256
|
+
req = Rack::MockRequest.new(pool)
|
199
257
|
|
200
|
-
|
201
|
-
|
202
|
-
|
258
|
+
res0 = req.get("/")
|
259
|
+
session_id = (cookie = res0["Set-Cookie"])[session_match, 1]
|
260
|
+
ses0 = pool.with { |c| c.get(session_id) }
|
203
261
|
|
204
|
-
|
205
|
-
|
262
|
+
req.get("/", "HTTP_COOKIE" => cookie)
|
263
|
+
ses1 = pool.with { |c| c.get(session_id) }
|
206
264
|
|
207
|
-
|
265
|
+
ses1.wont_equal(ses0)
|
266
|
+
end
|
208
267
|
end
|
209
268
|
|
210
269
|
# anyone know how to do this better?
|
@@ -214,76 +273,98 @@ describe Rack::Session::Redis do
|
|
214
273
|
next
|
215
274
|
end
|
216
275
|
warn 'Running multithread test for Session::Redis'
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
276
|
+
with_pool_management(incrementor) do |pool|
|
277
|
+
req = Rack::MockRequest.new(pool)
|
278
|
+
|
279
|
+
res = req.get('/')
|
280
|
+
res.body.must_equal('{"counter"=>1}')
|
281
|
+
cookie = res["Set-Cookie"]
|
282
|
+
session_id = cookie[session_match, 1]
|
283
|
+
|
284
|
+
delta_incrementor = lambda do |env|
|
285
|
+
# emulate disconjoinment of threading
|
286
|
+
env['rack.session'] = env['rack.session'].dup
|
287
|
+
Thread.stop
|
288
|
+
env['rack.session'][(Time.now.usec*rand).to_i] = true
|
289
|
+
incrementor.call(env)
|
290
|
+
end
|
291
|
+
tses = Rack::Utils::Context.new pool, delta_incrementor
|
292
|
+
treq = Rack::MockRequest.new(tses)
|
293
|
+
tnum = rand(7).to_i+5
|
294
|
+
r = Array.new(tnum) do
|
295
|
+
Thread.new(treq) do |run|
|
296
|
+
run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true)
|
297
|
+
end
|
298
|
+
end.reverse.map{|t| t.run.join.value }
|
299
|
+
r.each do |request|
|
300
|
+
request['Set-Cookie'].must_equal(cookie)
|
301
|
+
request.body.must_include('"counter"=>2')
|
238
302
|
end
|
239
|
-
end.reverse.map{|t| t.run.join.value }
|
240
|
-
r.each do |request|
|
241
|
-
request['Set-Cookie'].must_equal(cookie)
|
242
|
-
request.body.must_include('"counter"=>2')
|
243
|
-
end
|
244
303
|
|
245
|
-
|
246
|
-
|
247
|
-
|
304
|
+
session = pool.with { |c| c.get(session_id) }
|
305
|
+
session.size.must_equal(tnum+1) # counter
|
306
|
+
session['counter'].must_equal(2) # meeeh
|
307
|
+
|
308
|
+
tnum = rand(7).to_i+5
|
309
|
+
r = Array.new(tnum) do |i|
|
310
|
+
app = Rack::Utils::Context.new pool, time_delta
|
311
|
+
req = Rack::MockRequest.new app
|
312
|
+
Thread.new(req) do |run|
|
313
|
+
run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true)
|
314
|
+
end
|
315
|
+
end.reverse.map{|t| t.run.join.value }
|
316
|
+
r.each do |request|
|
317
|
+
request['Set-Cookie'].must_equal(cookie)
|
318
|
+
request.body.must_include('"counter"=>3')
|
319
|
+
end
|
248
320
|
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
321
|
+
session = pool.with { |c| c.get(session_id) }
|
322
|
+
session.size.must_equal(tnum+1)
|
323
|
+
session['counter'].must_equal(3)
|
324
|
+
|
325
|
+
drop_counter = proc do |env|
|
326
|
+
env['rack.session'].delete 'counter'
|
327
|
+
env['rack.session']['foo'] = 'bar'
|
328
|
+
[200, {'Content-Type'=>'text/plain'}, env['rack.session'].inspect]
|
329
|
+
end
|
330
|
+
tses = Rack::Utils::Context.new pool, drop_counter
|
331
|
+
treq = Rack::MockRequest.new(tses)
|
332
|
+
tnum = rand(7).to_i+5
|
333
|
+
r = Array.new(tnum) do
|
334
|
+
Thread.new(treq) do |run|
|
335
|
+
run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true)
|
336
|
+
end
|
337
|
+
end.reverse.map{|t| t.run.join.value }
|
338
|
+
r.each do |request|
|
339
|
+
request['Set-Cookie'].must_equal(cookie)
|
340
|
+
request.body.must_include('"foo"=>"bar"')
|
255
341
|
end
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
342
|
+
|
343
|
+
session = pool.with { |c| c.get(session_id) }
|
344
|
+
session.size.must_equal(r.size+1)
|
345
|
+
session['counter'].must_be_nil
|
346
|
+
session['foo'].must_equal('bar')
|
260
347
|
end
|
348
|
+
end
|
261
349
|
|
262
|
-
|
263
|
-
|
264
|
-
|
350
|
+
private
|
351
|
+
def with_pool_management(*args)
|
352
|
+
yield simple(*args)
|
353
|
+
yield pooled(*args)
|
354
|
+
yield external_pooled(*args)
|
355
|
+
end
|
265
356
|
|
266
|
-
|
267
|
-
|
268
|
-
env['rack.session']['foo'] = 'bar'
|
269
|
-
[200, {'Content-Type'=>'text/plain'}, env['rack.session'].inspect]
|
357
|
+
def simple(app, options = {})
|
358
|
+
Rack::Session::Redis.new(app, options)
|
270
359
|
end
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
r.each do |request|
|
280
|
-
request['Set-Cookie'].must_equal(cookie)
|
281
|
-
request.body.must_include('"foo"=>"bar"')
|
360
|
+
|
361
|
+
def pooled(app, options = {})
|
362
|
+
Rack::Session::Redis.new(app, options)
|
363
|
+
Rack::Session::Redis.new(app, options.merge(pool_size: 5, pool_timeout: 10))
|
364
|
+
end
|
365
|
+
|
366
|
+
def external_pooled(app, options = {})
|
367
|
+
Rack::Session::Redis.new(app, options.merge(pool: ::ConnectionPool.new(size: 1, timeout: 1) { ::Redis::Store::Factory.create("redis://127.0.0.1:6380/1") }))
|
282
368
|
end
|
283
369
|
|
284
|
-
session = pool.pool.get(session_id)
|
285
|
-
session.size.must_equal(r.size+1)
|
286
|
-
session['counter'].must_be_nil
|
287
|
-
session['foo'].must_equal('bar')
|
288
|
-
end
|
289
370
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redis-rack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0.pre
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Luca Guidi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-05-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis-store
|
@@ -16,28 +16,34 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ~>
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 1.2.0
|
19
|
+
version: 1.2.0.pre
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ~>
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 1.2.0
|
26
|
+
version: 1.2.0.pre
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rack
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - '>'
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '1.5'
|
34
|
+
- - <
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '3'
|
34
37
|
type: :runtime
|
35
38
|
prerelease: false
|
36
39
|
version_requirements: !ruby/object:Gem::Requirement
|
37
40
|
requirements:
|
38
|
-
- -
|
41
|
+
- - '>'
|
39
42
|
- !ruby/object:Gem::Version
|
40
43
|
version: '1.5'
|
44
|
+
- - <
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '3'
|
41
47
|
- !ruby/object:Gem::Dependency
|
42
48
|
name: rake
|
43
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -108,6 +114,20 @@ dependencies:
|
|
108
114
|
- - '>='
|
109
115
|
- !ruby/object:Gem::Version
|
110
116
|
version: '0'
|
117
|
+
- !ruby/object:Gem::Dependency
|
118
|
+
name: connection_pool
|
119
|
+
requirement: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - ~>
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: 1.2.0
|
124
|
+
type: :development
|
125
|
+
prerelease: false
|
126
|
+
version_requirements: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - ~>
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: 1.2.0
|
111
131
|
description: Redis Store for Rack applications
|
112
132
|
email:
|
113
133
|
- me@lucaguidi.com
|
@@ -143,9 +163,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
143
163
|
version: '0'
|
144
164
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
145
165
|
requirements:
|
146
|
-
- - '
|
166
|
+
- - '>'
|
147
167
|
- !ruby/object:Gem::Version
|
148
|
-
version:
|
168
|
+
version: 1.3.1
|
149
169
|
requirements: []
|
150
170
|
rubyforge_project: redis-rack
|
151
171
|
rubygems_version: 2.5.2
|