Class: Marloss::Store

Inherits:
Object
  • Object
show all
Defined in:
lib/marloss/store.rb

Overview

rubocop:disable Metrics/ClassLength

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(table, hash_key, **options) ⇒ Store

Returns a new instance of Store.



7
8
9
10
11
12
13
14
15
# File 'lib/marloss/store.rb', line 7

def initialize(table, hash_key, **options)
  client_options = options.fetch(:client_options, {})
  @client = Aws::DynamoDB::Client.new(client_options)
  @table = table
  @hash_key = hash_key
  @expires_key = options.fetch(:expires_key, "Expires")
  @ttl = options.fetch(:ttl, 30)
  @process_id = options[:custom_process_id] || host_process_id
end

Instance Attribute Details

#clientObject (readonly)

Returns the value of attribute client.



5
6
7
# File 'lib/marloss/store.rb', line 5

def client
  @client
end

#expires_keyObject (readonly)

Returns the value of attribute expires_key.



5
6
7
# File 'lib/marloss/store.rb', line 5

def expires_key
  @expires_key
end

#hash_keyObject (readonly)

Returns the value of attribute hash_key.



5
6
7
# File 'lib/marloss/store.rb', line 5

def hash_key
  @hash_key
end

#process_idObject (readonly)

Returns the value of attribute process_id.



5
6
7
# File 'lib/marloss/store.rb', line 5

def process_id
  @process_id
end

#tableObject (readonly)

Returns the value of attribute table.



5
6
7
# File 'lib/marloss/store.rb', line 5

def table
  @table
end

#ttlObject (readonly)

Returns the value of attribute ttl.



5
6
7
# File 'lib/marloss/store.rb', line 5

def ttl
  @ttl
end

Instance Method Details

#create_lock(name) ⇒ Object

rubocop:disable Metrics/MethodLength, Metrics/AbcSize



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/marloss/store.rb', line 89

def create_lock(name) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
  client.put_item(
    table_name: table,
    item: {
      hash_key => name,
      "ProcessID" => process_id,
      expires_key => (Time.now + ttl).to_i
    },
    expression_attribute_names: {
      "#E" => expires_key,
      "#P" => "ProcessID"
    },
    expression_attribute_values: {
      ":now" => Time.now.to_i,
      ":process_id" => process_id
    },
    condition_expression: "attribute_not_exists(#{hash_key}) OR #E < :now OR #P = :process_id"
  )

  Marloss.logger.info("Lock for #{name} created successfully, will expire in #{ttl} seconds")
rescue Aws::DynamoDB::Errors::ConditionalCheckFailedException => e
  Marloss.logger.error("Failed to create lock for #{name}")

  raise(LockNotObtainedError, e.message)
end

#create_tableObject



17
18
19
20
21
# File 'lib/marloss/store.rb', line 17

def create_table
  create_ddb_table
  wait_until_ddb_table_exists
  set_ddb_table_ttl
end

#delete_lock(name) ⇒ Object



139
140
141
142
143
# File 'lib/marloss/store.rb', line 139

def delete_lock(name)
  client.delete_item(key: { hash_key => name }, table_name: table)

  Marloss.logger.info("Lock for #{name} deleted successfully")
end

#delete_tableObject



83
84
85
86
87
# File 'lib/marloss/store.rb', line 83

def delete_table
  client.delete_table(table_name: table)

  Marloss.logger.info("DynamoDB table deleted successfully")
end

#refresh_lock(name) ⇒ Object

rubocop:disable Metrics/MethodLength, Metrics/AbcSize



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/marloss/store.rb', line 115

def refresh_lock(name) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
  client.update_item(
    table_name: table,
    key: { hash_key => name },
    expression_attribute_names: {
      "#E" => expires_key,
      "#P" => "ProcessID"
    },
    expression_attribute_values: {
      ":expires" => (Time.now + ttl).to_i,
      ":now" => Time.now.to_i,
      ":process_id" => process_id
    },
    update_expression: "SET #E = :expires",
    condition_expression: "attribute_exists(#{hash_key}) AND (#E < :now OR #P = :process_id)"
  )

  Marloss.logger.info("Lock for #{name} refreshed successfully, will expire in #{ttl} seconds")
rescue Aws::DynamoDB::Errors::ConditionalCheckFailedException => e
  Marloss.logger.error("Failed to refresh lock for #{name}")

  raise(LockNotRefreshedError, e.message)
end