aws-sessionstore-dynamodb 1.0.0 → 2.0.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.
- checksums.yaml +5 -5
- data/.github/PULL_REQUEST_TEMPLATE.md +6 -0
- data/.gitignore +1 -0
- data/.gitmodules +3 -0
- data/.travis.yml +16 -5
- data/.yardopts +3 -2
- data/CHANGELOG.md +24 -0
- data/CODE_OF_CONDUCT.md +4 -0
- data/CONTRIBUTING.md +61 -0
- data/Gemfile +7 -19
- data/{LICENSE.txt → LICENSE} +0 -0
- data/README.md +17 -63
- data/Rakefile +37 -14
- data/VERSION +1 -0
- data/aws-sessionstore-dynamodb.gemspec +7 -5
- data/doc-src/templates/default/layout/html/footer.erb +10 -0
- data/doc-src/templates/default/layout/html/layout.erb +31 -0
- data/lib/aws-sessionstore-dynamodb.rb +0 -15
- data/lib/aws/session_store/dynamo_db/configuration.rb +2 -29
- data/lib/aws/session_store/dynamo_db/errors/base_handler.rb +0 -14
- data/lib/aws/session_store/dynamo_db/errors/default_handler.rb +0 -14
- data/lib/aws/session_store/dynamo_db/garbage_collection.rb +2 -15
- data/lib/aws/session_store/dynamo_db/invalid_id_error.rb +0 -14
- data/lib/aws/session_store/dynamo_db/lock_wait_timeout_error.rb +0 -14
- data/lib/aws/session_store/dynamo_db/locking/base.rb +14 -17
- data/lib/aws/session_store/dynamo_db/locking/null.rb +0 -14
- data/lib/aws/session_store/dynamo_db/locking/pessimistic.rb +0 -16
- data/lib/aws/session_store/dynamo_db/missing_secret_key_error.rb +0 -14
- data/lib/aws/session_store/dynamo_db/rack_middleware.rb +11 -24
- data/lib/aws/session_store/dynamo_db/table.rb +1 -14
- data/lib/aws/session_store/dynamo_db/version.rb +1 -15
- data/spec/aws/session_store/dynamo_db/app_config.yml +6 -6
- data/spec/aws/session_store/dynamo_db/configuration_spec.rb +28 -51
- data/spec/aws/session_store/dynamo_db/error/default_error_handler_spec.rb +23 -21
- data/spec/aws/session_store/dynamo_db/garbage_collection_spec.rb +68 -69
- data/spec/aws/session_store/dynamo_db/locking/threaded_sessions_spec.rb +17 -16
- data/spec/aws/session_store/dynamo_db/rack_middleware_database_spec.rb +47 -46
- data/spec/aws/session_store/dynamo_db/rack_middleware_spec.rb +59 -61
- data/spec/aws/session_store/dynamo_db/table_spec.rb +9 -7
- data/spec/spec_helper.rb +14 -11
- metadata +27 -29
- data/lib/aws/session_store/dynamo_db/railtie.rb +0 -28
- data/lib/aws/session_store/dynamo_db/tasks/session_table.rake +0 -21
- data/lib/rails/generators/sessionstore/dynamodb/dynamodb_generator.rb +0 -55
- data/lib/rails/generators/sessionstore/dynamodb/templates/sessionstore/USAGE +0 -13
- data/lib/rails/generators/sessionstore/dynamodb/templates/sessionstore/dynamodb.yml +0 -71
- data/lib/rails/generators/sessionstore/dynamodb/templates/sessionstore_migration.rb +0 -10
- data/spec/aws/session_store/dynamo_db/config/dynamo_db_session.yml +0 -24
- data/spec/aws/session_store/dynamo_db/rails_app_config.yml +0 -24
- data/tasks/test.rake +0 -29
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Copyright 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
4
|
#
|
3
5
|
# Licensed under the Apache License, Version 2.0 (the "License"). You
|
@@ -11,7 +13,6 @@
|
|
11
13
|
# ANY KIND, either express or implied. See the License for the specific
|
12
14
|
# language governing permissions and limitations under the License.
|
13
15
|
|
14
|
-
|
15
16
|
require 'spec_helper'
|
16
17
|
|
17
18
|
describe Aws::SessionStore::DynamoDB do
|
@@ -20,43 +21,44 @@ describe Aws::SessionStore::DynamoDB do
|
|
20
21
|
instance_exec(&ConstantHelpers)
|
21
22
|
|
22
23
|
before do
|
23
|
-
@options = { :
|
24
|
+
@options = { dynamo_db_client: client, secret_key: 'meltingbutter' }
|
24
25
|
end
|
25
26
|
|
26
27
|
let(:base_app) { MultiplierApplication.new }
|
27
28
|
let(:app) { Aws::SessionStore::DynamoDB::RackMiddleware.new(base_app, @options) }
|
28
29
|
let(:client) { double('Aws::DynamoDB::Client') }
|
29
30
|
|
30
|
-
context
|
31
|
-
it
|
32
|
-
client.
|
33
|
-
|
31
|
+
context 'Error handling for Rack Middleware with default error handler' do
|
32
|
+
it 'raises error for missing secret key' do
|
33
|
+
allow(client).to receive(:update_item).and_raise(missing_key_error)
|
34
|
+
expect { get '/' }.to raise_error(missing_key_error)
|
34
35
|
end
|
35
36
|
|
36
|
-
it
|
37
|
-
client.
|
38
|
-
|
37
|
+
it 'catches exception for inaccurate table name and raises error ' do
|
38
|
+
allow(client).to receive(:update_item).and_raise(resource_error)
|
39
|
+
expect { get '/' }.to raise_error(resource_error)
|
39
40
|
end
|
40
41
|
|
41
|
-
it
|
42
|
-
client.
|
43
|
-
client.
|
44
|
-
|
45
|
-
|
42
|
+
it 'catches exception for inaccurate table key' do
|
43
|
+
allow(client).to receive(:update_item).and_raise(key_error)
|
44
|
+
allow(client).to receive(:get_item).and_raise(key_error)
|
45
|
+
|
46
|
+
get '/'
|
47
|
+
expect(last_request.env['rack.errors'].string).to include(key_error_msg)
|
46
48
|
end
|
47
49
|
end
|
48
50
|
|
49
|
-
context
|
50
|
-
it
|
51
|
+
context 'Test ExceptionHandler with true as return value for handle_error' do
|
52
|
+
it 'raises all errors' do
|
51
53
|
@options[:raise_errors] = true
|
52
|
-
client.
|
53
|
-
|
54
|
+
allow(client).to receive(:update_item).and_raise(client_error)
|
55
|
+
expect { get '/' }.to raise_error(client_error)
|
54
56
|
end
|
55
57
|
|
56
|
-
it
|
58
|
+
it 'catches exception for inaccurate table key and raises error' do
|
57
59
|
@options[:raise_errors] = true
|
58
|
-
client.
|
59
|
-
|
60
|
+
allow(client).to receive(:update_item).and_raise(key_error)
|
61
|
+
expect { get '/' }.to raise_error(key_error)
|
60
62
|
end
|
61
63
|
end
|
62
64
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Copyright 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
4
|
#
|
3
5
|
# Licensed under the Apache License, Version 2.0 (the "License"). You
|
@@ -14,80 +16,79 @@
|
|
14
16
|
require 'spec_helper'
|
15
17
|
|
16
18
|
describe Aws::SessionStore::DynamoDB::GarbageCollection do
|
17
|
-
def
|
18
|
-
|
19
|
-
|
20
|
-
|
19
|
+
def items(min, max)
|
20
|
+
items = []
|
21
|
+
(min..max).each do |i|
|
22
|
+
items << { 'session_id' => { s: i.to_s } }
|
21
23
|
end
|
22
|
-
|
24
|
+
items
|
23
25
|
end
|
24
26
|
|
25
27
|
def format_scan_result
|
26
|
-
|
27
|
-
|
28
|
-
|
28
|
+
items = []
|
29
|
+
(31..49).each do |i|
|
30
|
+
items << { 'session_id' => { s: i.to_s } }
|
29
31
|
end
|
30
32
|
|
31
|
-
|
32
|
-
rqst_array << {:
|
33
|
-
rqst_array
|
33
|
+
items.each_with_object([]) do |item, rqst_array|
|
34
|
+
rqst_array << { delete_request: { key: item } }
|
34
35
|
end
|
35
36
|
end
|
36
37
|
|
37
38
|
def collect_garbage
|
38
|
-
options = { :
|
39
|
+
options = { dynamo_db_client: dynamo_db_client, max_age: 100, max_stale: 100 }
|
39
40
|
Aws::SessionStore::DynamoDB::GarbageCollection.collect_garbage(options)
|
40
41
|
end
|
41
42
|
|
42
|
-
let(:scan_resp1)
|
43
|
+
let(:scan_resp1) do
|
43
44
|
resp = {
|
44
|
-
:
|
45
|
-
:
|
46
|
-
:
|
47
|
-
:
|
45
|
+
items: items(0, 49),
|
46
|
+
count: 50,
|
47
|
+
scanned_count: 1000,
|
48
|
+
last_evaluated_key: {}
|
48
49
|
}
|
49
|
-
|
50
|
+
end
|
50
51
|
|
51
|
-
let(:scan_resp2)
|
52
|
+
let(:scan_resp2) do
|
52
53
|
{
|
53
|
-
:
|
54
|
-
:
|
54
|
+
items: items(0, 31),
|
55
|
+
last_evaluated_key: { 'session_id' => { s: '31' } }
|
55
56
|
}
|
56
|
-
|
57
|
+
end
|
57
58
|
|
58
|
-
let(:scan_resp3)
|
59
|
+
let(:scan_resp3) do
|
59
60
|
{
|
60
|
-
:
|
61
|
-
:
|
61
|
+
items: items(31, 49),
|
62
|
+
last_evaluated_key: {}
|
62
63
|
}
|
63
|
-
|
64
|
+
end
|
64
65
|
|
65
|
-
let(:write_resp1)
|
66
|
+
let(:write_resp1) do
|
66
67
|
{
|
67
|
-
:
|
68
|
+
unprocessed_items: {}
|
68
69
|
}
|
69
|
-
|
70
|
+
end
|
70
71
|
|
71
|
-
let(:write_resp2)
|
72
|
+
let(:write_resp2) do
|
72
73
|
{
|
73
|
-
:
|
74
|
-
|
74
|
+
unprocessed_items: {
|
75
|
+
'sessions' => [
|
75
76
|
{
|
76
|
-
:
|
77
|
-
:
|
78
|
-
|
77
|
+
delete_request: {
|
78
|
+
key: {
|
79
|
+
'session_id' =>
|
79
80
|
{
|
80
|
-
:
|
81
|
+
s: '1'
|
81
82
|
}
|
82
83
|
}
|
83
84
|
}
|
84
85
|
},
|
85
86
|
{
|
86
|
-
:
|
87
|
-
:
|
88
|
-
|
87
|
+
delete_request: {
|
88
|
+
key: {
|
89
|
+
'session_id' =>
|
89
90
|
{
|
90
|
-
:
|
91
|
+
s: '17'
|
91
92
|
}
|
92
93
|
}
|
93
94
|
}
|
@@ -95,64 +96,62 @@ describe Aws::SessionStore::DynamoDB::GarbageCollection do
|
|
95
96
|
]
|
96
97
|
}
|
97
98
|
}
|
98
|
-
|
99
|
+
end
|
99
100
|
|
100
101
|
let(:dynamo_db_client) {Aws::DynamoDB::Client.new}
|
101
102
|
|
102
|
-
context
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
dynamo_db_client.should_receive(:batch_write_item).
|
103
|
+
context 'Mock DynamoDB client with garbage collection' do
|
104
|
+
it 'processes scan result greater than 25 and deletes in batches of 25' do
|
105
|
+
expect(dynamo_db_client).to receive(:scan)
|
106
|
+
.exactly(1).times.and_return(scan_resp1)
|
107
|
+
expect(dynamo_db_client).to receive(:batch_write_item).
|
108
108
|
exactly(2).times.and_return(write_resp1)
|
109
109
|
collect_garbage
|
110
110
|
end
|
111
111
|
|
112
|
-
it
|
113
|
-
dynamo_db_client.
|
112
|
+
it 'gets scan results then returns last evaluated key and resumes scanning' do
|
113
|
+
expect(dynamo_db_client).to receive(:scan).
|
114
114
|
exactly(1).times.and_return(scan_resp2)
|
115
|
-
dynamo_db_client.
|
115
|
+
expect(dynamo_db_client).to receive(:scan).
|
116
116
|
exactly(1).times.with(hash_including(exclusive_start_key: scan_resp2[:last_evaluated_key])).
|
117
117
|
and_return(scan_resp3)
|
118
|
-
dynamo_db_client.
|
118
|
+
expect(dynamo_db_client).to receive(:batch_write_item).
|
119
119
|
exactly(3).times.and_return(write_resp1)
|
120
|
-
|
120
|
+
collect_garbage
|
121
121
|
end
|
122
122
|
|
123
|
-
it
|
124
|
-
dynamo_db_client.
|
123
|
+
it 'it formats unprocessed_items and then batch deletes them' do
|
124
|
+
expect(dynamo_db_client).to receive(:scan).
|
125
125
|
exactly(1).times.and_return(scan_resp3)
|
126
|
-
dynamo_db_client.
|
127
|
-
with(:
|
126
|
+
expect(dynamo_db_client).to receive(:batch_write_item).ordered.
|
127
|
+
with(request_items: { 'sessions' => format_scan_result }).
|
128
128
|
and_return(write_resp2)
|
129
|
-
dynamo_db_client.
|
130
|
-
:
|
131
|
-
|
132
|
-
"sessions" => [
|
129
|
+
expect(dynamo_db_client).to receive(:batch_write_item).ordered.with(
|
130
|
+
request_items: {
|
131
|
+
'sessions' => [
|
133
132
|
{
|
134
|
-
:
|
135
|
-
:
|
136
|
-
|
133
|
+
delete_request: {
|
134
|
+
key: {
|
135
|
+
'session_id' =>
|
137
136
|
{
|
138
|
-
:
|
137
|
+
s: '1'
|
139
138
|
}
|
140
139
|
}
|
141
140
|
}
|
142
141
|
},
|
143
142
|
{
|
144
|
-
:
|
145
|
-
:
|
146
|
-
|
143
|
+
delete_request: {
|
144
|
+
key: {
|
145
|
+
'session_id' =>
|
147
146
|
{
|
148
|
-
:
|
147
|
+
s: '17'
|
149
148
|
}
|
150
149
|
}
|
151
150
|
}
|
152
151
|
}
|
153
152
|
]
|
154
153
|
}
|
155
|
-
|
154
|
+
).and_return(write_resp1)
|
156
155
|
collect_garbage
|
157
156
|
end
|
158
157
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Copyright 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
4
|
#
|
3
5
|
# Licensed under the Apache License, Version 2.0 (the "License"). You
|
@@ -11,7 +13,6 @@
|
|
11
13
|
# ANY KIND, either express or implied. See the License for the specific
|
12
14
|
# language governing permissions and limitations under the License.
|
13
15
|
|
14
|
-
|
15
16
|
require 'spec_helper'
|
16
17
|
|
17
18
|
describe Aws::SessionStore::DynamoDB::RackMiddleware do
|
@@ -20,17 +21,17 @@ describe Aws::SessionStore::DynamoDB::RackMiddleware do
|
|
20
21
|
def thread(mul_val, time, check)
|
21
22
|
Thread.new do
|
22
23
|
sleep(time)
|
23
|
-
get
|
24
|
-
last_request.session[:multiplier].
|
24
|
+
get '/'
|
25
|
+
expect(last_request.session[:multiplier]).to eq(mul_val) if check
|
25
26
|
end
|
26
27
|
end
|
27
28
|
|
28
29
|
def thread_exception(error)
|
29
|
-
Thread.new { expect { get
|
30
|
+
Thread.new { expect { get '/' }.to raise_error(error) }
|
30
31
|
end
|
31
32
|
|
32
33
|
def update_item_mock(options, update_method)
|
33
|
-
if options[:return_values] ==
|
34
|
+
if options[:return_values] == 'UPDATED_NEW' && options.key?(:expected)
|
34
35
|
sleep(0.50)
|
35
36
|
update_method.call(options)
|
36
37
|
else
|
@@ -41,23 +42,23 @@ describe Aws::SessionStore::DynamoDB::RackMiddleware do
|
|
41
42
|
let(:base_app) { MultiplierApplication.new }
|
42
43
|
let(:app) { Aws::SessionStore::DynamoDB::RackMiddleware.new(base_app, @options) }
|
43
44
|
|
44
|
-
context
|
45
|
+
context 'Mock Multiple Threaded Sessions', integration: true do
|
45
46
|
before do
|
46
47
|
@options = Aws::SessionStore::DynamoDB::Configuration.new.to_hash
|
47
48
|
@options[:enable_locking] = true
|
48
49
|
@options[:secret_key] = 'watermelon_smiles'
|
49
50
|
|
50
51
|
update_method = @options[:dynamo_db_client].method(:update_item)
|
51
|
-
@options[:dynamo_db_client].
|
52
|
+
expect(@options[:dynamo_db_client]).to receive(:update_item).at_least(:once) do |options|
|
52
53
|
update_item_mock(options, update_method)
|
53
54
|
end
|
54
55
|
end
|
55
56
|
|
56
|
-
it
|
57
|
+
it 'should wait for lock' do
|
57
58
|
@options[:lock_expiry_time] = 2000
|
58
59
|
|
59
|
-
get
|
60
|
-
last_request.session[:multiplier].
|
60
|
+
get '/'
|
61
|
+
expect(last_request.session[:multiplier]).to eq(1)
|
61
62
|
|
62
63
|
t1 = thread(2, 0, false)
|
63
64
|
t2 = thread(4, 0.25, true)
|
@@ -65,11 +66,11 @@ describe Aws::SessionStore::DynamoDB::RackMiddleware do
|
|
65
66
|
t2.join
|
66
67
|
end
|
67
68
|
|
68
|
-
it
|
69
|
+
it 'should bust lock' do
|
69
70
|
@options[:lock_expiry_time] = 100
|
70
71
|
|
71
|
-
get
|
72
|
-
last_request.session[:multiplier].
|
72
|
+
get '/'
|
73
|
+
expect(last_request.session[:multiplier]).to eq(1)
|
73
74
|
|
74
75
|
t1 = thread_exception(Aws::DynamoDB::Errors::ConditionalCheckFailedException)
|
75
76
|
t2 = thread(2, 0.25, true)
|
@@ -77,13 +78,13 @@ describe Aws::SessionStore::DynamoDB::RackMiddleware do
|
|
77
78
|
t2.join
|
78
79
|
end
|
79
80
|
|
80
|
-
it
|
81
|
+
it 'should throw exceeded time spent aquiring lock error' do
|
81
82
|
@options[:lock_expiry_time] = 1000
|
82
83
|
@options[:lock_retry_delay] = 100
|
83
84
|
@options[:lock_max_wait_time] = 0.25
|
84
85
|
|
85
|
-
get
|
86
|
-
last_request.session[:multiplier].
|
86
|
+
get '/'
|
87
|
+
expect(last_request.session[:multiplier]).to eq(1)
|
87
88
|
|
88
89
|
t1 = thread(2, 0, false)
|
89
90
|
sleep(0.25)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Copyright 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
2
4
|
#
|
3
5
|
# Licensed under the Apache License, Version 2.0 (the "License"). You
|
@@ -22,28 +24,28 @@ module Aws
|
|
22
24
|
instance_exec(&ConstantHelpers)
|
23
25
|
|
24
26
|
before do
|
25
|
-
@options = { :
|
27
|
+
@options = { secret_key: 'watermelon_cherries' }
|
26
28
|
end
|
27
29
|
|
28
30
|
# Table options for client
|
29
31
|
def table_opts(sid)
|
30
32
|
{
|
31
|
-
:
|
32
|
-
:
|
33
|
+
table_name: Configuration::DEFAULTS[:table_name],
|
34
|
+
key: { Configuration::DEFAULTS[:table_key] => sid }
|
33
35
|
}
|
34
36
|
end
|
35
37
|
|
36
38
|
# Attributes to be retrieved via client
|
37
39
|
def attr_opts
|
38
40
|
{
|
39
|
-
:
|
40
|
-
:
|
41
|
+
attributes_to_get: %w[data created_at locked_at],
|
42
|
+
consistent_read: true
|
41
43
|
}
|
42
44
|
end
|
43
45
|
|
44
46
|
def extract_time(sid)
|
45
47
|
options = table_opts(sid).merge(attr_opts)
|
46
|
-
Time.at((client.get_item(options)[:item][
|
48
|
+
Time.at((client.get_item(options)[:item]['created_at']).to_f)
|
47
49
|
end
|
48
50
|
|
49
51
|
let(:base_app) { MultiplierApplication.new }
|
@@ -51,76 +53,75 @@ module Aws
|
|
51
53
|
let(:config) { Configuration.new }
|
52
54
|
let(:client) { config.dynamo_db_client }
|
53
55
|
|
54
|
-
context
|
55
|
-
it
|
56
|
-
get
|
57
|
-
last_request.session[:multiplier].
|
56
|
+
context 'Testing best case session storage', integration: true do
|
57
|
+
it 'stores session data in session object' do
|
58
|
+
get '/'
|
59
|
+
expect(last_request.session[:multiplier]).to eq(1)
|
58
60
|
end
|
59
61
|
|
60
|
-
it
|
61
|
-
get
|
62
|
-
last_response.body.
|
63
|
-
last_response['Set-Cookie'].
|
62
|
+
it 'creates a new HTTP cookie when Cookie not supplied' do
|
63
|
+
get '/'
|
64
|
+
expect(last_response.body).to eq('All good!')
|
65
|
+
expect(last_response['Set-Cookie']).to be_truthy
|
64
66
|
end
|
65
67
|
|
66
|
-
it
|
67
|
-
get
|
68
|
-
last_response['Set-Cookie'].
|
69
|
-
|
68
|
+
it 'does not rewrite Cookie if cookie previously/accuarately set' do
|
69
|
+
get '/'
|
70
|
+
expect(last_response['Set-Cookie']).not_to be_nil
|
70
71
|
|
71
|
-
get
|
72
|
-
last_response['Set-Cookie'].
|
72
|
+
get '/'
|
73
|
+
expect(last_response['Set-Cookie']).to be_nil
|
73
74
|
end
|
74
75
|
|
75
|
-
it
|
76
|
+
it 'does not set cookie when defer option is specified' do
|
76
77
|
@options[:defer] = true
|
77
|
-
get
|
78
|
-
last_response['Set-Cookie'].
|
78
|
+
get '/'
|
79
|
+
expect(last_response['Set-Cookie']).to be_nil
|
79
80
|
end
|
80
81
|
|
81
|
-
it
|
82
|
-
get
|
83
|
-
last_response['Set-Cookie'].
|
84
|
-
last_response['Set-Cookie'].
|
82
|
+
it 'creates new session with false/nonexistant http-cookie id' do
|
83
|
+
get '/', {}, invalid_cookie.merge(invalid_session_data)
|
84
|
+
expect(last_response['Set-Cookie']).not_to eq('rack.session=ApplePieBlueberries')
|
85
|
+
expect(last_response['Set-Cookie']).not_to be_nil
|
85
86
|
end
|
86
87
|
|
87
|
-
it
|
88
|
+
it 'expires after specified time and sets date for cookie to expire' do
|
88
89
|
@options[:expire_after] = 1
|
89
|
-
get
|
90
|
+
get '/'
|
90
91
|
session_cookie = last_response['Set-Cookie']
|
91
92
|
sleep(1.2)
|
92
93
|
|
93
|
-
get
|
94
|
-
last_response['Set-Cookie'].
|
95
|
-
last_response['Set-Cookie'].
|
94
|
+
get '/'
|
95
|
+
expect(last_response['Set-Cookie']).not_to be_nil
|
96
|
+
expect(last_response['Set-Cookie']).not_to eq(session_cookie)
|
96
97
|
end
|
97
98
|
|
98
|
-
it
|
99
|
+
it 'will not set a session cookie when defer is true' do
|
99
100
|
@options[:defer] = true
|
100
|
-
get
|
101
|
-
last_response['Set-Cookie'].
|
101
|
+
get '/'
|
102
|
+
expect(last_response['Set-Cookie']).to be_nil
|
102
103
|
end
|
103
104
|
|
104
|
-
it
|
105
|
-
get
|
106
|
-
last_request.env[
|
105
|
+
it 'adds the created at attribute for a new session' do
|
106
|
+
get '/'
|
107
|
+
expect(last_request.env['dynamo_db.new_session']).to eq('true')
|
107
108
|
sid = last_response['Set-Cookie'].split(/[;\=]/)[1]
|
108
109
|
time = extract_time(sid)
|
109
|
-
time.
|
110
|
+
expect(time).to be_within(2).of(Time.now)
|
110
111
|
|
111
|
-
get
|
112
|
-
last_request.env['dynamo_db.new_session'].
|
112
|
+
get '/'
|
113
|
+
expect(last_request.env['dynamo_db.new_session']).to be_nil
|
113
114
|
end
|
114
115
|
|
115
|
-
it
|
116
|
+
it 'releases pessimistic lock at finish of transaction' do
|
116
117
|
@options[:enable_locking] = true
|
117
|
-
get
|
118
|
-
last_request.env[
|
118
|
+
get '/'
|
119
|
+
expect(last_request.env['dynamo_db.new_session']).to eq('true')
|
119
120
|
sid = last_response['Set-Cookie'].split(/[;\=]/)[1]
|
120
121
|
|
121
|
-
get
|
122
|
+
get '/'
|
122
123
|
options = table_opts(sid).merge(attr_opts)
|
123
|
-
client.get_item(options)[:item][
|
124
|
+
expect(client.get_item(options)[:item]['locked_at']).to be_nil
|
124
125
|
end
|
125
126
|
end
|
126
127
|
end
|