aws-sessionstore-dynamodb 2.1.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +22 -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 +25 -47
  17. data/.github/PULL_REQUEST_TEMPLATE.md +0 -6
  18. data/.github/workflows/ci.yml +0 -32
  19. data/.gitignore +0 -6
  20. data/.gitmodules +0 -3
  21. data/.travis.yml +0 -24
  22. data/.yardopts +0 -4
  23. data/CODE_OF_CONDUCT.md +0 -4
  24. data/CONTRIBUTING.md +0 -61
  25. data/Gemfile +0 -20
  26. data/LICENSE +0 -12
  27. data/README.md +0 -125
  28. data/Rakefile +0 -35
  29. data/aws-sessionstore-dynamodb.gemspec +0 -21
  30. data/doc-src/templates/default/layout/html/footer.erb +0 -6
  31. data/doc-src/templates/default/layout/html/layout.erb +0 -31
  32. data/lib/aws/session_store/dynamo_db/invalid_id_error.rb +0 -7
  33. data/lib/aws/session_store/dynamo_db/lock_wait_timeout_error.rb +0 -7
  34. data/lib/aws/session_store/dynamo_db/missing_secret_key_error.rb +0 -7
  35. data/lib/aws/session_store/dynamo_db/version.rb +0 -7
  36. data/spec/aws/session_store/dynamo_db/app_config.yml +0 -16
  37. data/spec/aws/session_store/dynamo_db/configuration_spec.rb +0 -81
  38. data/spec/aws/session_store/dynamo_db/error/default_error_handler_spec.rb +0 -64
  39. data/spec/aws/session_store/dynamo_db/garbage_collection_spec.rb +0 -158
  40. data/spec/aws/session_store/dynamo_db/locking/threaded_sessions_spec.rb +0 -96
  41. data/spec/aws/session_store/dynamo_db/rack_middleware_database_spec.rb +0 -130
  42. data/spec/aws/session_store/dynamo_db/rack_middleware_spec.rb +0 -148
  43. data/spec/aws/session_store/dynamo_db/table_spec.rb +0 -48
  44. data/spec/spec_helper.rb +0 -70
@@ -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