Module: RedisQueuedLocks::Resource Private

Defined in:
lib/redis_queued_locks/resource.rb

Overview

This module is part of a private API. You should avoid using this module if possible, as it may be removed or be changed in the future.

Since:

  • 1.0.0

Constant Summary collapse

KEY_PATTERN =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Returns:

  • (String)

Since:

  • 1.0.0

'rql:lock*'
LOCK_PATTERN =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Returns:

  • (String)

Since:

  • 1.0.0

'rql:lock:*'
LOCK_QUEUE_PATTERN =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Returns:

  • (String)

Since:

  • 1.0.0

'rql:lock_queue:*'
READ_LOCK_QUEUE_PATTERN =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Returns:

  • (String)

Since:

  • ?.?.?

'rql:lock_queue:*:read'
WRITE_LOCK_QUEUE_PATTERN =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Returns:

  • (String)

Since:

  • ?.?.?

'rql:lock_queue:*:write'
SWARM_KEY =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Returns:

  • (String)

Since:

  • 1.9.0

'rql:swarm:hsts'
REDIS_TIMESHIFT_ERROR =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Returns Redis time error (in milliseconds).

Returns:

  • (Integer) —

    Redis time error (in milliseconds).

Since:

  • 1.3.0

2

Class Method Summary collapse

Class Method Details

.acquirer_dead_score(queue_ttl) ⇒ Float

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns Redis's score barrier for acquirers that should be removed from queue.

Parameters:

  • queue_ttl (Numeric) —

    In seconds

Returns:

  • (Float) —

    Redis's score barrier for acquirers that should be removed from queue.

Since:

  • 1.0.0



139
140
141
# File 'lib/redis_queued_locks/resource.rb', line 139

def acquirer_dead_score(queue_ttl)
  Time.now.to_f - queue_ttl
end

.acquirer_identifier(process_id, thread_id, fiber_id, ractor_id, identity) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parameters:

  • process_id (Integer, String)
  • thread_id (Integer, String)
  • fiber_id (Integer, String)
  • ractor_id (Integer, String)
  • identity (String)

Returns:

  • (String)

Since:

  • 1.0.0



70
71
72
# File 'lib/redis_queued_locks/resource.rb', line 70

def acquirer_identifier(process_id, thread_id, fiber_id, ractor_id, identity)
  "rql:acq:#{process_id}/#{thread_id}/#{fiber_id}/#{ractor_id}/#{identity}"
end

.calc_initial_acquirer_position ⇒ Float

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns Redis's score that is calculated from the time (epoch) as a float.

Returns:

  • (Float) —

    Redis's score that is calculated from the time (epoch) as a float.

Since:

  • 1.0.0



130
131
132
# File 'lib/redis_queued_locks/resource.rb', line 130

def calc_initial_acquirer_position
  Time.now.to_f
end

.calc_uniq_identity ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns 16-byte unique identifier. It is used for uniquely identify current process between different nodes/pods of your application during the lock obtaining and self-identifying in the lock queue.

Returns:

  • (String)

Since:

  • 1.0.0



57
58
59
# File 'lib/redis_queued_locks/resource.rb', line 57

def calc_uniq_identity
  SecureRandom.hex(8)
end

.calc_zombie_score(zombie_ttl) ⇒ Float

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parameters:

  • zombie_ttl (Float) —

    In seconds with milliseconds.

Returns:

  • (Float)

Since:

  • 1.9.0



148
149
150
# File 'lib/redis_queued_locks/resource.rb', line 148

def calc_zombie_score(zombie_ttl)
  Time.now.to_f - zombie_ttl
end

.dead_score_reached?(acquirer_position, queue_ttl) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns Is the lock request time limit has reached or not.

Parameters:

  • acquirer_position (Float) —

    A time (epoch, seconds.milliseconds) that represents the acquirer position in lock request queue.

  • queue_ttl (Integer) —

    In second.

Returns:

  • (Boolean) —

    Is the lock request time limit has reached or not.

Since:

  • 1.0.0



162
163
164
# File 'lib/redis_queued_locks/resource.rb', line 162

def dead_score_reached?(acquirer_position, queue_ttl)
  (acquirer_position + queue_ttl) < Time.now.to_f
end

.get_fiber_id ⇒ Integer

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Integer)

Since:

  • 1.0.0



188
189
190
# File 'lib/redis_queued_locks/resource.rb', line 188

def get_fiber_id
  ::Fiber.current.object_id
end

.get_process_id ⇒ Integer

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Integer)

Since:

  • 1.0.0



204
205
206
# File 'lib/redis_queued_locks/resource.rb', line 204

def get_process_id
  ::Process.pid
end

.get_ractor_id ⇒ Integer

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Integer)

Since:

  • 1.0.0



196
197
198
# File 'lib/redis_queued_locks/resource.rb', line 196

def get_ractor_id
  ::Ractor.current.object_id
end

.get_thread_id ⇒ Integer

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Integer)

Since:

  • 1.0.0



180
181
182
# File 'lib/redis_queued_locks/resource.rb', line 180

def get_thread_id
  ::Thread.current.object_id
end

.host_identifier(process_id, thread_id, ractor_id, identity) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parameters:

  • process_id (Integer, String)
  • thread_id (Integer, String)
  • ractor_id (Integer, String)
  • identity (String)

Returns:

  • (String)

Since:

  • 1.9.0



82
83
84
85
86
87
88
# File 'lib/redis_queued_locks/resource.rb', line 82

def host_identifier(process_id, thread_id, ractor_id, identity)
  # NOTE:
  #   - fiber's object_id is not used cuz we can't analyze fiber objects via ObjectSpace
  #     after the any new Ractor object is created in the current process
  #     (ObjectSpace no longer sees objects of Thread and Fiber classes after that);
  "rql:hst:#{process_id}/#{thread_id}/#{ractor_id}/#{identity}"
end

.lock_key_from_queue(lock_queue) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parameters:

  • lock_queue (String)

Returns:

  • (String)

Since:

  • 1.0.0



171
172
173
174
# File 'lib/redis_queued_locks/resource.rb', line 171

def lock_key_from_queue(lock_queue)
  # NOTE: 15 is a start position of the lock name
  "rql:lock:#{lock_queue[15..]}"
end

.possible_host_identifiers(identity) ⇒ Array<String>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Array<String>)

Since:

  • 1.9.0



212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'lib/redis_queued_locks/resource.rb', line 212

def possible_host_identifiers(identity)
  # NOTE №1: we can not use ObjectSpace.each_object for Thread and Fiber cuz after the any
  #   ractor creation the ObjectSpace stops seeing ::Thread and ::Fiber objects: each_object
  #   for each of them returns `0`;
  # NOTE №2: we have no any approach to count Fiber objects in the current process without
  #   object space API (or super memory-expensive) so host identification works without fibers;
  # NOTE №3: we still can extract thread objects via Thread.list API;

  # @type var current_process_id: Integer
  current_process_id = get_process_id
  # @type var current_threads: Array[Thread]
  current_threads = ::Thread.list
  # @type var current_ractor_id: Integer
  current_ractor_id = get_ractor_id

  # NOTE: steep can't resolve a type of dynamic `[]` literal mutated via inline tap;
  # steep:ignore:start
  [].tap do |acquirers|
    # @type var acquirers: Array[String]
    current_threads.each do |thread|
      acquirers << host_identifier(
        current_process_id,
        thread.object_id,
        current_ractor_id,
        identity
      )
    end
  end
  # steep:ignore:end
end

.prepare_lock_key(lock_name) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parameters:

  • lock_name (String)

Returns:

  • (String)

Since:

  • 1.0.0



95
96
97
# File 'lib/redis_queued_locks/resource.rb', line 95

def prepare_lock_key(lock_name)
  "rql:lock:#{lock_name}"
end

.prepare_lock_queue(lock_name) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parameters:

  • lock_name (String)

Returns:

  • (String)

Since:

  • 1.0.0



104
105
106
# File 'lib/redis_queued_locks/resource.rb', line 104

def prepare_lock_queue(lock_name)
  "rql:lock_queue:#{lock_name}"
end

.prepare_read_lock_queue(lock_name) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parameters:

  • lock_name (String)

Returns:

  • (String)

Since:

  • 1.0.0



113
114
115
# File 'lib/redis_queued_locks/resource.rb', line 113

def prepare_read_lock_queue(lock_name)
  "rql:lock_queue:#{lock_name}:read"
end

.prepare_write_lock_queue(lock_name) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Parameters:

  • lock_name (String)

Returns:

  • (String)

Since:

  • 1.0.0



122
123
124
# File 'lib/redis_queued_locks/resource.rb', line 122

def prepare_write_lock_queue(lock_name)
  "rql:lock_queue:#{lock_name}:write"
end