aws-sessionstore-dynamodb 2.2.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -0
  3. data/LICENSE.txt +202 -0
  4. data/VERSION +1 -1
  5. data/lib/aws/session_store/dynamo_db/configuration.rb +119 -204
  6. data/lib/aws/session_store/dynamo_db/errors/base_handler.rb +2 -0
  7. data/lib/aws/session_store/dynamo_db/errors/default_handler.rb +13 -12
  8. data/lib/aws/session_store/dynamo_db/errors.rb +27 -0
  9. data/lib/aws/session_store/dynamo_db/garbage_collection.rb +84 -93
  10. data/lib/aws/session_store/dynamo_db/locking/base.rb +31 -32
  11. data/lib/aws/session_store/dynamo_db/locking/null.rb +4 -3
  12. data/lib/aws/session_store/dynamo_db/locking/pessimistic.rb +32 -20
  13. data/lib/aws/session_store/dynamo_db/rack_middleware.rb +45 -49
  14. data/lib/aws/session_store/dynamo_db/table.rb +64 -67
  15. data/lib/aws-sessionstore-dynamodb.rb +14 -14
  16. metadata +18 -64
  17. data/.github/PULL_REQUEST_TEMPLATE.md +0 -6
  18. data/.github/workflows/ci.yml +0 -39
  19. data/.gitignore +0 -12
  20. data/.gitmodules +0 -3
  21. data/.yardopts +0 -4
  22. data/CODE_OF_CONDUCT.md +0 -4
  23. data/CONTRIBUTING.md +0 -61
  24. data/Gemfile +0 -24
  25. data/LICENSE +0 -12
  26. data/README.md +0 -125
  27. data/Rakefile +0 -35
  28. data/aws-sessionstore-dynamodb.gemspec +0 -24
  29. data/doc-src/templates/default/layout/html/footer.erb +0 -6
  30. data/doc-src/templates/default/layout/html/layout.erb +0 -31
  31. data/lib/aws/session_store/dynamo_db/invalid_id_error.rb +0 -7
  32. data/lib/aws/session_store/dynamo_db/lock_wait_timeout_error.rb +0 -7
  33. data/lib/aws/session_store/dynamo_db/missing_secret_key_error.rb +0 -7
  34. data/lib/aws/session_store/dynamo_db/version.rb +0 -7
  35. data/spec/aws/session_store/dynamo_db/app_config.yml +0 -16
  36. data/spec/aws/session_store/dynamo_db/configuration_spec.rb +0 -81
  37. data/spec/aws/session_store/dynamo_db/error/default_error_handler_spec.rb +0 -64
  38. data/spec/aws/session_store/dynamo_db/garbage_collection_spec.rb +0 -158
  39. data/spec/aws/session_store/dynamo_db/locking/threaded_sessions_spec.rb +0 -96
  40. data/spec/aws/session_store/dynamo_db/rack_middleware_database_spec.rb +0 -130
  41. data/spec/aws/session_store/dynamo_db/rack_middleware_spec.rb +0 -148
  42. data/spec/aws/session_store/dynamo_db/table_spec.rb +0 -48
  43. data/spec/spec_helper.rb +0 -65
data/README.md DELETED
@@ -1,125 +0,0 @@
1
- # Amazon DynamoDB Session Store
2
-
3
- The **Amazon DynamoDB Session Store** handles sessions for Ruby web applications
4
- using a DynamoDB backend. The session store is compatible with all Rack based
5
- frameworks. For Rails applications, use the [`aws-sdk-rails`][1] gem.
6
-
7
- ## Installation
8
-
9
- For Rack applications, you can create the Amazon DynamoDB table in a
10
- Ruby file using the following method:
11
-
12
- require 'aws-sessionstore-dynamodb'
13
-
14
- Aws::SessionStore::DynamoDB::Table.create_table
15
-
16
- Run the session store as a Rack middleware in the following way:
17
-
18
- require 'aws-sessionstore-dynamodb'
19
- require 'some_rack_app'
20
-
21
- options = { :secret_key => 'SECRET_KEY' }
22
-
23
- use Aws::SessionStore::DynamoDB::RackMiddleware.new(options)
24
- run SomeRackApp
25
-
26
- Note that `:secret_key` is a mandatory configuration option that must be set.
27
-
28
- ## Detailed Usage
29
-
30
- The session store is a Rack Middleware, meaning that it will implement the Rack
31
- interface for dealing with HTTP request/responses.
32
-
33
- This session store uses a DynamoDB backend in order to provide scaling and
34
- centralized data benefits for session storage with more ease than other
35
- containers, like local servers or cookies. Once an application scales beyond
36
- a single web server, session data will need to be shared across the servers.
37
- DynamoDB takes care of this burden for you by scaling with your application.
38
- Cookie storage places all session data on the client side,
39
- discouraging sensitive data storage. It also forces strict data size
40
- limitations. DynamoDB takes care of these concerns by allowing for a safe and
41
- scalable storage container with a much larger data size limit for session data.
42
-
43
- For more developer information, see the [Full API documentation][2].
44
-
45
- ### Configuration Options
46
-
47
- A number of options are available to be set in
48
- `Aws::SessionStore::DynamoDB::Configuration`, which is used by the
49
- `RackMiddleware` class. These options can be set directly by Ruby code or
50
- through environment variables.
51
-
52
- The full set of options along with defaults can be found in the
53
- [Configuration class documentation][3].
54
-
55
- #### Environment Options
56
-
57
- Certain configuration options can be loaded from the environment. These
58
- options must be specified in the following format:
59
-
60
- DYNAMO_DB_SESSION_NAME-OF-CONFIGURATION-OPTION
61
-
62
- The example below would be a valid way to set the session table name:
63
-
64
- export DYNAMO_DB_SESSION_TABLE_NAME='sessions'
65
-
66
- ### Garbage Collection
67
-
68
- You may want to delete old sessions from your session table. You can use the
69
- DynamoDB [Time to Live (TTL) feature][4] on the `expire_at` attribute to
70
- automatically delete expired items.
71
-
72
- If you want to take other attributes into consideration for deletion, you could
73
- instead use the `GarbageCollection` class. You can create your own Rake task for
74
- garbage collection similar to below:
75
-
76
- require "aws-sessionstore-dynamodb"
77
-
78
- desc 'Perform Garbage Collection'
79
- task :garbage_collect do |t|
80
- options = {:max_age => 3600*24, max_stale => 5*3600 }
81
- Aws::SessionStore::DynamoDB::GarbageCollection.collect_garbage(options)
82
- end
83
-
84
- The above example will clear sessions older than one day or that have been
85
- stale for longer than an hour.
86
-
87
- ### Locking Strategy
88
-
89
- You may want the Session Store to implement the provided pessimistic locking
90
- strategy if you are concerned about concurrency issues with session accesses.
91
- By default, locking is not implemented for the session store. You must trigger
92
- the locking strategy through the configuration of the session store. Pessimistic
93
- locking, in this case, means that only one read can be made on a session at
94
- once. While the session is being read by the process with the lock, other
95
- processes may try to obtain a lock on the same session but will be blocked.
96
-
97
- Locking is expensive and will drive up costs depending on how it is used.
98
- Without locking, one read and one write are performed per request for session
99
- data manipulation. If a locking strategy is implemented, as many as the total
100
- maximum wait time divided by the lock retry delay writes to the database.
101
- Keep these considerations in mind if you plan to enable locking.
102
-
103
- #### Configuration for Locking
104
-
105
- The following configuration options will allow you to configure the pessimistic
106
- locking strategy according to your needs:
107
-
108
- options = {
109
- :enable_locking => true,
110
- :lock_expiry_time => 500,
111
- :lock_retry_delay => 500,
112
- :lock_max_wait_time => 1
113
- }
114
-
115
- ### Error Handling
116
-
117
- You can pass in your own error handler for raised exceptions or you can allow
118
- the default error handler to them for you. See the API documentation
119
- on the {Aws::SessionStore::DynamoDB::Errors::BaseHandler} class for more
120
- details.
121
-
122
- [1]: https://github.com/aws/aws-sdk-rails/
123
- [2]: https://docs.aws.amazon.com/sdk-for-ruby/aws-sessionstore-dynamodb/api/
124
- [3]: https://docs.aws.amazon.com/sdk-for-ruby/aws-sessionstore-dynamodb/api/Aws/SessionStore/DynamoDB/Configuration.html
125
- [4]: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/TTL.html
data/Rakefile DELETED
@@ -1,35 +0,0 @@
1
- require 'rspec/core/rake_task'
2
-
3
- $REPO_ROOT = File.dirname(__FILE__)
4
- $LOAD_PATH.unshift(File.join($REPO_ROOT, 'lib'))
5
- $VERSION = ENV['VERSION'] || File.read(File.join($REPO_ROOT, 'VERSION')).strip
6
-
7
-
8
- Dir.glob('**/*.rake').each do |task_file|
9
- load task_file
10
- end
11
-
12
- task 'test:coverage:clear' do
13
- sh("rm -rf #{File.join($REPO_ROOT, 'coverage')}")
14
- end
15
-
16
- desc 'Runs unit tests'
17
- RSpec::Core::RakeTask.new do |t|
18
- t.rspec_opts = "-I #{$REPO_ROOT}/lib -I #{$REPO_ROOT}/spec --tag ~integration"
19
- t.pattern = "#{$REPO_ROOT}/spec"
20
- end
21
- task :spec => 'test:coverage:clear'
22
-
23
- desc 'Runs integration tests'
24
- RSpec::Core::RakeTask.new('spec:integration') do |t|
25
- t.rspec_opts = "-I #{$REPO_ROOT}/lib -I #{$REPO_ROOT}/spec --tag integration"
26
- t.pattern = "#{$REPO_ROOT}/spec"
27
- end
28
-
29
- desc 'Runs unit and integration tests'
30
- task 'test' => [:spec, 'spec:integration']
31
-
32
- task :default => :spec
33
- task 'release:test' => [:spec, 'spec:integration']
34
-
35
-
@@ -1,24 +0,0 @@
1
- version = File.read(File.expand_path('../VERSION', __FILE__)).strip
2
-
3
- Gem::Specification.new do |spec|
4
- spec.name = "aws-sessionstore-dynamodb"
5
- spec.version = version
6
- spec.authors = ["Amazon Web Services"]
7
- spec.email = ["aws-dr-rubygems@amazon.com"]
8
-
9
- spec.summary = "The Amazon DynamoDB Session Store handles sessions " +
10
- "for Ruby web applications using a DynamoDB backend."
11
- spec.homepage = "http://github.com/aws/aws-sessionstore-dynamodb-ruby"
12
- spec.license = "Apache License 2.0"
13
-
14
- spec.files = `git ls-files`.split($/)
15
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
16
- spec.require_paths = ["lib"]
17
-
18
- # Require 1.85.0 for user_agent_frameworks config
19
- spec.add_dependency 'aws-sdk-dynamodb', '~> 1', '>= 1.85.0'
20
- spec.add_dependency 'rack', '>= 2', '< 4'
21
- spec.add_dependency 'rack-session', '>= 1', '< 3'
22
-
23
- spec.required_ruby_version = '>= 2.5'
24
- end
@@ -1,6 +0,0 @@
1
- <div id="footer">
2
- Generated on <%= Time.now.strftime("%c") %> by
3
- <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
4
- <%= YARD::VERSION %> (ruby-<%= RUBY_VERSION %>).
5
- <div id="awsdocs-legal-zone-copyright"></div>
6
- </div>
@@ -1,31 +0,0 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <%= erb(:headers) %>
5
- <!-- Docs Metrics + Cookie Consent Script -->
6
- <meta name="guide-name" content="API Reference">
7
- <meta name="service-name" content="AWS SDK For Ruby - AWS DynamoDB Session Store">
8
- <script type="text/javascript" src="/assets/js/awsdocs-boot.js"></script>
9
- </head>
10
- <body>
11
- <div class="nav_wrap">
12
- <iframe id="nav" src="<%= @nav_url %>?1"></iframe>
13
- <div id="resizer"></div>
14
- </div>
15
-
16
- <div id="main" tabindex="-1">
17
- <div id="header">
18
- <%= erb(:breadcrumb) %>
19
- <%= erb(:search) %>
20
- <div class="clear"></div>
21
- </div>
22
-
23
- <div id="content">
24
- <!-- REGION_DISCLAIMER_DO_NOT_REMOVE -->
25
- <%= yieldall %>
26
- </div>
27
-
28
- <%= erb(:footer) %>
29
- </div>
30
- </body>
31
- </html>
@@ -1,7 +0,0 @@
1
- module Aws::SessionStore::DynamoDB
2
- class InvalidIDError < RuntimeError
3
- def initialize(msg = "Corrupt Session ID!")
4
- super
5
- end
6
- end
7
- end
@@ -1,7 +0,0 @@
1
- module Aws::SessionStore::DynamoDB
2
- class LockWaitTimeoutError < RuntimeError
3
- def initialize(msg = 'Maximum time spent to acquire lock has been exceeded!')
4
- super
5
- end
6
- end
7
- end
@@ -1,7 +0,0 @@
1
- module Aws::SessionStore::DynamoDB
2
- class MissingSecretKeyError < RuntimeError
3
- def initialize(msg = "No secret key provided!")
4
- super
5
- end
6
- end
7
- end
@@ -1,7 +0,0 @@
1
- module Aws
2
- module SessionStore
3
- module DynamoDB
4
- VERSION = "2.0.0"
5
- end
6
- end
7
- end
@@ -1,16 +0,0 @@
1
- # Copyright 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License"). You
4
- # may not use this file except in compliance with the License. A copy of
5
- # the License is located at
6
- #
7
- # http://aws.amazon.com/apache2.0/
8
- #
9
- # or in the "license" file accompanying this file. This file is
10
- # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11
- # ANY KIND, either express or implied. See the License for the specific
12
- # language governing permissions and limitations under the License.
13
-
14
- table_name: NewTable
15
- table_key: Somekey
16
- consistent_read: true
@@ -1,81 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Copyright 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4
- #
5
- # Licensed under the Apache License, Version 2.0 (the "License"). You
6
- # may not use this file except in compliance with the License. A copy of
7
- # the License is located at
8
- #
9
- # http://aws.amazon.com/apache2.0/
10
- #
11
- # or in the "license" file accompanying this file. This file is
12
- # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
13
- # ANY KIND, either express or implied. See the License for the specific
14
- # language governing permissions and limitations under the License.
15
-
16
- require 'spec_helper'
17
-
18
- describe Aws::SessionStore::DynamoDB::Configuration do
19
- let(:defaults) do
20
- {
21
- table_name: 'sessions',
22
- table_key: 'session_id',
23
- consistent_read: true,
24
- read_capacity: 10,
25
- write_capacity: 5,
26
- raise_errors: false
27
- }
28
- end
29
-
30
- let(:expected_file_opts) do
31
- {
32
- consistent_read: true,
33
- table_name: 'NewTable',
34
- table_key: 'Somekey',
35
- }
36
- end
37
-
38
- let(:client) { Aws::DynamoDB::Client.new(stub_responses: true) }
39
-
40
- let(:runtime_options) do
41
- {
42
- table_name: 'SessionTable',
43
- table_key: 'session_id_stuff'
44
- }
45
- end
46
-
47
- def expected_options(opts)
48
- cfg = Aws::SessionStore::DynamoDB::Configuration.new(opts)
49
- expected_opts = defaults.merge(expected_file_opts).merge(opts)
50
- expect(cfg.to_hash).to include(expected_opts)
51
- end
52
-
53
- before do
54
- allow(Aws::DynamoDB::Client).to receive(:new).and_return(client)
55
- end
56
-
57
- context 'Configuration Tests' do
58
- it 'configures option with out runtime,YAML or ENV options' do
59
- cfg = Aws::SessionStore::DynamoDB::Configuration.new
60
- expect(cfg.to_hash).to include(defaults)
61
- end
62
-
63
- it 'configures accurate option hash with runtime options, no YAML or ENV' do
64
- cfg = Aws::SessionStore::DynamoDB::Configuration.new(runtime_options)
65
- expected_opts = defaults.merge(runtime_options)
66
- expect(cfg.to_hash).to include(expected_opts)
67
- end
68
-
69
- it 'merge YAML and runtime options giving runtime precendence' do
70
- config_path = File.dirname(__FILE__) + '/app_config.yml'
71
- runtime_opts = { config_file: config_path }.merge(runtime_options)
72
- expected_options(runtime_opts)
73
- end
74
-
75
- it 'throws an exception when wrong path for file' do
76
- config_path = 'Wrong path!'
77
- runtime_opts = { config_file: config_path }.merge(runtime_options)
78
- expect { cfg = Aws::SessionStore::DynamoDB::Configuration.new(runtime_opts) }.to raise_error(Errno::ENOENT)
79
- end
80
- end
81
- end
@@ -1,64 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Copyright 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4
- #
5
- # Licensed under the Apache License, Version 2.0 (the "License"). You
6
- # may not use this file except in compliance with the License. A copy of
7
- # the License is located at
8
- #
9
- # http://aws.amazon.com/apache2.0/
10
- #
11
- # or in the "license" file accompanying this file. This file is
12
- # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
13
- # ANY KIND, either express or implied. See the License for the specific
14
- # language governing permissions and limitations under the License.
15
-
16
- require 'spec_helper'
17
-
18
- describe Aws::SessionStore::DynamoDB do
19
- include Rack::Test::Methods
20
-
21
- instance_exec(&ConstantHelpers)
22
-
23
- before do
24
- @options = { dynamo_db_client: client, secret_key: 'meltingbutter' }
25
- end
26
-
27
- let(:base_app) { MultiplierApplication.new }
28
- let(:app) { Aws::SessionStore::DynamoDB::RackMiddleware.new(base_app, @options) }
29
- let(:client) { double('Aws::DynamoDB::Client', config: double(user_agent_frameworks: [])) }
30
-
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)
35
- end
36
-
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)
40
- end
41
-
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)
48
- end
49
- end
50
-
51
- context 'Test ExceptionHandler with true as return value for handle_error' do
52
- it 'raises all errors' do
53
- @options[:raise_errors] = true
54
- allow(client).to receive(:update_item).and_raise(client_error)
55
- expect { get '/' }.to raise_error(client_error)
56
- end
57
-
58
- it 'catches exception for inaccurate table key and raises error' do
59
- @options[:raise_errors] = true
60
- allow(client).to receive(:update_item).and_raise(key_error)
61
- expect { get '/' }.to raise_error(key_error)
62
- end
63
- end
64
- end
@@ -1,158 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Copyright 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4
- #
5
- # Licensed under the Apache License, Version 2.0 (the "License"). You
6
- # may not use this file except in compliance with the License. A copy of
7
- # the License is located at
8
- #
9
- # http://aws.amazon.com/apache2.0/
10
- #
11
- # or in the "license" file accompanying this file. This file is
12
- # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
13
- # ANY KIND, either express or implied. See the License for the specific
14
- # language governing permissions and limitations under the License.
15
-
16
- require 'spec_helper'
17
-
18
- describe Aws::SessionStore::DynamoDB::GarbageCollection do
19
- def items(min, max)
20
- items = []
21
- (min..max).each do |i|
22
- items << { 'session_id' => { s: i.to_s } }
23
- end
24
- items
25
- end
26
-
27
- def format_scan_result
28
- items = []
29
- (31..49).each do |i|
30
- items << { 'session_id' => { s: i.to_s } }
31
- end
32
-
33
- items.each_with_object([]) do |item, rqst_array|
34
- rqst_array << { delete_request: { key: item } }
35
- end
36
- end
37
-
38
- def collect_garbage
39
- options = { dynamo_db_client: dynamo_db_client, max_age: 100, max_stale: 100 }
40
- Aws::SessionStore::DynamoDB::GarbageCollection.collect_garbage(options)
41
- end
42
-
43
- let(:scan_resp1) do
44
- resp = {
45
- items: items(0, 49),
46
- count: 50,
47
- scanned_count: 1000,
48
- last_evaluated_key: {}
49
- }
50
- end
51
-
52
- let(:scan_resp2) do
53
- {
54
- items: items(0, 31),
55
- last_evaluated_key: { 'session_id' => { s: '31' } }
56
- }
57
- end
58
-
59
- let(:scan_resp3) do
60
- {
61
- items: items(31, 49),
62
- last_evaluated_key: {}
63
- }
64
- end
65
-
66
- let(:write_resp1) do
67
- {
68
- unprocessed_items: {}
69
- }
70
- end
71
-
72
- let(:write_resp2) do
73
- {
74
- unprocessed_items: {
75
- 'sessions' => [
76
- {
77
- delete_request: {
78
- key: {
79
- 'session_id' =>
80
- {
81
- s: '1'
82
- }
83
- }
84
- }
85
- },
86
- {
87
- delete_request: {
88
- key: {
89
- 'session_id' =>
90
- {
91
- s: '17'
92
- }
93
- }
94
- }
95
- }
96
- ]
97
- }
98
- }
99
- end
100
-
101
- let(:dynamo_db_client) {Aws::DynamoDB::Client.new(stub_responses: true)}
102
-
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
- exactly(2).times.and_return(write_resp1)
109
- collect_garbage
110
- end
111
-
112
- it 'gets scan results then returns last evaluated key and resumes scanning' do
113
- expect(dynamo_db_client).to receive(:scan).
114
- exactly(1).times.and_return(scan_resp2)
115
- expect(dynamo_db_client).to receive(:scan).
116
- exactly(1).times.with(hash_including(exclusive_start_key: scan_resp2[:last_evaluated_key])).
117
- and_return(scan_resp3)
118
- expect(dynamo_db_client).to receive(:batch_write_item).
119
- exactly(3).times.and_return(write_resp1)
120
- collect_garbage
121
- end
122
-
123
- it 'it formats unprocessed_items and then batch deletes them' do
124
- expect(dynamo_db_client).to receive(:scan).
125
- exactly(1).times.and_return(scan_resp3)
126
- expect(dynamo_db_client).to receive(:batch_write_item).ordered.
127
- with({request_items: { 'sessions' => format_scan_result }}).
128
- and_return(write_resp2)
129
- expect(dynamo_db_client).to receive(:batch_write_item).ordered.with({
130
- request_items: {
131
- 'sessions' => [
132
- {
133
- delete_request: {
134
- key: {
135
- 'session_id' =>
136
- {
137
- s: '1'
138
- }
139
- }
140
- }
141
- },
142
- {
143
- delete_request: {
144
- key: {
145
- 'session_id' =>
146
- {
147
- s: '17'
148
- }
149
- }
150
- }
151
- }
152
- ]
153
- }
154
- }).and_return(write_resp1)
155
- collect_garbage
156
- end
157
- end
158
- end
@@ -1,96 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Copyright 2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4
- #
5
- # Licensed under the Apache License, Version 2.0 (the "License"). You
6
- # may not use this file except in compliance with the License. A copy of
7
- # the License is located at
8
- #
9
- # http://aws.amazon.com/apache2.0/
10
- #
11
- # or in the "license" file accompanying this file. This file is
12
- # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
13
- # ANY KIND, either express or implied. See the License for the specific
14
- # language governing permissions and limitations under the License.
15
-
16
- require 'spec_helper'
17
-
18
- describe Aws::SessionStore::DynamoDB::RackMiddleware do
19
- include Rack::Test::Methods
20
-
21
- def thread(mul_val, time, check)
22
- Thread.new do
23
- sleep(time)
24
- get '/'
25
- expect(last_request.session[:multiplier]).to eq(mul_val) if check
26
- end
27
- end
28
-
29
- def thread_exception(error)
30
- Thread.new { expect { get '/' }.to raise_error(error) }
31
- end
32
-
33
- def update_item_mock(options, update_method)
34
- if options[:return_values] == 'UPDATED_NEW' && options.key?(:expected)
35
- sleep(0.50)
36
- update_method.call(options)
37
- else
38
- update_method.call(options)
39
- end
40
- end
41
-
42
- let(:base_app) { MultiplierApplication.new }
43
- let(:app) { Aws::SessionStore::DynamoDB::RackMiddleware.new(base_app, @options) }
44
-
45
- context 'Mock Multiple Threaded Sessions', integration: true do
46
- before do
47
- @options = Aws::SessionStore::DynamoDB::Configuration.new.to_hash
48
- @options[:enable_locking] = true
49
- @options[:secret_key] = 'watermelon_smiles'
50
-
51
- update_method = @options[:dynamo_db_client].method(:update_item)
52
- expect(@options[:dynamo_db_client]).to receive(:update_item).at_least(:once) do |options|
53
- update_item_mock(options, update_method)
54
- end
55
- end
56
-
57
- it 'should wait for lock' do
58
- @options[:lock_expiry_time] = 2000
59
-
60
- get '/'
61
- expect(last_request.session[:multiplier]).to eq(1)
62
-
63
- t1 = thread(2, 0, false)
64
- t2 = thread(4, 0.25, true)
65
- t1.join
66
- t2.join
67
- end
68
-
69
- it 'should bust lock' do
70
- @options[:lock_expiry_time] = 100
71
-
72
- get '/'
73
- expect(last_request.session[:multiplier]).to eq(1)
74
-
75
- t1 = thread_exception(Aws::DynamoDB::Errors::ConditionalCheckFailedException)
76
- t2 = thread(2, 0.25, true)
77
- t1.join
78
- t2.join
79
- end
80
-
81
- it 'should throw exceeded time spent aquiring lock error' do
82
- @options[:lock_expiry_time] = 1000
83
- @options[:lock_retry_delay] = 100
84
- @options[:lock_max_wait_time] = 0.25
85
-
86
- get '/'
87
- expect(last_request.session[:multiplier]).to eq(1)
88
-
89
- t1 = thread(2, 0, false)
90
- sleep(0.25)
91
- t2 = thread_exception(Aws::SessionStore::DynamoDB::LockWaitTimeoutError)
92
- t1.join
93
- t2.join
94
- end
95
- end
96
- end