Skip to content

Commit edeb3d1

Browse files
authored
Modularize Session Store (#147)
1 parent 3bbbf0a commit edeb3d1

File tree

38 files changed

+649
-290
lines changed

38 files changed

+649
-290
lines changed

.github/workflows/ci.yml

Lines changed: 47 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ on:
99
branches:
1010
- main
1111

12+
env:
13+
ruby_version: 3.3
14+
1215
jobs:
1316
test:
1417
runs-on: ubuntu-latest
@@ -19,7 +22,7 @@ jobs:
1922
rails: ['7.0', 7.1, 7.2, main]
2023

2124
exclude:
22-
# Rails 7.1 dropped support for older rubygems
25+
# Rails 7.2 dropped support for older rubygems
2326
- rails: 7.2
2427
ruby: 2.7
2528
- rails: 7.2
@@ -61,49 +64,55 @@ jobs:
6164
rubocop:
6265
runs-on: ubuntu-latest
6366

64-
steps:
65-
- name: Set up Ruby 3.3
66-
uses: ruby/setup-ruby@v1
67-
with:
68-
ruby-version: 3.3
69-
70-
- uses: actions/checkout@v4
71-
72-
- name: Install gems
73-
run: bundle install
74-
75-
- name: Rubocop
76-
run: bundle exec rubocop -E -S
77-
78-
test-sample-app:
79-
runs-on: ubuntu-latest
80-
services:
81-
dynamodb:
82-
image: amazon/dynamodb-local:latest
83-
ports:
84-
- 8000:8000
85-
env:
86-
AWS_REGION: us-east-1
87-
AWS_ACCESS_KEY_ID: dummy
88-
AWS_SECRET_ACCESS_KEY: dummy
89-
AWS_ENDPOINT_URL: http://localhost:8000
9067
steps:
9168
- uses: actions/checkout@v4
9269

9370
- name: Setup Ruby
9471
uses: ruby/setup-ruby@v1
9572
with:
96-
bundler-cache: true
97-
working-directory: ${{ github.workspace }}/sample_app
73+
ruby-version: ${{ env.ruby_version }}
9874

99-
- name: Create table
100-
run: cd ${{ github.workspace }}/sample_app && bin/rails runner Aws::SessionStore::DynamoDB::Table.create_table
101-
102-
- name: Insert dummy manifest.json
75+
- name: Install gems
10376
run: |
104-
mkdir -p ${{ github.workspace }}/sample_app/public/packs-test
105-
echo "{\"application.js\":\"/packs-test/js/application-dummy.js\"}" >> ${{ github.workspace }}/sample_app/public/packs-test/manifest.json
77+
bundle config set --local with 'development'
78+
bundle install
10679
107-
- name: Test
108-
run: bundle exec rake test
109-
working-directory: ${{ github.workspace }}/sample_app
80+
- name: Rubocop
81+
run: bundle exec rake rubocop
82+
83+
# test-sample-app:
84+
# runs-on: ubuntu-latest
85+
# services:
86+
# dynamodb:
87+
# image: amazon/dynamodb-local:latest
88+
# ports:
89+
# - 8000:8000
90+
# env:
91+
# AWS_REGION: us-east-1
92+
# AWS_ACCESS_KEY_ID: dummy
93+
# AWS_SECRET_ACCESS_KEY: dummy
94+
# AWS_ENDPOINT_URL: http://localhost:8000
95+
# steps:
96+
# - uses: actions/checkout@v4
97+
#
98+
# - name: Setup Ruby
99+
# uses: ruby/setup-ruby@v1
100+
# with:
101+
# ruby-version: ${{ env.ruby_version }}
102+
# bundler-cache: true
103+
# working-directory: ${{ github.workspace }}/sample_app
104+
#
105+
# - name: Create table
106+
# run: cd ${{ github.workspace }}/sample_app && bin/rails runner Aws::SessionStore::DynamoDB::Table.create_table
107+
#
108+
# - name: Insert dummy manifest.json
109+
# run: |
110+
# mkdir -p ${{ github.workspace }}/sample_app/public/packs-test
111+
# echo "{\"application.js\":\"/packs-test/js/application-dummy.js\"}" >> ${{ github.workspace }}/sample_app/public/packs-test/manifest.json
112+
#
113+
# - name: DB Migrate
114+
# run: cd ${{ github.workspace }}/sample_app && bin/rails db:migrate
115+
#
116+
# - name: Test
117+
# run: bundle exec rake test
118+
# working-directory: ${{ github.workspace }}/sample_app

.gitignore

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,25 @@
1-
.bundle
2-
.byebug_history
3-
.yardoc
4-
.ruby-version
1+
.DS_Store
2+
3+
/.byebug_history
4+
/.bundle
5+
/.yardoc
6+
/doc
7+
/Gemfile.lock
8+
/coverage
59
*.gem
6-
coverage
7-
doc
8-
docs.zip
9-
Gemfile.lock
10-
sample_app/Gemfile.lock
10+
/.release
11+
12+
.idea/
13+
1114
gemfiles/*.gemfile.lock
15+
16+
test/dummy/db/migrate
17+
test/dummy/log/
18+
19+
sample_app/Gemfile.lock
1220
spec/dummy/db/test.db-shm
1321
spec/dummy/db/test.db-wal
1422
spec/dummy/db/test.db
1523
spec/dummy/db/schema.rb
1624
spec/dummy/log/
17-
spec/dummy/tmp/
18-
vendor
19-
.idea/
20-
.release/
25+
spec/dummy/tmp/

.rubocop.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,5 @@ Style/Documentation:
4444
Exclude:
4545
- 'lib/generators/**/*.rb'
4646
- 'lib/aws/rails/notifications.rb'
47+
- 'test/**/*.rb'
4748
- 'spec/**/*.rb'

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
Unreleased Changes
22
------------------
33

4+
* Feature - Add session store config generation.
5+
6+
* Feature - Prepare modularization of `aws-sessionstore-dynamodb`.
7+
48
4.1.0 (2024-09-27)
59
------------------
610

Gemfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@ group :development, :test do
99
end
1010

1111
group :development do
12+
gem 'byebug', platforms: :ruby
1213
gem 'rubocop'
1314
end
1415

1516
group :test do
1617
gem 'bcrypt'
18+
gem 'minitest-spec-rails'
1719
gem 'rspec-rails'
1820
gem 'webmock'
1921
end

README.md

Lines changed: 85 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ This gem also brings in the following AWS gems:
2424
* `aws-sdk-sqs`
2525
* `aws-sdk-sns`
2626
* `aws-record`
27-
* `aws-sessionstore-dynamodb`
2827

2928
You will have to ensure that you provide credentials for the SDK to use. See the
3029
latest [AWS SDK for Ruby Docs](https://docs.aws.amazon.com/sdk-for-ruby/v3/api/index.html#Configuration)
@@ -72,7 +71,35 @@ configuration: they will be loaded automatically.
7271

7372
You can configure session storage in Rails to use DynamoDB instead of cookies,
7473
allowing access to sessions from other applications and devices. You will need
75-
to have an existing Amazon DynamoDB session table to use this feature.
74+
to have or create an existing Amazon DynamoDB session table to use this feature.
75+
76+
To enable this feature, add the following to your Gemfile:
77+
78+
```ruby
79+
gem 'aws-sessionstore-dynamodb', '~> 2'
80+
```
81+
82+
For more information about this feature and configuration options, see the
83+
[API reference](https://docs.aws.amazon.com/sdk-for-ruby/aws-sessionstore-dynamodb/api/)
84+
and the
85+
[GitHub repository](https://github.com/aws/aws-sessionstore-dynamodb-ruby).
86+
87+
### Configuration generator
88+
89+
You can generate a configuration file for the session store using the following
90+
command (--environment=<environment> is optional):
91+
92+
```bash
93+
rails generate dynamo_db:session_store_config --environment=<Rails.env>
94+
```
95+
96+
The session store configuration generator command will generate a YAML file
97+
`config/dynamo_db_session_store.yml` with default options. If provided an
98+
environment, the file will be named
99+
`config/dynamo_db_session_store/<Rails.env>.yml`, which takes precedence over
100+
the default file.
101+
102+
### ActiveRecord Migration generator
76103

77104
You can generate a migration file for the session table using the following
78105
command (<MigrationName> is optional):
@@ -81,29 +108,55 @@ command (<MigrationName> is optional):
81108
rails generate dynamo_db:session_store_migration <MigrationName>
82109
```
83110

84-
The session store migration generator command will generate two files: a
85-
migration file, `db/migration/#{VERSION}_#{MIGRATION_NAME}.rb`, and a
86-
configuration YAML file, `config/dynamo_db_session_store.yml`.
111+
The session store migration generator command will generate a
112+
migration file `db/migration/#{VERSION}_#{MIGRATION_NAME}.rb`.
87113

88114
The migration file will create and delete a table with default options. These
89-
options can be changed prior to running the migration and are documented in the
90-
[Table](https://docs.aws.amazon.com/sdk-for-ruby/aws-sessionstore-dynamodb/api/Aws/SessionStore/DynamoDB/Table.html) class.
115+
options can be changed prior to running the migration either in code by editing
116+
the migration file or in the config YAML file. These options are documented in
117+
the
118+
[Table](https://docs.aws.amazon.com/sdk-for-ruby/aws-sessionstore-dynamodb/api/Aws/SessionStore/DynamoDB/Table.html)
119+
class.
91120

92121
To create the table, run migrations as normal with:
93122

94123
```bash
95124
rails db:migrate
96125
```
97126

98-
Next, configure the Rails session store to be `:dynamodb_store` by editing
99-
`config/initializers/session_store.rb` to contain the following:
127+
To delete the table and rollback, run the following command:
128+
129+
```bash
130+
rails db:migrate:down VERSION=<VERSION>
131+
```
132+
133+
### Migration Rake tasks
134+
135+
If you are not using ActiveRecord, you can manage the table using the provided
136+
Rake tasks:
137+
138+
```bash
139+
rake dynamo_db:session_store:create_table
140+
rake dynamo_db:session_store:delete_table
141+
```
142+
143+
The rake tasks will create and delete a table with default options. These
144+
options can be changed prior to running the task in the config YAML file. These
145+
options are documented in the
146+
[Table](https://docs.aws.amazon.com/sdk-for-ruby/aws-sessionstore-dynamodb/api/Aws/SessionStore/DynamoDB/Table.html)
147+
class.
148+
149+
### Usage
150+
151+
To use the session store, add or edit your
152+
`config/initializers/session_store.rb` file:
100153

101154
```ruby
102-
# config/initializers/session_store.rb
103-
Rails.application.config.session_store :dynamodb_store, key: '_your_app_session'
155+
options = { table_name: '_your_app_session' } # overrides from YAML or ENV
156+
Rails.application.config.session_store :dynamo_db_store, **options
104157
```
105158

106-
You can now start your Rails application with session support.
159+
You can now start your Rails application with DynamoDB session support.
107160

108161
### Configuration
109162

@@ -113,38 +166,41 @@ initializer like so:
113166

114167
```ruby
115168
# config/initializers/session_store.rb
116-
Rails.application.config.session_store :dynamodb_store,
117-
key: '_your_app_session',
118-
table_name: 'foo',
169+
Rails.application.config.session_store :dynamo_db_store,
170+
table_name: 'your-table-name',
171+
table_key: 'your-session-key',
119172
dynamo_db_client: my_ddb_client
120173
```
121174

122-
Alternatively, you can use the generated YAML configuration file
123-
`config/dynamo_db_session_store.yml`. YAML configuration may also be specified
124-
per environment, with environment configuration having precedence. To do this,
125-
create `config/dynamo_db_session_store/#{Rails.env}.yml` files as needed.
126-
127-
For configuration options, see the [Configuration](https://docs.aws.amazon.com/sdk-for-ruby/aws-sessionstore-dynamodb/api/Aws/SessionStore/DynamoDB/Configuration.html) class.
175+
Alternatively, you can use the generated YAML configuration files
176+
`config/dynamo_db_session_store.yml` or
177+
`config/dynamo_db_session_store/<Rails.env>.yml`.
128178

129-
#### Rack Configuration
179+
For configuration options, see the [Configuration]
180+
(https://docs.aws.amazon.com/sdk-for-ruby/aws-sessionstore-dynamodb/api/Aws/SessionStore/DynamoDB/Configuration.html)
181+
class.
130182

131-
DynamoDB session storage is implemented in the [\`aws-sessionstore-dynamodb\`](https://github.com/aws/aws-sessionstore-dynamodb-ruby)
132-
gem. The Rack middleware inherits from the [\`Rack::Session::Abstract::Persisted\`](https://www.rubydoc.info/github/rack/rack/Rack/Session/Abstract/Persisted)
183+
The session store inherits from the
184+
[`Rack::Session::Abstract::Persisted`](https://rubydoc.info/github/rack/rack-session/main/Rack/Session/Abstract/Persisted)
133185
class, which also includes additional options (such as `:key`) that can be
134186
passed into the Rails initializer.
135187

136188
### Cleaning old sessions
137189

138-
By default sessions do not expire. See `config/dynamo_db_session_store.yml` to
190+
By default sessions do not expire. You can use `:max_age` and `:max_stale` to
139191
configure the max age or stale period of a session.
140192

141-
You can use the DynamoDB [Time to Live (TTL) feature](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/TTL.html)
142-
on the `expire_at` attribute to automatically delete expired items.
193+
You can use the DynamoDB
194+
[Time to Live (TTL) feature](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/TTL.html)
195+
on the `expire_at` attribute to automatically delete expired items, saving you
196+
the trouble of manually deleting them and reducing costs.
143197

144-
Alternatively, a Rake task for garbage collection is provided:
198+
If you wish to delete old sessions based on creation age (invalidating valid
199+
sessions) or if you want control over the garbage collection process, you can
200+
use the provided Rake task:
145201

146202
```bash
147-
rake dynamo_db:collect_garbage
203+
rake dynamo_db:session_store:clean
148204
```
149205

150206
## Amazon Simple Email Service (SES) as an ActionMailer Delivery Method

Rakefile

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# frozen_string_literal: true
22

33
require 'rspec/core/rake_task'
4+
require 'rake/testtask'
45
require 'rubocop/rake_task'
56

67
$REPO_ROOT = File.dirname(__FILE__)
@@ -14,6 +15,15 @@ RuboCop::RakeTask.new
1415

1516
RSpec::Core::RakeTask.new(:spec)
1617

18+
# Eventually, migrate all tests back into the minitest
19+
# runner. But use minitest-spec-rails to enable syntax.
20+
# Currently, rails generator specs are not running.
21+
Rake::TestTask.new('test:rails') do |t|
22+
t.libs << 'test'
23+
t.pattern = 'test/**/*_test.rb'
24+
t.warning = false
25+
end
26+
1727
task :db_migrate do
1828
Dir.chdir('spec/dummy') do
1929
version = ENV.delete('VERSION') # ActiveRecord uses this
@@ -22,6 +32,6 @@ task :db_migrate do
2232
end
2333
end
2434

25-
task test: %i[db_migrate spec]
35+
task test: [:db_migrate, :spec, 'test:rails']
2636
task default: :test
2737
task 'release:test' => :test

gemfiles/rails-main.gemfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,5 @@ group :test do
1616
# this is not published for some reason
1717
git: 'https://github.com/jruby/activerecord-jdbc-adapter',
1818
glob: 'activerecord-jdbcsqlite3-adapter/activerecord-jdbcsqlite3-adapter.gemspec'
19-
gem 'sqlite3', '~> 2.0.0', platform: :ruby
19+
gem 'sqlite3', platform: :ruby
2020
end

0 commit comments

Comments
 (0)