aws-sessionstore-dynamodb 2.2.0 → 3.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.
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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Aws::SessionStore::DynamoDB::Errors
2
4
  # This class handles errors raised from DynamoDB.
3
5
  class DefaultHandler < Aws::SessionStore::DynamoDB::Errors::BaseHandler
@@ -5,38 +7,37 @@ module Aws::SessionStore::DynamoDB::Errors
5
7
  HARD_ERRORS = [
6
8
  Aws::DynamoDB::Errors::ResourceNotFoundException,
7
9
  Aws::DynamoDB::Errors::ConditionalCheckFailedException,
8
- Aws::SessionStore::DynamoDB::MissingSecretKeyError,
9
- Aws::SessionStore::DynamoDB::LockWaitTimeoutError
10
- ]
10
+ Aws::SessionStore::DynamoDB::Errors::MissingSecretKeyError,
11
+ Aws::SessionStore::DynamoDB::Errors::LockWaitTimeoutError
12
+ ].freeze
11
13
 
12
14
  # Determines behavior of DefaultErrorHandler
13
15
  # @param [true] raise_errors Pass all errors up the Rack stack.
14
16
  def initialize(raise_errors)
17
+ super()
15
18
  @raise_errors = raise_errors
16
19
  end
17
20
 
18
21
  # Raises {HARD_ERRORS} up the Rack stack.
19
22
  # Places all other errors in Racks error stream.
20
23
  def handle_error(error, env = {})
21
- if HARD_ERRORS.include?(error.class) || @raise_errors
22
- raise error
23
- else
24
- store_error(error, env)
25
- false
26
- end
24
+ raise error if HARD_ERRORS.include?(error.class) || @raise_errors
25
+
26
+ store_error(error, env)
27
+ false
27
28
  end
28
29
 
29
30
  # Sends error to error stream
30
31
  def store_error(error, env = {})
31
- env["rack.errors"].puts(errors_string(error)) if env
32
+ env['rack.errors'].puts(errors_string(error)) if env
32
33
  end
33
34
 
34
35
  # Returns string to be placed in error stream
35
36
  def errors_string(error)
36
37
  str = []
37
38
  str << "Exception occurred: #{error.message}"
38
- str << "Stack trace:"
39
- str += error.backtrace.map {|l| " " + l }
39
+ str << 'Stack trace:'
40
+ str += error.backtrace.map { |l| " #{l}" }
40
41
  str.join("\n")
41
42
  end
42
43
  end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws::SessionStore::DynamoDB::Errors
4
+ # This error is raised when no secret key is provided.
5
+ class MissingSecretKeyError < RuntimeError
6
+ def initialize(msg = 'No secret key provided!')
7
+ super
8
+ end
9
+ end
10
+
11
+ # This error is raised when an invalid session ID is provided.
12
+ class InvalidIDError < RuntimeError
13
+ def initialize(msg = 'Corrupt Session ID!')
14
+ super
15
+ end
16
+ end
17
+
18
+ # This error is raised when the maximum time spent to acquire lock has been exceeded.
19
+ class LockWaitTimeoutError < RuntimeError
20
+ def initialize(msg = 'Maximum time spent to acquire lock has been exceeded!')
21
+ super
22
+ end
23
+ end
24
+ end
25
+
26
+ require_relative 'errors/base_handler'
27
+ require_relative 'errors/default_handler'
@@ -1,115 +1,106 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'aws-sdk-dynamodb'
2
4
 
3
5
  module Aws::SessionStore::DynamoDB
4
6
  # Collects and deletes unwanted sessions based on
5
7
  # their creation and update dates.
6
8
  module GarbageCollection
7
- module_function
8
-
9
- # Scans DynamoDB session table to find
10
- # sessions that match the max age and max stale period
11
- # requirements. it then deletes all of the found sessions.
12
- def collect_garbage(options = {})
13
- config = load_config(options)
14
- last_key = eliminate_unwanted_sessions(config)
15
- while !last_key.empty?
16
- last_key = eliminate_unwanted_sessions(config, last_key)
9
+ class << self
10
+ # Scans DynamoDB session table to find sessions that match the max age and
11
+ # max stale period requirements. it then deletes all of the found sessions.
12
+ def collect_garbage(options = {})
13
+ config = load_config(options)
14
+ last_key = eliminate_unwanted_sessions(config)
15
+ last_key = eliminate_unwanted_sessions(config, last_key) until last_key.empty?
17
16
  end
18
- end
19
17
 
20
- # Loads configuration options.
21
- # @option (see Configuration#initialize)
22
- # @api private
23
- def load_config(options = {})
24
- Aws::SessionStore::DynamoDB::Configuration.new(options)
25
- end
18
+ private
26
19
 
27
- # Sets scan filter attributes based on attributes specified.
28
- # @api private
29
- def scan_filter(config)
30
- hash = {}
31
- hash['created_at'] = oldest_date(config.max_age) if config.max_age
32
- hash['updated_at'] = oldest_date(config.max_stale) if config.max_stale
33
- { :scan_filter => hash }
34
- end
20
+ # Loads configuration options.
21
+ # @option (see Configuration#initialize)
22
+ def load_config(options = {})
23
+ Aws::SessionStore::DynamoDB::Configuration.new(options)
24
+ end
35
25
 
36
- # Scans and deletes batch.
37
- # @api private
38
- def eliminate_unwanted_sessions(config, last_key = nil)
39
- scan_result = scan(config, last_key)
40
- batch_delete(config, scan_result[:items])
41
- scan_result[:last_evaluated_key] || {}
42
- end
26
+ # Sets scan filter attributes based on attributes specified.
27
+ def scan_filter(config)
28
+ hash = {}
29
+ hash['created_at'] = oldest_date(config.max_age) if config.max_age
30
+ hash['updated_at'] = oldest_date(config.max_stale) if config.max_stale
31
+ { scan_filter: hash }
32
+ end
43
33
 
44
- # Scans the table for sessions matching the max age and
45
- # max stale time specified.
46
- # @api private
47
- def scan(config, last_item = nil)
48
- options = scan_opts(config)
49
- options = options.merge(start_key(last_item)) if last_item
50
- config.dynamo_db_client.scan(options)
51
- end
34
+ # Scans and deletes batch.
35
+ def eliminate_unwanted_sessions(config, last_key = nil)
36
+ scan_result = scan(config, last_key)
37
+ batch_delete(config, scan_result[:items])
38
+ scan_result[:last_evaluated_key] || {}
39
+ end
52
40
 
53
- # Deletes the batch gotten from the scan result.
54
- # @api private
55
- def batch_delete(config, items)
56
- begin
57
- subset = items.shift(25)
58
- sub_batch = write(subset)
59
- process!(config, sub_batch)
60
- end until subset.empty?
61
- end
41
+ # Scans the table for sessions matching the max age and
42
+ # max stale time specified.
43
+ def scan(config, last_item = nil)
44
+ options = scan_opts(config)
45
+ options = options.merge(start_key(last_item)) if last_item
46
+ config.dynamo_db_client.scan(options)
47
+ end
62
48
 
63
- # Turns array into correct format to be passed in to
64
- # a delete request.
65
- # @api private
66
- def write(sub_batch)
67
- sub_batch.inject([]) do |rqst_array, item|
68
- rqst_array << {:delete_request => {:key => item}}
69
- rqst_array
49
+ # Deletes the batch gotten from the scan result.
50
+ def batch_delete(config, items)
51
+ loop do
52
+ subset = items.shift(25)
53
+ sub_batch = write(subset)
54
+ process!(config, sub_batch)
55
+ break if subset.empty?
56
+ end
70
57
  end
71
- end
72
58
 
73
- # Proccesses pending request items.
74
- # @api private
75
- def process!(config, sub_batch)
76
- return if sub_batch.empty?
77
- opts = {}
78
- opts[:request_items] = {config.table_name => sub_batch}
79
- begin
80
- response = config.dynamo_db_client.batch_write_item(opts)
81
- opts[:request_items] = response[:unprocessed_items]
82
- end until opts[:request_items].empty?
83
- end
59
+ # Turns array into correct format to be passed in to
60
+ # a delete request.
61
+ def write(sub_batch)
62
+ sub_batch.each_with_object([]) do |item, rqst_array|
63
+ rqst_array << { delete_request: { key: item } }
64
+ end
65
+ end
84
66
 
85
- # Provides scan options.
86
- # @api private
87
- def scan_opts(config)
88
- table_opts(config).merge(scan_filter(config))
89
- end
67
+ # Processes pending request items.
68
+ def process!(config, sub_batch)
69
+ return if sub_batch.empty?
90
70
 
91
- # Provides table options
92
- # @api private
93
- def table_opts(config)
94
- {
95
- :table_name => config.table_name,
96
- :attributes_to_get => [config.table_key]
97
- }
98
- end
71
+ opts = { request_items: { config.table_name => sub_batch } }
72
+ loop do
73
+ response = config.dynamo_db_client.batch_write_item(opts)
74
+ opts[:request_items] = response[:unprocessed_items]
75
+ break if opts[:request_items].empty?
76
+ end
77
+ end
99
78
 
100
- # @return [Hash] Hash with specified date attributes.
101
- # @api private
102
- def oldest_date(sec)
103
- hash = {}
104
- hash[:attribute_value_list] = [:n => "#{((Time.now - sec).to_f)}"]
105
- hash[:comparison_operator] = 'LT'
106
- hash
107
- end
79
+ # Provides scan options.
80
+ def scan_opts(config)
81
+ table_opts(config).merge(scan_filter(config))
82
+ end
83
+
84
+ # Provides table options
85
+ def table_opts(config)
86
+ {
87
+ table_name: config.table_name,
88
+ attributes_to_get: [config.table_key]
89
+ }
90
+ end
108
91
 
109
- # Provides start key.
110
- # @api private
111
- def start_key(last_item)
112
- { :exclusive_start_key => last_item }
92
+ # Provides specified date attributes.
93
+ def oldest_date(sec)
94
+ {
95
+ attribute_value_list: [n: (Time.now - sec).to_f.to_s],
96
+ comparison_operator: 'LT'
97
+ }
98
+ end
99
+
100
+ # Provides start key.
101
+ def start_key(last_item)
102
+ { exclusive_start_key: last_item }
103
+ end
113
104
  end
114
105
  end
115
106
  end
@@ -1,9 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Aws::SessionStore::DynamoDB::Locking
2
- # This class provides a framework for implementing
3
- # locking strategies.
4
+ # Handles session management.
4
5
  class Base
5
-
6
- # Creates configuration object.
6
+ # @param [Aws::SessionStore::DynamoDB::Configuration] cfg
7
7
  def initialize(cfg)
8
8
  @config = cfg
9
9
  end
@@ -11,6 +11,7 @@ module Aws::SessionStore::DynamoDB::Locking
11
11
  # Updates session in database
12
12
  def set_session_data(env, sid, session, options = {})
13
13
  return false if session.empty?
14
+
14
15
  packed_session = pack_data(session)
15
16
  handle_error(env) do
16
17
  save_opts = update_opts(env, sid, packed_session, options)
@@ -19,12 +20,7 @@ module Aws::SessionStore::DynamoDB::Locking
19
20
  end
20
21
  end
21
22
 
22
- # Packs session data.
23
- def pack_data(data)
24
- [Marshal.dump(data)].pack("m*")
25
- end
26
-
27
- # Gets session data.
23
+ # Retrieves session data based on id
28
24
  def get_session_data(env, sid)
29
25
  raise NotImplementedError
30
26
  end
@@ -36,19 +32,17 @@ module Aws::SessionStore::DynamoDB::Locking
36
32
  end
37
33
  end
38
34
 
35
+ private
36
+
39
37
  # Each database operation is placed in this rescue wrapper.
40
38
  # This wrapper will call the method, rescue any exceptions and then pass
41
39
  # exceptions to the configured error handler.
42
- def handle_error(env = nil, &block)
43
- begin
44
- yield
45
- rescue Aws::DynamoDB::Errors::ServiceError => e
46
- @config.error_handler.handle_error(e, env)
47
- end
40
+ def handle_error(env = nil)
41
+ yield
42
+ rescue Aws::DynamoDB::Errors::ServiceError => e
43
+ @config.error_handler.handle_error(e, env)
48
44
  end
49
45
 
50
- private
51
-
52
46
  # @return [Hash] Options for deleting session.
53
47
  def delete_opts(sid)
54
48
  table_opts(sid)
@@ -57,11 +51,10 @@ module Aws::SessionStore::DynamoDB::Locking
57
51
  # @return [Hash] Options for updating item in Session table.
58
52
  def update_opts(env, sid, session, options = {})
59
53
  if env['dynamo_db.new_session']
60
- updt_options = save_new_opts(env, sid, session)
54
+ save_new_opts(env, sid, session)
61
55
  else
62
- updt_options = save_exists_opts(env, sid, session, options)
56
+ save_exists_opts(env, sid, session, options)
63
57
  end
64
- updt_options
65
58
  end
66
59
 
67
60
  # @return [Hash] Options for saving a new session in database.
@@ -78,16 +71,21 @@ module Aws::SessionStore::DynamoDB::Locking
78
71
  merge_all(table_opts(sid), attribute_opts)
79
72
  end
80
73
 
74
+ # Marshal the data.
75
+ def pack_data(data)
76
+ [Marshal.dump(data)].pack('m*')
77
+ end
78
+
81
79
  # Unmarshal the data.
82
80
  def unpack_data(packed_data)
83
- Marshal.load(packed_data.unpack("m*").first)
81
+ Marshal.load(packed_data.unpack1('m*'))
84
82
  end
85
83
 
86
84
  # Table options for client.
87
85
  def table_opts(sid)
88
86
  {
89
- :table_name => @config.table_name,
90
- :key => { @config.table_key => sid }
87
+ table_name: @config.table_name,
88
+ key: { @config.table_key => sid }
91
89
  }
92
90
  end
93
91
 
@@ -102,12 +100,12 @@ module Aws::SessionStore::DynamoDB::Locking
102
100
 
103
101
  # Update client with current time attribute.
104
102
  def updated_at
105
- { :value => "#{(Time.now).to_f}", :action => "PUT" }
103
+ { value: Time.now.to_f.to_s, action: 'PUT' }
106
104
  end
107
105
 
108
106
  # Attribute for creation of session.
109
107
  def created_attr
110
- { "created_at" => updated_at }
108
+ { 'created_at' => updated_at }
111
109
  end
112
110
 
113
111
  # Update client with current time + max_stale.
@@ -124,35 +122,36 @@ module Aws::SessionStore::DynamoDB::Locking
124
122
  # Attribute for updating session.
125
123
  def updated_attr
126
124
  {
127
- "updated_at" => updated_at
125
+ 'updated_at' => updated_at
128
126
  }
129
127
  end
130
128
 
131
129
  def data_attr(session)
132
- { "data" => {:value => session, :action => "PUT"} }
130
+ { 'data' => { value: session, action: 'PUT' } }
133
131
  end
134
132
 
135
133
  # Determine if data has been manipulated
136
134
  def data_unchanged?(env, session)
137
135
  return false unless env['rack.initial_data']
136
+
138
137
  env['rack.initial_data'] == session
139
138
  end
140
139
 
141
140
  # Expected attributes
142
141
  def expected_attributes(sid)
143
- { :expected => { @config.table_key => {:value => sid, :exists => true} } }
142
+ { expected: { @config.table_key => { value: sid, exists: true } } }
144
143
  end
145
144
 
146
145
  # Attributes to be retrieved via client
147
146
  def attr_opts
148
- {:attributes_to_get => ["data"],
149
- :consistent_read => @config.consistent_read}
147
+ { attributes_to_get: ['data'],
148
+ consistent_read: @config.consistent_read }
150
149
  end
151
150
 
152
151
  # @return [Hash] merged hash of all hashes passed in.
153
152
  def merge_all(*hashes)
154
153
  new_hash = {}
155
- hashes.each{|hash| new_hash.merge!(hash)}
154
+ hashes.each { |hash| new_hash.merge!(hash) }
156
155
  new_hash
157
156
  end
158
157
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Aws::SessionStore::DynamoDB::Locking
2
4
  # This class gets and sets sessions
3
5
  # without a locking strategy.
@@ -18,9 +20,8 @@ module Aws::SessionStore::DynamoDB::Locking
18
20
 
19
21
  # @return [String] Session data.
20
22
  def extract_data(env, result = nil)
21
- env['rack.initial_data'] = result[:item]["data"] if result[:item]
22
- unpack_data(result[:item]["data"]) if result[:item]
23
+ env['rack.initial_data'] = result[:item]['data'] if result[:item]
24
+ unpack_data(result[:item]['data']) if result[:item]
23
25
  end
24
-
25
26
  end
26
27
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Aws::SessionStore::DynamoDB::Locking
2
4
  # This class implements a pessimistic locking strategy for the
3
5
  # DynamoDB session handler. Sessions obtain an exclusive lock
@@ -19,6 +21,7 @@ module Aws::SessionStore::DynamoDB::Locking
19
21
  private
20
22
 
21
23
  # Get session with implemented locking strategy.
24
+ # rubocop:disable Metrics/MethodLength
22
25
  def get_session_with_lock(env, sid)
23
26
  expires_at = nil
24
27
  result = nil
@@ -30,19 +33,21 @@ module Aws::SessionStore::DynamoDB::Locking
30
33
  rescue Aws::DynamoDB::Errors::ConditionalCheckFailedException
31
34
  expires_at ||= get_expire_date(sid)
32
35
  next if expires_at.nil?
36
+
33
37
  result = bust_lock(sid, expires_at)
34
38
  wait_to_retry(result)
35
39
  end
36
40
  end
37
41
  get_data(env, result)
38
42
  end
43
+ # rubocop:enable Metrics/MethodLength
39
44
 
40
45
  # Determine if session has waited too long to obtain lock.
41
46
  #
42
47
  # @raise [Error] When time for attempting to get lock has
43
48
  # been exceeded.
44
49
  def exceeded_wait_time?(max_attempt_date)
45
- lock_error = Aws::SessionStore::DynamoDB::LockWaitTimeoutError
50
+ lock_error = Aws::SessionStore::DynamoDB::Errors::LockWaitTimeoutError
46
51
  raise lock_error if Time.now.to_f > max_attempt_date
47
52
  end
48
53
 
@@ -54,22 +59,22 @@ module Aws::SessionStore::DynamoDB::Locking
54
59
  # @return [Time] Time stamp for which the session was locked.
55
60
  def lock_time(sid)
56
61
  result = @config.dynamo_db_client.get_item(get_lock_time_opts(sid))
57
- (result[:item]["locked_at"]).to_f if result[:item]["locked_at"]
62
+ (result[:item]['locked_at']).to_f if result[:item]['locked_at']
58
63
  end
59
64
 
60
65
  # @return [String] Session data.
61
66
  def get_data(env, result)
62
- lock_time = result[:attributes]["locked_at"]
63
- env["locked_at"] = (lock_time).to_f
64
- env['rack.initial_data'] = result[:item]["data"] if result.members.include? :item
65
- unpack_data(result[:attributes]["data"])
67
+ lock_time = result[:attributes]['locked_at']
68
+ env['locked_at'] = lock_time.to_f
69
+ env['rack.initial_data'] = result[:item]['data'] if result.members.include? :item
70
+ unpack_data(result[:attributes]['data'])
66
71
  end
67
72
 
68
73
  # Attempt to bust the lock if the expiration date has expired.
69
74
  def bust_lock(sid, expires_at)
70
- if expires_at < Time.now.to_f
71
- @config.dynamo_db_client.update_item(obtain_lock_opts(sid))
72
- end
75
+ return unless expires_at < Time.now.to_f
76
+
77
+ @config.dynamo_db_client.update_item(obtain_lock_opts(sid))
73
78
  end
74
79
 
75
80
  # @return [Hash] Options hash for obtaining the lock.
@@ -96,20 +101,20 @@ module Aws::SessionStore::DynamoDB::Locking
96
101
  # Lock attribute - time stamp of when session was locked.
97
102
  def lock_attr
98
103
  {
99
- :attribute_updates => {"locked_at" => updated_at},
100
- :return_values => "ALL_NEW"
104
+ attribute_updates: { 'locked_at' => updated_at },
105
+ return_values: 'ALL_NEW'
101
106
  }
102
107
  end
103
108
 
104
109
  # Time in which session was updated.
105
110
  def updated_at
106
- { :value => "#{(Time.now).to_f}", :action => "PUT" }
111
+ { value: Time.now.to_f.to_s, action: 'PUT' }
107
112
  end
108
113
 
109
114
  # Attributes for locking.
110
115
  def add_lock_attrs(env)
111
116
  {
112
- :add_attrs => add_attr, :expect_attr => expect_lock_time(env)
117
+ add_attrs: add_attr, expect_attr: expect_lock_time(env)
113
118
  }
114
119
  end
115
120
 
@@ -120,25 +125,32 @@ module Aws::SessionStore::DynamoDB::Locking
120
125
 
121
126
  # Lock expectation.
122
127
  def lock_expect
123
- { :expected => { "locked_at" => { :exists => false } } }
128
+ { expected: { 'locked_at' => { exists: false } } }
124
129
  end
125
130
 
126
131
  # Option to delete lock.
127
132
  def add_attr
128
- { "locked_at" => {:action => "DELETE"} }
133
+ { 'locked_at' => { action: 'DELETE' } }
129
134
  end
130
135
 
131
136
  # Expectation of when lock was set.
132
137
  def expect_lock_time(env)
133
- { :expected => {"locked_at" => {
134
- :value => "#{env["locked_at"]}", :exists => true}} }
138
+ {
139
+ expected: {
140
+ 'locked_at' => {
141
+ value: (env['locked_at']).to_s,
142
+ exists: true
143
+ }
144
+ }
145
+ }
135
146
  end
136
147
 
137
148
  # Attributes to be retrieved via client
138
149
  def lock_opts
139
- {:attributes_to_get => ["locked_at"],
140
- :consistent_read => @config.consistent_read}
150
+ {
151
+ attributes_to_get: ['locked_at'],
152
+ consistent_read: @config.consistent_read
153
+ }
141
154
  end
142
-
143
155
  end
144
156
  end