aws-sessionstore-dynamodb 0.5.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 +7 -0
- data/.gitignore +4 -0
- data/.yardopts +3 -0
- data/Gemfile +28 -0
- data/LICENSE.txt +12 -0
- data/README.md +171 -0
- data/Rakefile +15 -0
- data/aws-sessionstore-dynamodb.gemspec +18 -0
- data/lib/aws-sessionstore-dynamodb.rb +34 -0
- data/lib/aws/session_store/dynamo_db/configuration.rb +298 -0
- data/lib/aws/session_store/dynamo_db/errors/base_handler.rb +45 -0
- data/lib/aws/session_store/dynamo_db/errors/default_handler.rb +57 -0
- data/lib/aws/session_store/dynamo_db/garbage_collection.rb +128 -0
- data/lib/aws/session_store/dynamo_db/invalid_id_error.rb +21 -0
- data/lib/aws/session_store/dynamo_db/lock_wait_timeout_error.rb +21 -0
- data/lib/aws/session_store/dynamo_db/locking/base.rb +162 -0
- data/lib/aws/session_store/dynamo_db/locking/null.rb +40 -0
- data/lib/aws/session_store/dynamo_db/locking/pessimistic.rb +160 -0
- data/lib/aws/session_store/dynamo_db/missing_secret_key_error.rb +21 -0
- data/lib/aws/session_store/dynamo_db/rack_middleware.rb +130 -0
- data/lib/aws/session_store/dynamo_db/railtie.rb +28 -0
- data/lib/aws/session_store/dynamo_db/table.rb +98 -0
- data/lib/aws/session_store/dynamo_db/tasks/session_table.rake +21 -0
- data/lib/aws/session_store/dynamo_db/version.rb +21 -0
- data/lib/rails/generators/sessionstore/dynamodb/dynamodb_generator.rb +55 -0
- data/lib/rails/generators/sessionstore/dynamodb/templates/sessionstore/USAGE +13 -0
- data/lib/rails/generators/sessionstore/dynamodb/templates/sessionstore/dynamodb.yml +71 -0
- data/lib/rails/generators/sessionstore/dynamodb/templates/sessionstore_migration.rb +10 -0
- data/spec/aws/session_store/dynamo_db/app_config.yml +19 -0
- data/spec/aws/session_store/dynamo_db/config/dynamo_db_session.yml +24 -0
- data/spec/aws/session_store/dynamo_db/configuration_spec.rb +101 -0
- data/spec/aws/session_store/dynamo_db/error/default_error_handler_spec.rb +62 -0
- data/spec/aws/session_store/dynamo_db/garbage_collection_spec.rb +156 -0
- data/spec/aws/session_store/dynamo_db/locking/threaded_sessions_spec.rb +95 -0
- data/spec/aws/session_store/dynamo_db/rack_middleware_database_spec.rb +129 -0
- data/spec/aws/session_store/dynamo_db/rack_middleware_spec.rb +149 -0
- data/spec/aws/session_store/dynamo_db/rails_app_config.yml +24 -0
- data/spec/aws/session_store/dynamo_db/table_spec.rb +46 -0
- data/spec/spec_helper.rb +61 -0
- data/tasks/test.rake +29 -0
- metadata +123 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1395af7cb7211af4f4cb72dcd4037ee046627a64
|
4
|
+
data.tar.gz: 55d5c7eb166a8571b05c883fb05baa53d293152f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a9f754fabdd1af66c5853249a946b39b76eca01db99ee569ba9f63b11eec8ba2be7f93d94f6e8055af7013371dde889d6af3c3e093967aeaa24dd56c9b4b52f3
|
7
|
+
data.tar.gz: 3d276410f121bdf18acc8217a14c4cc6967a0cd84863e562aa4dd17e1ce38765d4ee42da3472cc3a9ca75d10cbf20ec6cdac15877e2d7d01d84eac39072dca63
|
data/.gitignore
ADDED
data/.yardopts
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,28 @@
|
|
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
|
+
source 'https://rubygems.org'
|
15
|
+
|
16
|
+
gemspec
|
17
|
+
|
18
|
+
gem 'rake', '~> 10.0'
|
19
|
+
|
20
|
+
group :documentation do
|
21
|
+
gem 'yard', '~> 0.0'
|
22
|
+
end
|
23
|
+
|
24
|
+
group :test do
|
25
|
+
gem 'rspec', '~> 2.0'
|
26
|
+
gem 'simplecov', '~> 0.0', :require => false
|
27
|
+
gem 'rack-test', '~> 0.0'
|
28
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,12 @@
|
|
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.
|
data/README.md
ADDED
@@ -0,0 +1,171 @@
|
|
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 Rails and other
|
5
|
+
Rack based frameworks.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
#### Rails Installation
|
10
|
+
|
11
|
+
Install the session store gem by placing the following command into your
|
12
|
+
Gemfile:
|
13
|
+
|
14
|
+
gem 'aws-sessionstore-dynamodb'
|
15
|
+
|
16
|
+
You will need to have an existing Amazon DynamoDB session table in order for the
|
17
|
+
application to work. You can generate a migration file for the session table
|
18
|
+
with the following command:
|
19
|
+
|
20
|
+
rails generate sessionstore:dynamodb
|
21
|
+
|
22
|
+
To create the table, run migrations as normal with:
|
23
|
+
|
24
|
+
rake db:migrate
|
25
|
+
|
26
|
+
Change the session store to `:dynamodb_store` by editing
|
27
|
+
`config/initializers/session_store.rb` to contain the following:
|
28
|
+
|
29
|
+
YourAppName::Application.config.session_store :dynamodb_store
|
30
|
+
|
31
|
+
You can now start your Rails application with session support.
|
32
|
+
|
33
|
+
#### Basic Rack Application Installation
|
34
|
+
|
35
|
+
For non-Rails applications, you can create the Amazon DynamoDB table in a
|
36
|
+
Ruby file using the following method:
|
37
|
+
|
38
|
+
require 'aws-sessionstore-dynamodb'
|
39
|
+
|
40
|
+
AWS::SessionStore::DynamoDB::Table.create_table
|
41
|
+
|
42
|
+
Run the session store as a Rack middleware in the following way:
|
43
|
+
|
44
|
+
require 'aws-sessionstore-dynamodb'
|
45
|
+
require 'some_rack_app'
|
46
|
+
|
47
|
+
options = { :secret_key => 'SECRET_KEY' }
|
48
|
+
|
49
|
+
use AWS::SessionStore::DynamoDB::RackMiddleware.new(options)
|
50
|
+
run SomeRackApp
|
51
|
+
|
52
|
+
Note that `:secret_key` is a mandatory configuration option that must be set.
|
53
|
+
|
54
|
+
## Detailed Usage
|
55
|
+
|
56
|
+
The session store is a Rack Middleware, meaning that it will implement the Rack
|
57
|
+
interface for dealing with HTTP request/responses.
|
58
|
+
|
59
|
+
This session store uses a DynamoDB backend in order to provide scaling and
|
60
|
+
centralized data benefits for session storage with more ease than other
|
61
|
+
containers, like local servers or cookies. Once an application scales beyond
|
62
|
+
a single web server, session data will need to be shared across the servers.
|
63
|
+
DynamoDB takes care of this burden for you by scaling with your application.
|
64
|
+
Cookie storage places all session data on the client side,
|
65
|
+
discouraging sensitive data storage. It also forces strict data size
|
66
|
+
limitations. DynamoDB takes care of these concerns by allowing for a safe and
|
67
|
+
scalable storage container with a much larger data size limit for session data.
|
68
|
+
|
69
|
+
Full API documentation of the library can be found on [RubyDoc.info][1].
|
70
|
+
|
71
|
+
### Configuration Options
|
72
|
+
|
73
|
+
A number of options are available to be set in
|
74
|
+
`AWS::SessionStore::DynamoDB::Configuration`, which is used by the
|
75
|
+
`RackMiddleware` class. These options can be set in the YAML configuration
|
76
|
+
file in a Rails application (located in `config/sessionstore/dynamodb.yml`),
|
77
|
+
directly by Ruby code, or through environment variables.
|
78
|
+
|
79
|
+
The full set of options along with defaults can be found in the
|
80
|
+
[Configuration class documentation][2].
|
81
|
+
|
82
|
+
#### Environment Options
|
83
|
+
|
84
|
+
Certain configuration options can be loaded from the environment. These
|
85
|
+
options must be specified in the following format:
|
86
|
+
|
87
|
+
DYNAMO_DB_SESSION_NAME-OF-CONFIGURATION-OPTION
|
88
|
+
|
89
|
+
The example below would be a valid way to set the session table name:
|
90
|
+
|
91
|
+
export DYNAMO_DB_SESSION_TABLE_NAME='sessions'
|
92
|
+
|
93
|
+
### Rails Generator Details
|
94
|
+
|
95
|
+
The generator command specified in the installation section will generate two
|
96
|
+
files: a migration file, `db/migration/VERSION_migration_name.rb`, and a
|
97
|
+
configuration YAML file, `config/sessionstore/dynamodb.yml`.
|
98
|
+
|
99
|
+
You can run the command with an argument that will define the name of the
|
100
|
+
migration file. Once the YAML file is created, you can uncomment any of the
|
101
|
+
lines to set configuration options to your liking. The session store will pull
|
102
|
+
options from `config/sessionstore/dynamodb.yml` by default if the file exists.
|
103
|
+
If you do not wish to place the configuration YAML file in that location,
|
104
|
+
you can also pass in a different file path to pull options from.
|
105
|
+
|
106
|
+
### Garbage Collection
|
107
|
+
|
108
|
+
You may want to delete old sessions from your session table. The
|
109
|
+
following examples show how to clear old sessions from your table.
|
110
|
+
|
111
|
+
#### Rails
|
112
|
+
|
113
|
+
A Rake task for garbage collection is provided for Rails applications.
|
114
|
+
By default sessions do not expire. See `config/sessionstore/dynamodb.yml` to
|
115
|
+
configure the max age or stale period of a session. Once you have configured
|
116
|
+
those values you can clear the old sessions with:
|
117
|
+
|
118
|
+
rake dynamo_db:collect_garbage
|
119
|
+
|
120
|
+
#### Outside of Rails
|
121
|
+
|
122
|
+
You can create your own Rake task for garbage collection similar to below:
|
123
|
+
|
124
|
+
require "aws-sessionstore-dynamodb"
|
125
|
+
|
126
|
+
desc 'Perform Garbage Collection'
|
127
|
+
task :garbage_collect do |t|
|
128
|
+
options = {:max_age => 3600*24, max_stale => 5*3600 }
|
129
|
+
AWS::SessionStore::DynamoDB::GarbageCollection.collect_garbage(options)
|
130
|
+
end
|
131
|
+
|
132
|
+
The above example will clear sessions older than one day or that have been
|
133
|
+
stale for longer than an hour.
|
134
|
+
|
135
|
+
### Locking Strategy
|
136
|
+
|
137
|
+
You may want the Session Store to implement the provided pessimistic locking
|
138
|
+
strategy if you are concerned about concurrency issues with session accesses.
|
139
|
+
By default, locking is not implemented for the session store. You must trigger
|
140
|
+
the locking strategy through the configuration of the session store. Pessimistic
|
141
|
+
locking, in this case, means that only one read can be made on a session at
|
142
|
+
once. While the session is being read by the process with the lock, other
|
143
|
+
processes may try to obtain a lock on the same session but will be blocked.
|
144
|
+
|
145
|
+
Locking is expensive and will drive up costs depending on how it is used.
|
146
|
+
Without locking, one read and one write are performed per request for session
|
147
|
+
data manipulation. If a locking strategy is implemented, as many as the total
|
148
|
+
maximum wait time divided by the lock retry delay writes to the database.
|
149
|
+
Keep these considerations in mind if you plan to enable locking.
|
150
|
+
|
151
|
+
#### Configuration for Locking
|
152
|
+
|
153
|
+
The following configuration options will allow you to configure the pessimistic
|
154
|
+
locking strategy according to your needs:
|
155
|
+
|
156
|
+
options = {
|
157
|
+
:enable_locking => true,
|
158
|
+
:lock_expiry_time => 500,
|
159
|
+
:lock_retry_delay => 500,
|
160
|
+
:lock_max_wait_time => 1
|
161
|
+
}
|
162
|
+
|
163
|
+
### Error Handling
|
164
|
+
|
165
|
+
You can pass in your own error handler for raised exceptions or you can allow
|
166
|
+
the default error handler to them for you. See the API documentation
|
167
|
+
on the {AWS::SessionStore::DynamoDB::Errors::BaseHandler} class for more
|
168
|
+
details.
|
169
|
+
|
170
|
+
[1]: http://rubydoc.org/gems/aws-sessionstore-dynamodb/frames
|
171
|
+
[2]: http://rubydoc.org/gems/aws-sessionstore-dynamodb/AWS/SessionStore/DynamoDB/Configuration#initialize-instance_method
|
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
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
|
+
Dir.glob(File.dirname(__FILE__) + '/tasks/*.rake').each {|file| load file }
|
15
|
+
task :default => 'test:unit'
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/lib/aws/session_store/dynamo_db/version'
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = "aws-sessionstore-dynamodb"
|
5
|
+
spec.version = AWS::SessionStore::DynamoDB::VERSION
|
6
|
+
spec.authors = ["Ruby Robinson"]
|
7
|
+
spec.summary = "The Amazon DynamoDB Session Store handles sessions " +
|
8
|
+
"for Ruby web applications using a DynamoDB backend."
|
9
|
+
spec.homepage = "http://github.com/aws/aws-sessionstore-dynamodb-ruby"
|
10
|
+
spec.license = "Apache License 2.0"
|
11
|
+
|
12
|
+
spec.files = `git ls-files`.split($/)
|
13
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
14
|
+
spec.require_paths = ["lib"]
|
15
|
+
|
16
|
+
spec.add_dependency 'aws-sdk', '~> 1.0'
|
17
|
+
spec.add_dependency 'rack', '~> 1.0'
|
18
|
+
end
|
@@ -0,0 +1,34 @@
|
|
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
|
+
|
15
|
+
module AWS
|
16
|
+
module SessionStore
|
17
|
+
module DynamoDB; end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'aws/session_store/dynamo_db/configuration'
|
22
|
+
require 'aws/session_store/dynamo_db/invalid_id_error'
|
23
|
+
require 'aws/session_store/dynamo_db/missing_secret_key_error'
|
24
|
+
require 'aws/session_store/dynamo_db/lock_wait_timeout_error'
|
25
|
+
require 'aws/session_store/dynamo_db/errors/base_handler'
|
26
|
+
require 'aws/session_store/dynamo_db/errors/default_handler'
|
27
|
+
require 'aws/session_store/dynamo_db/garbage_collection'
|
28
|
+
require 'aws/session_store/dynamo_db/locking/base'
|
29
|
+
require 'aws/session_store/dynamo_db/locking/null'
|
30
|
+
require 'aws/session_store/dynamo_db/locking/pessimistic'
|
31
|
+
require 'aws/session_store/dynamo_db/rack_middleware'
|
32
|
+
require 'aws/session_store/dynamo_db/table'
|
33
|
+
require 'aws/session_store/dynamo_db/version'
|
34
|
+
require 'aws/session_store/dynamo_db/railtie' if defined?(Rails)
|
@@ -0,0 +1,298 @@
|
|
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
|
+
require 'yaml'
|
15
|
+
require 'aws-sdk'
|
16
|
+
|
17
|
+
module AWS::SessionStore::DynamoDB
|
18
|
+
# This class provides a Configuration object for all DynamoDB transactions
|
19
|
+
# by pulling configuration options from Runtime, a YAML file, the ENV and
|
20
|
+
# default settings.
|
21
|
+
#
|
22
|
+
# == Environment Variables
|
23
|
+
# The Configuration object can load default values from your environment. An example
|
24
|
+
# of setting and environment variable is below:
|
25
|
+
#
|
26
|
+
# export DYNAMO_DB_SESSION_TABLE_NAME='Sessions'
|
27
|
+
#
|
28
|
+
# == Handling Errors
|
29
|
+
# There are two configurable options for error handling: :raise_errors and :error_handler.
|
30
|
+
#
|
31
|
+
# If you would like to use the Default Error Handler, you can decide to set :raise_errors
|
32
|
+
# to true or false depending on whether you want all errors, regadless of class, to be raised
|
33
|
+
# up the stack and essentially throw a 500.
|
34
|
+
#
|
35
|
+
# If you decide to use your own Error Handler. You may pass it in for the value of the key
|
36
|
+
# :error_handler as a cofniguration object. You must implement the BaseErrorHandler class.
|
37
|
+
# @see BaseHandler Interface for Error Handling for DynamoDB Session Store.
|
38
|
+
#
|
39
|
+
# == Locking Strategy
|
40
|
+
# By default, locking is not implemented for the session store. You must trigger the
|
41
|
+
# locking strategy through the configuration of the session store. Pessimistic locking,
|
42
|
+
# in this case, means that only one read can be made on a session at once. While the session
|
43
|
+
# is being read by the process with the lock, other processes may try to obtain a lock on
|
44
|
+
# the same session but will be blocked. See the accessors with lock in their name for
|
45
|
+
# how to configure the pessimistic locking strategy to your needs.
|
46
|
+
#
|
47
|
+
# == DynamoDB Specific Options
|
48
|
+
# You may configure the table name and table hash key value of your session table with
|
49
|
+
# the :table_name and :table_key options. You may also configure performance options for
|
50
|
+
# your table with the :consistent_read, :read_capacity, write_capacity. For more information
|
51
|
+
# about these configurations see CreateTable method for Amazon DynamoDB.
|
52
|
+
#
|
53
|
+
class Configuration
|
54
|
+
|
55
|
+
# Default configuration options
|
56
|
+
DEFAULTS = {
|
57
|
+
:table_name => "sessions",
|
58
|
+
:table_key => "session_id",
|
59
|
+
:consistent_read => true,
|
60
|
+
:read_capacity => 10,
|
61
|
+
:write_capacity => 5,
|
62
|
+
:raise_errors => false,
|
63
|
+
# :max_age => 7*3600*24,
|
64
|
+
# :max_stale => 3600*5,
|
65
|
+
:enable_locking => false,
|
66
|
+
:lock_expiry_time => 500,
|
67
|
+
:lock_retry_delay => 500,
|
68
|
+
:lock_max_wait_time => 1,
|
69
|
+
:secret_key => nil,
|
70
|
+
:api_version => '2012-08-10'
|
71
|
+
}
|
72
|
+
|
73
|
+
# @return [String] Session table name.
|
74
|
+
attr_reader :table_name
|
75
|
+
|
76
|
+
# @return [String] Session table hash key name.
|
77
|
+
attr_reader :table_key
|
78
|
+
|
79
|
+
# @return [true] If a strongly consistent read is used
|
80
|
+
# @return [false] If an eventually consistent read is used.
|
81
|
+
# See AWS DynamoDB documentation for table consistent_read for more
|
82
|
+
# information on this setting.
|
83
|
+
attr_reader :consistent_read
|
84
|
+
|
85
|
+
# @return [Integer] Maximum number of reads consumed per second before
|
86
|
+
# DynamoDB returns a ThrottlingException. See AWS DynamoDB documentation
|
87
|
+
# for table read_capacity for more information on this setting.
|
88
|
+
attr_reader :read_capacity
|
89
|
+
|
90
|
+
# @return [Integer] Maximum number of writes consumed per second before
|
91
|
+
# DynamoDB returns a ThrottlingException. See AWS DynamoDB documentation
|
92
|
+
# for table write_capacity for more information on this setting.
|
93
|
+
attr_reader :write_capacity
|
94
|
+
|
95
|
+
# @return [true] All errors are raised up the stack when default ErrorHandler
|
96
|
+
# is used.
|
97
|
+
# @return [false] Only specified errors are raised up the stack when default
|
98
|
+
# ErrorHandler is used.
|
99
|
+
attr_reader :raise_errors
|
100
|
+
|
101
|
+
# @return [DynamoDB Client] DynamoDB client.
|
102
|
+
attr_reader :dynamo_db_client
|
103
|
+
|
104
|
+
# @return [Error Handler] An error handling object that handles all exceptions
|
105
|
+
# thrown during execution of the AWS DynamoDB Session Store Rack Middleware.
|
106
|
+
# For more information see the Handling Errors Section.
|
107
|
+
attr_reader :error_handler
|
108
|
+
|
109
|
+
# @return [Integer] Maximum number of seconds earlier
|
110
|
+
# from the current time that a session was created.
|
111
|
+
attr_reader :max_age
|
112
|
+
|
113
|
+
# @return [Integer] Maximum number of seconds
|
114
|
+
# before the current time that the session was last accessed.
|
115
|
+
attr_reader :max_stale
|
116
|
+
|
117
|
+
# @return [String] The secret key for HMAC encryption.
|
118
|
+
attr_reader :secret_key
|
119
|
+
|
120
|
+
# @return [true] Pessimistic locking strategy will be implemented for
|
121
|
+
# all session accesses.
|
122
|
+
# @return [false] No locking strategy will be implemented for
|
123
|
+
# all session accesses.
|
124
|
+
attr_reader :enable_locking
|
125
|
+
|
126
|
+
# @return [Integer] Time in milleseconds after which lock will expire.
|
127
|
+
attr_reader :lock_expiry_time
|
128
|
+
|
129
|
+
# @return [Integer] Time in milleseconds to wait before retrying to obtain
|
130
|
+
# lock once an attempt to obtain lock has been made and has failed.
|
131
|
+
attr_reader :lock_retry_delay
|
132
|
+
|
133
|
+
# @return [Integer] Maximum time in seconds to wait to acquire lock
|
134
|
+
# before giving up.
|
135
|
+
attr_reader :lock_max_wait_time
|
136
|
+
|
137
|
+
|
138
|
+
# Provides configuration object that allows access to options defined
|
139
|
+
# during Runtime, in a YAML file, in the ENV and by default.
|
140
|
+
#
|
141
|
+
# @option options [String] :table_name ("Sessions") Name of the session
|
142
|
+
# table.
|
143
|
+
# @option options [String] :table_key ("id") The hash key of the sesison
|
144
|
+
# table.
|
145
|
+
# @option options [Boolean] :consistent_read (true) If true, a strongly
|
146
|
+
# consistent read is used. If false, an eventually consistent read is
|
147
|
+
# used.
|
148
|
+
# @option options [Integer] :read_capacity (10) The maximum number of
|
149
|
+
# strongly consistent reads consumed per second before
|
150
|
+
# DynamoDB raises a ThrottlingException. See AWS DynamoDB documentation
|
151
|
+
# for table read_capacity for more information on this setting.
|
152
|
+
# @option options [Integer] :write_capacity (5) The maximum number of writes
|
153
|
+
# consumed per second before DynamoDB returns a ThrottlingException.
|
154
|
+
# See AWS DynamoDB documentation for table write_capacity for more
|
155
|
+
# information on this setting.
|
156
|
+
# @option options [DynamoDB Client] :dynamo_db_client
|
157
|
+
# (AWS::DynamoDB::ClientV2) DynamoDB client used to perform database
|
158
|
+
# operations inside of middleware application.
|
159
|
+
# @option options [Boolean] :raise_errors (false) If true, all errors are
|
160
|
+
# raised up the stack when default ErrorHandler. If false, Only specified
|
161
|
+
# errors are raised up the stack when default ErrorHandler is used.
|
162
|
+
# @option options [Error Handler] :error_handler (DefaultErrorHandler)
|
163
|
+
# An error handling object that handles all exceptions thrown during
|
164
|
+
# execution of the AWS DynamoDB Session Store Rack Middleware.
|
165
|
+
# For more information see the Handling Errors Section.
|
166
|
+
# @option options [Integer] :max_age (nil) Maximum number of seconds earlier
|
167
|
+
# from the current time that a session was created.
|
168
|
+
# @option options [Integer] :max_stale (nil) Maximum number of seconds
|
169
|
+
# before current time that session was last accessed.
|
170
|
+
# @option options [String] :secret_key (nil) Secret key for HMAC encription.
|
171
|
+
# @option options [Integer] :enable_locking (false) If true, a pessimistic
|
172
|
+
# locking strategy will be implemented for all session accesses.
|
173
|
+
# If false, no locking strategy will be implemented for all session
|
174
|
+
# accesses.
|
175
|
+
# @option options [Integer] :lock_expiry_time (500) Time in milliseconds
|
176
|
+
# after which lock expires on session.
|
177
|
+
# @option options [Integer] :lock_retry_delay (500) Time in milleseconds to
|
178
|
+
# wait before retrying to obtain lock once an attempt to obtain lock
|
179
|
+
# has been made and has failed.
|
180
|
+
# @option options [Integer] :lock_max_wait_time (500) Maximum time in seconds
|
181
|
+
# to wait to acquire lock before giving up.
|
182
|
+
# @option options [String] :secret_key (SecureRandom.hex(64))
|
183
|
+
# Secret key for HMAC encription.
|
184
|
+
def initialize(options = {})
|
185
|
+
@options = default_options.merge(
|
186
|
+
env_options.merge(
|
187
|
+
file_options(options).merge(
|
188
|
+
symbolize_keys(options)
|
189
|
+
)
|
190
|
+
)
|
191
|
+
)
|
192
|
+
@options = client_error.merge(@options)
|
193
|
+
set_attributes(@options)
|
194
|
+
end
|
195
|
+
|
196
|
+
# @return [Hash] The merged configuration hash.
|
197
|
+
def to_hash
|
198
|
+
@options.dup
|
199
|
+
end
|
200
|
+
|
201
|
+
private
|
202
|
+
|
203
|
+
# @return [Hash] DDB client.
|
204
|
+
def gen_dynamo_db_client
|
205
|
+
client_opts = client_subset(@options)
|
206
|
+
client = AWS::DynamoDB::Client
|
207
|
+
dynamo_db_client = @options[:dynamo_db_client] || client.new(client_opts)
|
208
|
+
{:dynamo_db_client => dynamo_db_client}
|
209
|
+
end
|
210
|
+
|
211
|
+
# @return [Hash] Default Error Handler
|
212
|
+
def gen_error_handler
|
213
|
+
default_handler = AWS::SessionStore::DynamoDB::Errors::DefaultHandler
|
214
|
+
error_handler = @options[:error_handler] ||
|
215
|
+
default_handler.new(@options[:raise_errors])
|
216
|
+
{:error_handler => error_handler}
|
217
|
+
end
|
218
|
+
|
219
|
+
# @return [Hash] Client and error objects in hash.
|
220
|
+
def client_error
|
221
|
+
gen_error_handler.merge(gen_dynamo_db_client)
|
222
|
+
end
|
223
|
+
|
224
|
+
# @return [Hash] Default Session table options.
|
225
|
+
def default_options
|
226
|
+
DEFAULTS
|
227
|
+
end
|
228
|
+
|
229
|
+
# @return [Hash] Environment options that are useful for Session Handler.
|
230
|
+
def env_options
|
231
|
+
default_options.keys.inject({}) do |opts, opt_name|
|
232
|
+
env_var = "DYNAMO_DB_SESSION_#{opt_name.to_s.upcase}"
|
233
|
+
opts[opt_name] = ENV[env_var] if ENV.key?(env_var)
|
234
|
+
opts
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
# @return [Hash] File options.
|
239
|
+
def file_options(options = {})
|
240
|
+
file_path = config_file_path(options)
|
241
|
+
if file_path
|
242
|
+
load_from_file(file_path)
|
243
|
+
elsif rails_defined && File.exists?(rails_config_file_path)
|
244
|
+
load_from_file(rails_config_file_path)
|
245
|
+
else
|
246
|
+
{}
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
# @return [Boolean] Necessary Rails variables defined.
|
251
|
+
def rails_defined
|
252
|
+
defined?(Rails) && defined?(Rails.root) && defined?(Rails.env)
|
253
|
+
end
|
254
|
+
|
255
|
+
# Load options from YAML file depending on existence of Rails
|
256
|
+
# and possible development stage defined.
|
257
|
+
def load_from_file(file_path)
|
258
|
+
require "erb"
|
259
|
+
opts = YAML.load(ERB.new(File.read(file_path)).result) || {}
|
260
|
+
opts = opts[Rails.env] if rails_defined && opts.key?(Rails.env)
|
261
|
+
symbolize_keys(opts)
|
262
|
+
end
|
263
|
+
|
264
|
+
# @return [String] Configuration path found in environment or YAML file.
|
265
|
+
def config_file_path(options)
|
266
|
+
options[:config_file] || ENV["DYNAMO_DB_SESSION_CONFIG_FILE"]
|
267
|
+
end
|
268
|
+
|
269
|
+
# @return [String] Rails configuraton path to YAML file default.
|
270
|
+
def rails_config_file_path
|
271
|
+
File.join(Rails.root, "config", "sessionstore/dynamodb.yml")
|
272
|
+
end
|
273
|
+
|
274
|
+
# Set accessible attributes after merged options.
|
275
|
+
def set_attributes(options)
|
276
|
+
@options.keys.each do |opt_name|
|
277
|
+
instance_variable_set("@#{opt_name}", options[opt_name])
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
# @return [Hash] Hash with all symbolized keys.
|
282
|
+
def symbolize_keys(options)
|
283
|
+
options.inject({}) do |opts, (opt_name, opt_value)|
|
284
|
+
opts[opt_name.to_sym] = opt_value
|
285
|
+
opts
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
# @return [Hash] Client subset options hash.
|
290
|
+
def client_subset(options = {})
|
291
|
+
client_keys = [:aws_secret_key, :aws_region, :aws_access_key, :api_version]
|
292
|
+
options.inject({}) do |opts, (opt_name, opt_value)|
|
293
|
+
opts[opt_name.to_sym] = opt_value if client_keys.include?(opt_name.to_sym)
|
294
|
+
opts
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|