redis_queued_locks 1.13.0 → 1.15.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.
- checksums.yaml +4 -4
 - data/.rubocop.yml +0 -1
 - data/.ruby-version +1 -1
 - data/CHANGELOG.md +21 -4
 - data/README.md +368 -107
 - data/Rakefile +1 -1
 - data/Steepfile +0 -1
 - data/github_ci/ruby3.3.gemfile.lock +23 -23
 - data/lib/redis_queued_locks/acquirer/acquire_lock.rb +7 -7
 - data/lib/redis_queued_locks/acquirer/release_all_locks.rb +3 -3
 - data/lib/redis_queued_locks/acquirer/release_lock.rb +3 -3
 - data/lib/redis_queued_locks/acquirer/release_locks_of.rb +221 -0
 - data/lib/redis_queued_locks/acquirer.rb +1 -0
 - data/lib/redis_queued_locks/client.rb +155 -2
 - data/lib/redis_queued_locks/config/dsl.rb +9 -9
 - data/lib/redis_queued_locks/config.rb +15 -10
 - data/lib/redis_queued_locks/errors.rb +3 -3
 - data/lib/redis_queued_locks/swarm.rb +1 -1
 - data/lib/redis_queued_locks/utilities.rb +9 -0
 - data/lib/redis_queued_locks/version.rb +2 -2
 - data/lib/redis_queued_locks.rb +0 -1
 - data/rbs_collection.lock.yaml +1 -13
 - data/rbs_collection.yaml +2 -1
 - data/redis_queued_locks.gemspec +1 -1
 - data/sig/manifest.yml +0 -1
 - data/sig/redis_queued_locks/acquirer/acquire_lock.rbs +1 -0
 - data/sig/redis_queued_locks/acquirer/release_locks_of.rbs +46 -0
 - data/sig/redis_queued_locks/client.rbs +40 -0
 - data/sig/redis_queued_locks/utilities.rbs +1 -0
 - metadata +5 -3
 
    
        data/README.md
    CHANGED
    
    | 
         @@ -1,10 +1,10 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            # RedisQueuedLocks ·  
     | 
| 
      
 1 
     | 
    
         
            +
            # RedisQueuedLocks · 
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
     | 
    
         
            -
            [](https://github.com/0exp/redis_queued_locks/actions) [](https://github.com/0exp/redis_queued_locks/actions) [](https://github.com/0exp/redis_queued_locks/actions) [](https://github.com/0exp/redis_queued_locks/actions) [](https://github.com/0exp/redis_queued_locks/actions)
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
     | 
    
         
            -
            <a href="https://redis.io/docs/ 
     | 
| 
      
 5 
     | 
    
         
            +
            <a href="https://redis.io/docs/latest/develop/clients/patterns/distributed-locks/">Distributed locks</a> with "prioritized lock acquisition queue" capabilities based on the Redis Database.
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
       7 
     | 
    
         
            -
            Each lock request is put into the request queue (each lock is hosted by  
     | 
| 
      
 7 
     | 
    
         
            +
            Each lock request is put into the request queue (each lock is hosted by its own queue separately from other queues) and processed in order of their priority (FIFO). Each lock request lives some period of time (RTTL) (with requeue capabilities) which guarantees the request queue will never be stacked.
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
       9 
9 
     | 
    
         
             
            In addition to the classic `queued` (FIFO) strategy RQL supports `random` (RANDOM) lock obtaining strategy when any acquirer from the lock queue can obtain the lock regardless the position in the queue.
         
     | 
| 
       10 
10 
     | 
    
         | 
| 
         @@ -27,8 +27,10 @@ Provides flexible invocation flow, parametrized limits (lock request ttl, lock t 
     | 
|
| 
       27 
27 
     | 
    
         
             
              - [queue_info](#queue_info)
         
     | 
| 
       28 
28 
     | 
    
         
             
              - [locked?](#locked)
         
     | 
| 
       29 
29 
     | 
    
         
             
              - [queued?](#queued)
         
     | 
| 
       30 
     | 
    
         
            -
              - [unlock](#unlock---release-a-lock)
         
     | 
| 
       31 
     | 
    
         
            -
              - [clear_locks](#clear_locks---release-all-locks-and-lock-queues)
         
     | 
| 
      
 30 
     | 
    
         
            +
              - [unlock](#unlock---release-a-lock) (aka `release_lock`)
         
     | 
| 
      
 31 
     | 
    
         
            +
              - [clear_locks](#clear_locks---release-all-locks-and-lock-queues) (aka `release_locks`)
         
     | 
| 
      
 32 
     | 
    
         
            +
              - [clear_locks_of](#clear_locks_of) (aka `release_locks_of`)
         
     | 
| 
      
 33 
     | 
    
         
            +
              - [clear_current_locks](#clear_current_locks) (aka `release_current_locks`)
         
     | 
| 
       32 
34 
     | 
    
         
             
              - [extend_lock_ttl](#extend_lock_ttl)
         
     | 
| 
       33 
35 
     | 
    
         
             
              - [locks](#locks---get-list-of-obtained-locks)
         
     | 
| 
       34 
36 
     | 
    
         
             
              - [queues](#queues---get-list-of-lock-request-queues)
         
     | 
| 
         @@ -62,7 +64,16 @@ Provides flexible invocation flow, parametrized limits (lock request ttl, lock t 
     | 
|
| 
       62 
64 
     | 
    
         
             
            - [Instrumentation](#instrumentation)
         
     | 
| 
       63 
65 
     | 
    
         
             
              - [Instrumentation Configuration](#instrumentation-configuration)
         
     | 
| 
       64 
66 
     | 
    
         
             
              - [Instrumentation Events](#instrumentation-events)
         
     | 
| 
      
 67 
     | 
    
         
            +
                - ["redis_queued_locks.lock_obtained"](#redis_queued_lockslock_hold_and_release)
         
     | 
| 
      
 68 
     | 
    
         
            +
                - ["redis_queued_locks.extendable_reentrant_lock_obtained"](#redis_queued_locksextendable_reentrant_lock_obtained)
         
     | 
| 
      
 69 
     | 
    
         
            +
                - ["redis_queued_locks.reentrant_lock_obtained"](#redis_queued_locksreentrant_lock_obtained)
         
     | 
| 
      
 70 
     | 
    
         
            +
                - ["redis_queued_locks.lock_hold_and_release"](#redis_queued_lockslock_hold_and_release)
         
     | 
| 
      
 71 
     | 
    
         
            +
                - ["redis_queued_locks.reentrant_lock_hold_completes"](#redis_queued_locksreentrant_lock_hold_completes)
         
     | 
| 
      
 72 
     | 
    
         
            +
                - ["redis_queued_locks.explicit_lock_release"](#redis_queued_locksexplicit_lock_release)
         
     | 
| 
      
 73 
     | 
    
         
            +
                - ["redis_queued_locks.explicit_all_locks_release"](#redis_queued_locksexplicit_all_locks_release)
         
     | 
| 
      
 74 
     | 
    
         
            +
                - ["redis_queued_locks.release_locks_of"](#redis_queued_locksrelease_locks_of)
         
     | 
| 
       65 
75 
     | 
    
         
             
            - [Roadmap](#roadmap)
         
     | 
| 
      
 76 
     | 
    
         
            +
            - [Build and Develop](#build-and-develop)
         
     | 
| 
       66 
77 
     | 
    
         
             
            - [Contributing](#contributing)
         
     | 
| 
       67 
78 
     | 
    
         
             
            - [License](#license)
         
     | 
| 
       68 
79 
     | 
    
         
             
            - [Authors](#authors)
         
     | 
| 
         @@ -93,7 +104,7 @@ Provides flexible invocation flow, parametrized limits (lock request ttl, lock t 
     | 
|
| 
       93 
104 
     | 
    
         | 
| 
       94 
105 
     | 
    
         
             
            <sup>\[[back to top](#table-of-contents)\]</sup>
         
     | 
| 
       95 
106 
     | 
    
         | 
| 
       96 
     | 
    
         
            -
            > Each lock request is put into the request queue (each lock is hosted by  
     | 
| 
      
 107 
     | 
    
         
            +
            > Each lock request is put into the request queue (each lock is hosted by its own queue separately from other queues) and processed in order of their priority (FIFO). Each lock request lives some period of time (RTTL) which guarantees that the request queue will never be stacked.
         
     | 
| 
       97 
108 
     | 
    
         | 
| 
       98 
109 
     | 
    
         
             
            > In addition to the classic "queued" (FIFO) strategy RQL supports "random" (RANDOM) lock obtaining strategy when any acquirer from the lock queue can obtain the lock regardless the position in the queue.
         
     | 
| 
       99 
110 
     | 
    
         | 
| 
         @@ -151,7 +162,7 @@ rq_lock_client.lock("some-lock") { puts "Hello, lock!" } 
     | 
|
| 
       151 
162 
     | 
    
         
             
            ```ruby
         
     | 
| 
       152 
163 
     | 
    
         
             
            redis_client = RedisClient.config.new_pool # NOTE: provide your own RedisClient instance
         
     | 
| 
       153 
164 
     | 
    
         | 
| 
       154 
     | 
    
         
            -
             
     | 
| 
      
 165 
     | 
    
         
            +
            client = RedisQueuedLocks::Client.new(redis_client) do |config|
         
     | 
| 
       155 
166 
     | 
    
         
             
              # (default: 3) (supports nil)
         
     | 
| 
       156 
167 
     | 
    
         
             
              # - nil means "infinite retries" and you are only limited by the "try_to_lock_timeout" config;
         
     | 
| 
       157 
168 
     | 
    
         
             
              config['retry_count'] = 3
         
     | 
| 
         @@ -223,7 +234,7 @@ clinet = RedisQueuedLocks::Client.new(redis_client) do |config| 
     | 
|
| 
       223 
234 
     | 
    
         
             
              #   - `:extendable_work_through` - continue working under the lock <with> lock's TTL extension;
         
     | 
| 
       224 
235 
     | 
    
         
             
              #   - `:wait_for_lock` - (default) - work in classic way (with timeouts, retry delays, retry limits, etc - in classic way :));
         
     | 
| 
       225 
236 
     | 
    
         
             
              #   - `:dead_locking` - fail with deadlock exception;
         
     | 
| 
       226 
     | 
    
         
            -
              # - See "Dead locks and Reentrant Locks" documentation section in  
     | 
| 
      
 237 
     | 
    
         
            +
              # - See "Dead locks and Reentrant Locks" documentation section in README.md for details;
         
     | 
| 
       227 
238 
     | 
    
         
             
              config['default_conflict_strategy'] = :wait_for_lock
         
     | 
| 
       228 
239 
     | 
    
         | 
| 
       229 
240 
     | 
    
         
             
              # (default: 100)
         
     | 
| 
         @@ -231,10 +242,21 @@ clinet = RedisQueuedLocks::Client.new(redis_client) do |config| 
     | 
|
| 
       231 
242 
     | 
    
         
             
              # - affects the performance of your Redis and Ruby Application (configure thoughtfully);
         
     | 
| 
       232 
243 
     | 
    
         
             
              config['lock_release_batch_size'] = 100
         
     | 
| 
       233 
244 
     | 
    
         | 
| 
      
 245 
     | 
    
         
            +
              # (default: 300)
         
     | 
| 
      
 246 
     | 
    
         
            +
              # - how many items will be released at a time in #clear_locks_of and in #clear_current_locks methods (uses SCAN for batch extraction and DEL for batch deletion);
         
     | 
| 
      
 247 
     | 
    
         
            +
              # - affects the ruby's memory (cuz this batch will be stored in Set object in first, and then will be splatted to the DEL redis method invocation) (configure thoughtfully);
         
     | 
| 
      
 248 
     | 
    
         
            +
              # - affects the performance of your Redis (configure thoughtfully);
         
     | 
| 
      
 249 
     | 
    
         
            +
              config['clear_locks_of__lock_scan_size'] = 300
         
     | 
| 
      
 250 
     | 
    
         
            +
             
     | 
| 
      
 251 
     | 
    
         
            +
              # (default: 300)
         
     | 
| 
      
 252 
     | 
    
         
            +
              # - how many queues will be SCAN'ned at a time in #clear_locks_of and in #clear_current_locks methods (uses SCAN);
         
     | 
| 
      
 253 
     | 
    
         
            +
              # - affects the performance of your Redis (configure thoughtfully);
         
     | 
| 
      
 254 
     | 
    
         
            +
              config['clear_locks_of__queue_scan_size'] = 300
         
     | 
| 
      
 255 
     | 
    
         
            +
             
     | 
| 
       234 
256 
     | 
    
         
             
              # (default: 500)
         
     | 
| 
       235 
257 
     | 
    
         
             
              # - how many items should be extracted from redis during the #locks, #queues, #keys
         
     | 
| 
       236 
258 
     | 
    
         
             
              #   #locks_info, and #queues_info operations (uses SCAN);
         
     | 
| 
       237 
     | 
    
         
            -
              # - affects the performance of your Redis and Ruby Application (configure thoughtfully; 
     | 
| 
      
 259 
     | 
    
         
            +
              # - affects the performance of your Redis and Ruby Application (configure thoughtfully);
         
     | 
| 
       238 
260 
     | 
    
         
             
              config['key_extraction_batch_size'] = 500
         
     | 
| 
       239 
261 
     | 
    
         | 
| 
       240 
262 
     | 
    
         
             
              # (default: 1 day)
         
     | 
| 
         @@ -555,8 +577,8 @@ def lock( 
     | 
|
| 
       555 
577 
     | 
    
         
             
              - `false` by default;
         
     | 
| 
       556 
578 
     | 
    
         
             
            - `block` - (optional) `[Block]`
         
     | 
| 
       557 
579 
     | 
    
         
             
              - A block of code that should be executed after the successfully acquired lock.
         
     | 
| 
       558 
     | 
    
         
            -
              - If block is **passed** the obtained lock will be released after the block execution or  
     | 
| 
       559 
     | 
    
         
            -
              - If block is **not passed** the obtained lock will be released after  
     | 
| 
      
 580 
     | 
    
         
            +
              - If block is **passed** the obtained lock will be released after the block execution or its ttl (what will happen first);
         
     | 
| 
      
 581 
     | 
    
         
            +
              - If block is **not passed** the obtained lock will be released after its ttl;
         
     | 
| 
       560 
582 
     | 
    
         
             
              - If you want the block to have a TTL too and this TTL to be the same as TTL of the lock
         
     | 
| 
       561 
583 
     | 
    
         
             
                use `timed: true` option (`rql.lock("my_lock", timed: true, ttl: 5_000) { ... }`)
         
     | 
| 
       562 
584 
     | 
    
         | 
| 
         @@ -700,7 +722,7 @@ rql.lock_info("my_lock") 
     | 
|
| 
       700 
722 
     | 
    
         | 
| 
       701 
723 
     | 
    
         
             
            - (`:queue_ttl`) setting a short limit of time to the lock request queue position (if a process fails to acquire
         
     | 
| 
       702 
724 
     | 
    
         
             
              the lock within this period of time (and before timeout/retry_count limits occurs of course) -
         
     | 
| 
       703 
     | 
    
         
            -
               
     | 
| 
      
 725 
     | 
    
         
            +
              its lock request will be moved to the end of queue):
         
     | 
| 
       704 
726 
     | 
    
         | 
| 
       705 
727 
     | 
    
         
             
            ```ruby
         
     | 
| 
       706 
728 
     | 
    
         
             
            rql.lock("my_lock", queue_ttl: 5, timeout: 10_000, retry_count: nil)
         
     | 
| 
         @@ -735,7 +757,7 @@ rql.lock("my_lock", queue_ttl: 5, timeout: 10_000, retry_count: nil) 
     | 
|
| 
       735 
757 
     | 
    
         
             
            ```
         
     | 
| 
       736 
758 
     | 
    
         | 
| 
       737 
759 
     | 
    
         
             
            - obtain a lock in `:random` way (with `:random` strategy): in `:random` strategy
         
     | 
| 
       738 
     | 
    
         
            -
              any acquirer from the  
     | 
| 
      
 760 
     | 
    
         
            +
              any acquirer from the lock queue can obtain the lock regardless of the position in the lock queue;
         
     | 
| 
       739 
761 
     | 
    
         | 
| 
       740 
762 
     | 
    
         
             
            ```ruby
         
     | 
| 
       741 
763 
     | 
    
         
             
            # Current Process (process#1)
         
     | 
| 
         @@ -1120,6 +1142,197 @@ rql.clear_locks 
     | 
|
| 
       1120 
1142 
     | 
    
         | 
| 
       1121 
1143 
     | 
    
         
             
            ---
         
     | 
| 
       1122 
1144 
     | 
    
         | 
| 
      
 1145 
     | 
    
         
            +
            #### #clear_locks_of
         
     | 
| 
      
 1146 
     | 
    
         
            +
             
     | 
| 
      
 1147 
     | 
    
         
            +
            <sup>\[[back to top](#usage)\]</sup>
         
     | 
| 
      
 1148 
     | 
    
         
            +
             
     | 
| 
      
 1149 
     | 
    
         
            +
            - release all locks of the passed acquirer/host and remove this acquirer/host from all queues (locks will be released first)
         
     | 
| 
      
 1150 
     | 
    
         
            +
            - this is a cleanup helper intended for operational and debugging scenarios (for example: your
         
     | 
| 
      
 1151 
     | 
    
         
            +
              current puma request thread is killed by Rack::Timeout and you need to cleanup all zombie RQL
         
     | 
| 
      
 1152 
     | 
    
         
            +
              locks and lock reuqests obtained during the request processing);
         
     | 
| 
      
 1153 
     | 
    
         
            +
            - acquirer/host dentifiers can be extracted via:
         
     | 
| 
      
 1154 
     | 
    
         
            +
              - `#current_host_id`
         
     | 
| 
      
 1155 
     | 
    
         
            +
              - `#current_acquirer_id`
         
     | 
| 
      
 1156 
     | 
    
         
            +
              - `#possible_host_ids`
         
     | 
| 
      
 1157 
     | 
    
         
            +
              - from lock data (extracted via `#lock_info`, `#locks_info`, `#queue_info`, `#queues_info`);
         
     | 
| 
      
 1158 
     | 
    
         
            +
            - produces `"redis_queued_locks.release_locks_of"` instrumentation event;
         
     | 
| 
      
 1159 
     | 
    
         
            +
            - accepts:
         
     | 
| 
      
 1160 
     | 
    
         
            +
              - `:host_id` - (required) `[String]`
         
     | 
| 
      
 1161 
     | 
    
         
            +
                - host indentifier whose locks we want to release and which we want to remove from all locks queues;
         
     | 
| 
      
 1162 
     | 
    
         
            +
              - `:acquirer_id` - (required) `[String]`
         
     | 
| 
      
 1163 
     | 
    
         
            +
                - acquirer indentifier whose locks we want to release and which we want to remove from all locks queues;
         
     | 
| 
      
 1164 
     | 
    
         
            +
              - `:lock_scan_size` - (optional) `[Integer]`
         
     | 
| 
      
 1165 
     | 
    
         
            +
                - how many items will be released at a time (uses `SCAN `for batch extraction and `DEL` for batch deletion);
         
     | 
| 
      
 1166 
     | 
    
         
            +
                - pre-configuerd value in `config['clear_locks_of__lock_scan_size']`;
         
     | 
| 
      
 1167 
     | 
    
         
            +
              - `:queue_scan_size` - (optional) `[Integer]`
         
     | 
| 
      
 1168 
     | 
    
         
            +
                - how many queues will be SCAN'ned at a time (uses `SCAN)`;
         
     | 
| 
      
 1169 
     | 
    
         
            +
                - pre-configuerd value in `config['clear_locks_of__queue_scan_size']`;
         
     | 
| 
      
 1170 
     | 
    
         
            +
              - `:logger` - (optional) `[::Logger,#debug]`
         
     | 
| 
      
 1171 
     | 
    
         
            +
                - custom logger object;
         
     | 
| 
      
 1172 
     | 
    
         
            +
                - pre-configured value in `config['logger']`;
         
     | 
| 
      
 1173 
     | 
    
         
            +
              - `:instrumenter` - (optional) `[#notify]`
         
     | 
| 
      
 1174 
     | 
    
         
            +
                - custom instrumenter object;
         
     | 
| 
      
 1175 
     | 
    
         
            +
                - pre-configured value in `config['isntrumenter']`;
         
     | 
| 
      
 1176 
     | 
    
         
            +
              - `:instrument` - (optional) `[NilClass,Any]`
         
     | 
| 
      
 1177 
     | 
    
         
            +
                - custom instrumentation data wich will be passed to the instrumenter's payload with `:instrument` key;
         
     | 
| 
      
 1178 
     | 
    
         
            +
              - `:log_sampling_enabled` - (optional) `[Boolean]`
         
     | 
| 
      
 1179 
     | 
    
         
            +
                - enables **log sampling**;
         
     | 
| 
      
 1180 
     | 
    
         
            +
                - pre-configured in `config['log_sampling_enabled']`;
         
     | 
| 
      
 1181 
     | 
    
         
            +
              - `:log_sampling_percent` - (optional) `[Integer]`
         
     | 
| 
      
 1182 
     | 
    
         
            +
                - **log sampling**:the percent of cases that should be logged;
         
     | 
| 
      
 1183 
     | 
    
         
            +
                - pre-configured in `config['log_sampling_percent']`;
         
     | 
| 
      
 1184 
     | 
    
         
            +
              - `:log_sampler` - (optional) `[#sampling_happened?,Module<RedisQueuedLocks::Logging::Sampler>]`
         
     | 
| 
      
 1185 
     | 
    
         
            +
                - **log sampling**: percent-based log sampler that decides should be RQL case logged or not;
         
     | 
| 
      
 1186 
     | 
    
         
            +
                - pre-configured in `config['log_sampler']`;
         
     | 
| 
      
 1187 
     | 
    
         
            +
              - `log_sample_this` - (optional) `[Boolean]`
         
     | 
| 
      
 1188 
     | 
    
         
            +
                - marks the method that everything should be logged despite the enabled log sampling;
         
     | 
| 
      
 1189 
     | 
    
         
            +
                - makes sense when log sampling is enabled;
         
     | 
| 
      
 1190 
     | 
    
         
            +
                - `false` by default;
         
     | 
| 
      
 1191 
     | 
    
         
            +
              - `:instr_sampling_enabled` - (optional) `[Boolean]`
         
     | 
| 
      
 1192 
     | 
    
         
            +
                - enables **instrumentaion sampling**;
         
     | 
| 
      
 1193 
     | 
    
         
            +
                - pre-configured in `config['instr_sampling_enabled']`;
         
     | 
| 
      
 1194 
     | 
    
         
            +
              - `instr_sampling_percent` - (optional) `[Integer]`
         
     | 
| 
      
 1195 
     | 
    
         
            +
                - the percent of cases that should be instrumented;
         
     | 
| 
      
 1196 
     | 
    
         
            +
                - pre-configured in `config['instr_sampling_percent']`;
         
     | 
| 
      
 1197 
     | 
    
         
            +
              - `instr_sampler` - (optional) `[#sampling_happened?,Module<RedisQueuedLocks::Instrument::Sampler>]`
         
     | 
| 
      
 1198 
     | 
    
         
            +
                - percent-based log sampler that decides should be RQL case instrumented or not;
         
     | 
| 
      
 1199 
     | 
    
         
            +
                - pre-configured in `config['instr_sampler']`;
         
     | 
| 
      
 1200 
     | 
    
         
            +
              - `instr_sample_this` - (optional) `[Boolean]`
         
     | 
| 
      
 1201 
     | 
    
         
            +
                - marks the method that everything should be instrumneted despite the enabled instrumentation sampling;
         
     | 
| 
      
 1202 
     | 
    
         
            +
                - makes sense when instrumentation sampling is enabled;
         
     | 
| 
      
 1203 
     | 
    
         
            +
                - `false` by default;
         
     | 
| 
      
 1204 
     | 
    
         
            +
            - returns:
         
     | 
| 
      
 1205 
     | 
    
         
            +
              - `[Hash<Symbol,Numeric>]` - Format: `{ ok: true, result: Hash<Symbol,Numeric> }`;
         
     | 
| 
      
 1206 
     | 
    
         
            +
              - result data:
         
     | 
| 
      
 1207 
     | 
    
         
            +
                - `:rel_time` - `Numeric` - time spent;
         
     | 
| 
      
 1208 
     | 
    
         
            +
                - `:rel_key_cnt` - `Integer` - the count of released locks;
         
     | 
| 
      
 1209 
     | 
    
         
            +
                - `:tch_queue_cnt` - `Integer` - the count of touched (modified) queues (the number of queues from which the acquirer/host was removed);
         
     | 
| 
      
 1210 
     | 
    
         
            +
             
     | 
| 
      
 1211 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 1212 
     | 
    
         
            +
            rql.clear_locks_of(
         
     | 
| 
      
 1213 
     | 
    
         
            +
              host_id: "rql:hst:41478/4320/4360/848818f09d8c3420",
         
     | 
| 
      
 1214 
     | 
    
         
            +
              acquirer_id: "rql:acq:41478/4320/4340/4360/848818f09d8c3420"
         
     | 
| 
      
 1215 
     | 
    
         
            +
            )
         
     | 
| 
      
 1216 
     | 
    
         
            +
            # -- or (alias) --
         
     | 
| 
      
 1217 
     | 
    
         
            +
            rql.release_locks_of(
         
     | 
| 
      
 1218 
     | 
    
         
            +
              host_id: "rql:hst:41478/4320/4360/848818f09d8c3420",
         
     | 
| 
      
 1219 
     | 
    
         
            +
              acquirer_id: "rql:acq:41478/4320/4340/4360/848818f09d8c3420"
         
     | 
| 
      
 1220 
     | 
    
         
            +
            )
         
     | 
| 
      
 1221 
     | 
    
         
            +
             
     | 
| 
      
 1222 
     | 
    
         
            +
            # -> result
         
     | 
| 
      
 1223 
     | 
    
         
            +
            {
         
     | 
| 
      
 1224 
     | 
    
         
            +
              ok: true,
         
     | 
| 
      
 1225 
     | 
    
         
            +
              result: {
         
     | 
| 
      
 1226 
     | 
    
         
            +
                rel_key_cnt: 123,
         
     | 
| 
      
 1227 
     | 
    
         
            +
                tch_queue_cnt: 2,
         
     | 
| 
      
 1228 
     | 
    
         
            +
                rel_time: 0.1
         
     | 
| 
      
 1229 
     | 
    
         
            +
              }
         
     | 
| 
      
 1230 
     | 
    
         
            +
            }
         
     | 
| 
      
 1231 
     | 
    
         
            +
            ```
         
     | 
| 
      
 1232 
     | 
    
         
            +
             
     | 
| 
      
 1233 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 1234 
     | 
    
         
            +
            # clear locks and queues of the current acquirer:
         
     | 
| 
      
 1235 
     | 
    
         
            +
            rql.clear_locks_of(
         
     | 
| 
      
 1236 
     | 
    
         
            +
              host_id: rql.current_host_id,
         
     | 
| 
      
 1237 
     | 
    
         
            +
              acquirer_id: rql.current_acquirer_id
         
     | 
| 
      
 1238 
     | 
    
         
            +
            )
         
     | 
| 
      
 1239 
     | 
    
         
            +
             
     | 
| 
      
 1240 
     | 
    
         
            +
            # equivalent:
         
     | 
| 
      
 1241 
     | 
    
         
            +
            rql.clear_current_locks
         
     | 
| 
      
 1242 
     | 
    
         
            +
             
     | 
| 
      
 1243 
     | 
    
         
            +
            # -> result
         
     | 
| 
      
 1244 
     | 
    
         
            +
            {
         
     | 
| 
      
 1245 
     | 
    
         
            +
              ok: true,
         
     | 
| 
      
 1246 
     | 
    
         
            +
              result: {
         
     | 
| 
      
 1247 
     | 
    
         
            +
                rel_key_cnt: 43,
         
     | 
| 
      
 1248 
     | 
    
         
            +
                tch_queue_cnt: 3,
         
     | 
| 
      
 1249 
     | 
    
         
            +
                rel_time: 0.2
         
     | 
| 
      
 1250 
     | 
    
         
            +
              }
         
     | 
| 
      
 1251 
     | 
    
         
            +
            }
         
     | 
| 
      
 1252 
     | 
    
         
            +
            ```
         
     | 
| 
      
 1253 
     | 
    
         
            +
             
     | 
| 
      
 1254 
     | 
    
         
            +
            ---
         
     | 
| 
      
 1255 
     | 
    
         
            +
             
     | 
| 
      
 1256 
     | 
    
         
            +
            #### #clear_current_locks
         
     | 
| 
      
 1257 
     | 
    
         
            +
             
     | 
| 
      
 1258 
     | 
    
         
            +
            <sup>\[[back to top](#usage)\]</sup>
         
     | 
| 
      
 1259 
     | 
    
         
            +
             
     | 
| 
      
 1260 
     | 
    
         
            +
            - release all locks of the current acquirer/host and remove the current acquirer/host from all queues (locks will be released first);
         
     | 
| 
      
 1261 
     | 
    
         
            +
            - this is a cleanup helper intended for operational and debugging scenarios (for example: your
         
     | 
| 
      
 1262 
     | 
    
         
            +
              current puma request thread is killed by Rack::Timeout and you need to cleanup all zombie RQL
         
     | 
| 
      
 1263 
     | 
    
         
            +
              locks and lock reuqests obtained during the request processing);
         
     | 
| 
      
 1264 
     | 
    
         
            +
            - representes an equivalent invocation:
         
     | 
| 
      
 1265 
     | 
    
         
            +
              ```ruby
         
     | 
| 
      
 1266 
     | 
    
         
            +
              rql.clear_locks_of(host_id: rql.current_host_id, acquirer_id: rql.current_acquirer_id)
         
     | 
| 
      
 1267 
     | 
    
         
            +
              ```
         
     | 
| 
      
 1268 
     | 
    
         
            +
            - produces `"redis_queued_locks.release_locks_of"` instrumentation event;
         
     | 
| 
      
 1269 
     | 
    
         
            +
              - `:lock_scan_size` - (optional) `[Integer]`
         
     | 
| 
      
 1270 
     | 
    
         
            +
                - how many items will be released at a time (uses `SCAN `for batch extraction and `DEL` for batch deletion);
         
     | 
| 
      
 1271 
     | 
    
         
            +
                - pre-configuerd value in `config['clear_locks_of__lock_scan_size']`;
         
     | 
| 
      
 1272 
     | 
    
         
            +
              - `:queue_scan_size` - (optional) `[Integer]`
         
     | 
| 
      
 1273 
     | 
    
         
            +
                - how many queues will be SCAN'ned at a time (uses `SCAN)`;
         
     | 
| 
      
 1274 
     | 
    
         
            +
                - pre-configuerd value in `config['clear_locks_of__queue_scan_size']`;
         
     | 
| 
      
 1275 
     | 
    
         
            +
              - `:logger` - (optional) `[::Logger,#debug]`
         
     | 
| 
      
 1276 
     | 
    
         
            +
                - custom logger object;
         
     | 
| 
      
 1277 
     | 
    
         
            +
                - pre-configured value in `config['logger']`;
         
     | 
| 
      
 1278 
     | 
    
         
            +
              - `:instrumenter` - (optional) `[#notify]`
         
     | 
| 
      
 1279 
     | 
    
         
            +
                - custom instrumenter object;
         
     | 
| 
      
 1280 
     | 
    
         
            +
                - pre-configured value in `config['isntrumenter']`;
         
     | 
| 
      
 1281 
     | 
    
         
            +
              - `:instrument` - (optional) `[NilClass,Any]`
         
     | 
| 
      
 1282 
     | 
    
         
            +
                - custom instrumentation data wich will be passed to the instrumenter's payload with `:instrument` key;
         
     | 
| 
      
 1283 
     | 
    
         
            +
              - `:log_sampling_enabled` - (optional) `[Boolean]`
         
     | 
| 
      
 1284 
     | 
    
         
            +
                - enables **log sampling**;
         
     | 
| 
      
 1285 
     | 
    
         
            +
                - pre-configured in `config['log_sampling_enabled']`;
         
     | 
| 
      
 1286 
     | 
    
         
            +
              - `:log_sampling_percent` - (optional) `[Integer]`
         
     | 
| 
      
 1287 
     | 
    
         
            +
                - **log sampling**:the percent of cases that should be logged;
         
     | 
| 
      
 1288 
     | 
    
         
            +
                - pre-configured in `config['log_sampling_percent']`;
         
     | 
| 
      
 1289 
     | 
    
         
            +
              - `:log_sampler` - (optional) `[#sampling_happened?,Module<RedisQueuedLocks::Logging::Sampler>]`
         
     | 
| 
      
 1290 
     | 
    
         
            +
                - **log sampling**: percent-based log sampler that decides should be RQL case logged or not;
         
     | 
| 
      
 1291 
     | 
    
         
            +
                - pre-configured in `config['log_sampler']`;
         
     | 
| 
      
 1292 
     | 
    
         
            +
              - `log_sample_this` - (optional) `[Boolean]`
         
     | 
| 
      
 1293 
     | 
    
         
            +
                - marks the method that everything should be logged despite the enabled log sampling;
         
     | 
| 
      
 1294 
     | 
    
         
            +
                - makes sense when log sampling is enabled;
         
     | 
| 
      
 1295 
     | 
    
         
            +
                - `false` by default;
         
     | 
| 
      
 1296 
     | 
    
         
            +
              - `:instr_sampling_enabled` - (optional) `[Boolean]`
         
     | 
| 
      
 1297 
     | 
    
         
            +
                - enables **instrumentaion sampling**;
         
     | 
| 
      
 1298 
     | 
    
         
            +
                - pre-configured in `config['instr_sampling_enabled']`;
         
     | 
| 
      
 1299 
     | 
    
         
            +
              - `instr_sampling_percent` - (optional) `[Integer]`
         
     | 
| 
      
 1300 
     | 
    
         
            +
                - the percent of cases that should be instrumented;
         
     | 
| 
      
 1301 
     | 
    
         
            +
                - pre-configured in `config['instr_sampling_percent']`;
         
     | 
| 
      
 1302 
     | 
    
         
            +
              - `instr_sampler` - (optional) `[#sampling_happened?,Module<RedisQueuedLocks::Instrument::Sampler>]`
         
     | 
| 
      
 1303 
     | 
    
         
            +
                - percent-based log sampler that decides should be RQL case instrumented or not;
         
     | 
| 
      
 1304 
     | 
    
         
            +
                - pre-configured in `config['instr_sampler']`;
         
     | 
| 
      
 1305 
     | 
    
         
            +
              - `instr_sample_this` - (optional) `[Boolean]`
         
     | 
| 
      
 1306 
     | 
    
         
            +
                - marks the method that everything should be instrumneted despite the enabled instrumentation sampling;
         
     | 
| 
      
 1307 
     | 
    
         
            +
                - makes sense when instrumentation sampling is enabled;
         
     | 
| 
      
 1308 
     | 
    
         
            +
                - `false` by default;
         
     | 
| 
      
 1309 
     | 
    
         
            +
            - returns:
         
     | 
| 
      
 1310 
     | 
    
         
            +
              - `[Hash<Symbol,Numeric>]` - Format: `{ ok: true, result: Hash<Symbol,Numeric> }`;
         
     | 
| 
      
 1311 
     | 
    
         
            +
              - result data:
         
     | 
| 
      
 1312 
     | 
    
         
            +
                - `:rel_time` - `Numeric` - time spent;
         
     | 
| 
      
 1313 
     | 
    
         
            +
                - `:rel_key_cnt` - `Integer` - the count of released locks;
         
     | 
| 
      
 1314 
     | 
    
         
            +
                - `:tch_queue_cnt` - `Integer` - the count of touched (modified) queues (the number of queues from which the acquirer/host was removed);
         
     | 
| 
      
 1315 
     | 
    
         
            +
             
     | 
| 
      
 1316 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 1317 
     | 
    
         
            +
            rql.clear_current_locks
         
     | 
| 
      
 1318 
     | 
    
         
            +
            # -- or (alias) --
         
     | 
| 
      
 1319 
     | 
    
         
            +
            rql.release_current_locks
         
     | 
| 
      
 1320 
     | 
    
         
            +
            # equivalent:
         
     | 
| 
      
 1321 
     | 
    
         
            +
            rql.release_locks_of(host_id: rql.current_host_id, acquirer_id: rql.current_acquirer_id)
         
     | 
| 
      
 1322 
     | 
    
         
            +
             
     | 
| 
      
 1323 
     | 
    
         
            +
            # -> result
         
     | 
| 
      
 1324 
     | 
    
         
            +
            {
         
     | 
| 
      
 1325 
     | 
    
         
            +
              ok: true,
         
     | 
| 
      
 1326 
     | 
    
         
            +
              result: {
         
     | 
| 
      
 1327 
     | 
    
         
            +
                rel_key_cnt: 43,
         
     | 
| 
      
 1328 
     | 
    
         
            +
                tch_queue_cnt: 3,
         
     | 
| 
      
 1329 
     | 
    
         
            +
                rel_time: 0.2
         
     | 
| 
      
 1330 
     | 
    
         
            +
              }
         
     | 
| 
      
 1331 
     | 
    
         
            +
            }
         
     | 
| 
      
 1332 
     | 
    
         
            +
            ```
         
     | 
| 
      
 1333 
     | 
    
         
            +
             
     | 
| 
      
 1334 
     | 
    
         
            +
            ---
         
     | 
| 
      
 1335 
     | 
    
         
            +
             
     | 
| 
       1123 
1336 
     | 
    
         
             
            #### #extend_lock_ttl
         
     | 
| 
       1124 
1337 
     | 
    
         | 
| 
       1125 
1338 
     | 
    
         
             
            <sup>\[[back to top](#usage)\]</sup>
         
     | 
| 
         @@ -1320,7 +1533,7 @@ rql.locks_info # or rql.locks_info(scan_size: 123) 
     | 
|
| 
       1320 
1533 
     | 
    
         
             
               :status=>:alive,
         
     | 
| 
       1321 
1534 
     | 
    
         
             
               :info=>{
         
     | 
| 
       1322 
1535 
     | 
    
         
             
                "acq_id"=>"rql:acq:41478/4320/4340/4360/848818f09d8c3420",
         
     | 
| 
       1323 
     | 
    
         
            -
                "hst_id"=>"rql:hst:41478/4320/4360/848818f09d8c3420"
         
     | 
| 
      
 1536 
     | 
    
         
            +
                "hst_id"=>"rql:hst:41478/4320/4360/848818f09d8c3420",
         
     | 
| 
       1324 
1537 
     | 
    
         
             
                "ts"=>1711607112.670343,
         
     | 
| 
       1325 
1538 
     | 
    
         
             
                "ini_ttl"=>15000,
         
     | 
| 
       1326 
1539 
     | 
    
         
             
                "rem_ttl"=>13998}},
         
     | 
| 
         @@ -1383,7 +1596,7 @@ Accepts: 
     | 
|
| 
       1383 
1596 
     | 
    
         
             
            - `:dead_ttl` - (optional) `[Integer]`
         
     | 
| 
       1384 
1597 
     | 
    
         
             
              - lock request ttl after which a lock request is considered dead;
         
     | 
| 
       1385 
1598 
     | 
    
         
             
              - has a preconfigured value in `config['dead_request_ttl']` (1 day by default);
         
     | 
| 
       1386 
     | 
    
         
            -
            - `: 
     | 
| 
      
 1599 
     | 
    
         
            +
            - `:scan_size` - (optional) `[Integer]`
         
     | 
| 
       1387 
1600 
     | 
    
         
             
              - the batch of scanned keys for Redis'es SCAN command;
         
     | 
| 
       1388 
1601 
     | 
    
         
             
              - has a preconfigured valie in `config['lock_release_batch_size']`;
         
     | 
| 
       1389 
1602 
     | 
    
         
             
            - `:logger` - (optional) `[::Logger,#debug]`
         
     | 
| 
         @@ -1445,6 +1658,7 @@ rql.clear_dead_requests(dead_ttl: 60 * 60 * 1000) # 1 hour in milliseconds 
     | 
|
| 
       1445 
1658 
     | 
    
         | 
| 
       1446 
1659 
     | 
    
         
             
            <sup>\[[back to top](#usage)\]</sup>
         
     | 
| 
       1447 
1660 
     | 
    
         | 
| 
      
 1661 
     | 
    
         
            +
            - (aliases: `#current_acq_id`, `#acq_id`);
         
     | 
| 
       1448 
1662 
     | 
    
         
             
            - get the current acquirer identifier in RQL notation that you can use for debugging purposes during the lock analyzation;
         
     | 
| 
       1449 
1663 
     | 
    
         
             
            - acquirer identifier format:
         
     | 
| 
       1450 
1664 
     | 
    
         
             
              ```ruby
         
     | 
| 
         @@ -1482,6 +1696,7 @@ rql.current_acquirer_id 
     | 
|
| 
       1482 
1696 
     | 
    
         | 
| 
       1483 
1697 
     | 
    
         
             
            <sup>\[[back to top](#usage)\]</sup>
         
     | 
| 
       1484 
1698 
     | 
    
         | 
| 
      
 1699 
     | 
    
         
            +
            - (aliases: `#current_hst_id`, `#hst_id`);
         
     | 
| 
       1485 
1700 
     | 
    
         
             
            - get a current host identifier in RQL notation that you can use for debugging purposes during the lock analyzis;
         
     | 
| 
       1486 
1701 
     | 
    
         
             
            - the host is a ruby worker (a combination of process/thread/ractor/identity) that is alive and can obtain locks;
         
     | 
| 
       1487 
1702 
     | 
    
         
             
            - the host is limited to `process`/`thread`/`ractor` (without `fiber`) combination cuz we have no abilities to extract
         
     | 
| 
         @@ -1907,17 +2122,16 @@ config['log_sampler'] = RedisQueuedLocks::Logging::Sampler 
     | 
|
| 
       1907 
2122 
     | 
    
         | 
| 
       1908 
2123 
     | 
    
         
             
            An instrumentation layer is incapsulated in `instrumenter` object stored in [config](#configuration) (`RedisQueuedLocks::Client#config['instrumenter']`).
         
     | 
| 
       1909 
2124 
     | 
    
         | 
| 
       1910 
     | 
    
         
            -
            Instrumentation can be sampled 
     | 
| 
      
 2125 
     | 
    
         
            +
            Instrumentation can be **sampled**. See [Instrumentation Configuration](#instrumentation-configuration) section for details.
         
     | 
| 
       1911 
2126 
     | 
    
         | 
| 
       1912 
2127 
     | 
    
         
             
            Instrumenter object should provide `notify(event, payload)` method with the following signarue:
         
     | 
| 
       1913 
2128 
     | 
    
         | 
| 
       1914 
2129 
     | 
    
         
             
            - `event` - `string`;
         
     | 
| 
       1915 
2130 
     | 
    
         
             
            - `payload` - `hash<Symbol,Any>`;
         
     | 
| 
       1916 
2131 
     | 
    
         | 
| 
       1917 
     | 
    
         
            -
             
     | 
| 
      
 2132 
     | 
    
         
            +
            **RQL** provides two instrumenters:
         
     | 
| 
       1918 
2133 
     | 
    
         | 
| 
       1919 
     | 
    
         
            -
            - `RedisQueuedLocks::Instrument::ActiveSupport` - **ActiveSupport::Notifications** instrumenter
         
     | 
| 
       1920 
     | 
    
         
            -
              that instrument events via **ActiveSupport::Notifications** API;
         
     | 
| 
      
 2134 
     | 
    
         
            +
            - `RedisQueuedLocks::Instrument::ActiveSupport` - **ActiveSupport::Notifications** instrumenter that instrument events via **ActiveSupport::Notifications** API;
         
     | 
| 
       1921 
2135 
     | 
    
         
             
            - `RedisQueuedLocks::Instrument::VoidNotifier` - instrumenter that does nothing;
         
     | 
| 
       1922 
2136 
     | 
    
         | 
| 
       1923 
2137 
     | 
    
         
             
            By default `RedisQueuedLocks::Client` is configured with the void notifier (which means "instrumentation is disabled").
         
     | 
| 
         @@ -1972,95 +2186,115 @@ config['instr_sampler'] = RedisQueuedLocks::Instrument::Sampler 
     | 
|
| 
       1972 
2186 
     | 
    
         | 
| 
       1973 
2187 
     | 
    
         
             
            List of instrumentation events
         
     | 
| 
       1974 
2188 
     | 
    
         | 
| 
       1975 
     | 
    
         
            -
            -  
     | 
| 
       1976 
     | 
    
         
            -
            -  
     | 
| 
       1977 
     | 
    
         
            -
            -  
     | 
| 
       1978 
     | 
    
         
            -
            -  
     | 
| 
       1979 
     | 
    
         
            -
            -  
     | 
| 
       1980 
     | 
    
         
            -
            -  
     | 
| 
       1981 
     | 
    
         
            -
            -  
     | 
| 
      
 2189 
     | 
    
         
            +
            - ["redis_queued_locks.lock_obtained"](#redis_queued_lockslock_hold_and_release)
         
     | 
| 
      
 2190 
     | 
    
         
            +
            - ["redis_queued_locks.extendable_reentrant_lock_obtained"](#redis_queued_locksextendable_reentrant_lock_obtained)
         
     | 
| 
      
 2191 
     | 
    
         
            +
            - ["redis_queued_locks.reentrant_lock_obtained"](#redis_queued_locksreentrant_lock_obtained)
         
     | 
| 
      
 2192 
     | 
    
         
            +
            - ["redis_queued_locks.lock_hold_and_release"](#redis_queued_lockslock_hold_and_release)
         
     | 
| 
      
 2193 
     | 
    
         
            +
            - ["redis_queued_locks.reentrant_lock_hold_completes"](#redis_queued_locksreentrant_lock_hold_completes)
         
     | 
| 
      
 2194 
     | 
    
         
            +
            - ["redis_queued_locks.explicit_lock_release"](#redis_queued_locksexplicit_lock_release)
         
     | 
| 
      
 2195 
     | 
    
         
            +
            - ["redis_queued_locks.explicit_all_locks_release"](#redis_queued_locksexplicit_all_locks_release)
         
     | 
| 
      
 2196 
     | 
    
         
            +
            - ["redis_queued_locks.release_locks_of"](#redis_queued_locksrelease_locks_of)
         
     | 
| 
       1982 
2197 
     | 
    
         | 
| 
       1983 
2198 
     | 
    
         
             
            Detalized event semantics and payload structure:
         
     | 
| 
       1984 
2199 
     | 
    
         | 
| 
       1985 
     | 
    
         
            -
             
     | 
| 
       1986 
     | 
    
         
            -
             
     | 
| 
       1987 
     | 
    
         
            -
             
     | 
| 
       1988 
     | 
    
         
            -
             
     | 
| 
       1989 
     | 
    
         
            -
             
     | 
| 
       1990 
     | 
    
         
            -
             
     | 
| 
       1991 
     | 
    
         
            -
             
     | 
| 
       1992 
     | 
    
         
            -
             
     | 
| 
       1993 
     | 
    
         
            -
             
     | 
| 
       1994 
     | 
    
         
            -
             
     | 
| 
       1995 
     | 
    
         
            -
             
     | 
| 
       1996 
     | 
    
         
            -
             
     | 
| 
       1997 
     | 
    
         
            -
             
     | 
| 
       1998 
     | 
    
         
            -
             
     | 
| 
       1999 
     | 
    
         
            -
             
     | 
| 
       2000 
     | 
    
         
            -
             
     | 
| 
       2001 
     | 
    
         
            -
             
     | 
| 
       2002 
     | 
    
         
            -
             
     | 
| 
       2003 
     | 
    
         
            -
             
     | 
| 
       2004 
     | 
    
         
            -
             
     | 
| 
       2005 
     | 
    
         
            -
             
     | 
| 
       2006 
     | 
    
         
            -
             
     | 
| 
       2007 
     | 
    
         
            -
             
     | 
| 
       2008 
     | 
    
         
            -
             
     | 
| 
       2009 
     | 
    
         
            -
            - ` 
     | 
| 
       2010 
     | 
    
         
            -
             
     | 
| 
       2011 
     | 
    
         
            -
             
     | 
| 
       2012 
     | 
    
         
            -
             
     | 
| 
       2013 
     | 
    
         
            -
             
     | 
| 
       2014 
     | 
    
         
            -
             
     | 
| 
       2015 
     | 
    
         
            -
             
     | 
| 
       2016 
     | 
    
         
            -
             
     | 
| 
       2017 
     | 
    
         
            -
             
     | 
| 
       2018 
     | 
    
         
            -
             
     | 
| 
       2019 
     | 
    
         
            -
             
     | 
| 
       2020 
     | 
    
         
            -
             
     | 
| 
       2021 
     | 
    
         
            -
            - ` 
     | 
| 
       2022 
     | 
    
         
            -
              -  
     | 
| 
       2023 
     | 
    
         
            -
             
     | 
| 
       2024 
     | 
    
         
            -
             
     | 
| 
       2025 
     | 
    
         
            -
             
     | 
| 
       2026 
     | 
    
         
            -
             
     | 
| 
       2027 
     | 
    
         
            -
             
     | 
| 
       2028 
     | 
    
         
            -
             
     | 
| 
       2029 
     | 
    
         
            -
             
     | 
| 
       2030 
     | 
    
         
            -
             
     | 
| 
       2031 
     | 
    
         
            -
             
     | 
| 
       2032 
     | 
    
         
            -
             
     | 
| 
       2033 
     | 
    
         
            -
             
     | 
| 
       2034 
     | 
    
         
            -
            - ` 
     | 
| 
       2035 
     | 
    
         
            -
              -  
     | 
| 
       2036 
     | 
    
         
            -
              -  
     | 
| 
       2037 
     | 
    
         
            -
             
     | 
| 
       2038 
     | 
    
         
            -
             
     | 
| 
       2039 
     | 
    
         
            -
             
     | 
| 
       2040 
     | 
    
         
            -
             
     | 
| 
       2041 
     | 
    
         
            -
             
     | 
| 
       2042 
     | 
    
         
            -
             
     | 
| 
       2043 
     | 
    
         
            -
             
     | 
| 
       2044 
     | 
    
         
            -
             
     | 
| 
       2045 
     | 
    
         
            -
             
     | 
| 
       2046 
     | 
    
         
            -
             
     | 
| 
       2047 
     | 
    
         
            -
             
     | 
| 
       2048 
     | 
    
         
            -
            - ` 
     | 
| 
       2049 
     | 
    
         
            -
              -  
     | 
| 
       2050 
     | 
    
         
            -
              -  
     | 
| 
       2051 
     | 
    
         
            -
              -  
     | 
| 
       2052 
     | 
    
         
            -
             
     | 
| 
       2053 
     | 
    
         
            -
             
     | 
| 
       2054 
     | 
    
         
            -
             
     | 
| 
       2055 
     | 
    
         
            -
             
     | 
| 
       2056 
     | 
    
         
            -
             
     | 
| 
       2057 
     | 
    
         
            -
            -  
     | 
| 
       2058 
     | 
    
         
            -
              -  
     | 
| 
       2059 
     | 
    
         
            -
              -  
     | 
| 
       2060 
     | 
    
         
            -
              -  
     | 
| 
       2061 
     | 
    
         
            -
             
     | 
| 
       2062 
     | 
    
         
            -
             
     | 
| 
       2063 
     | 
    
         
            -
             
     | 
| 
      
 2200 
     | 
    
         
            +
            ##### `"redis_queued_locks.lock_obtained"`
         
     | 
| 
      
 2201 
     | 
    
         
            +
            - <sup>\[[back to the list](#instrumentation-events)\]</sup>
         
     | 
| 
      
 2202 
     | 
    
         
            +
            - a moment when the lock was obtained;
         
     | 
| 
      
 2203 
     | 
    
         
            +
            - raised from `#lock`/`#lock!`;
         
     | 
| 
      
 2204 
     | 
    
         
            +
            - payload:
         
     | 
| 
      
 2205 
     | 
    
         
            +
              - `:ttl` - `integer`/`milliseconds` - lock ttl;
         
     | 
| 
      
 2206 
     | 
    
         
            +
              - `:acq_id` - `string` - lock acquirer identifier;
         
     | 
| 
      
 2207 
     | 
    
         
            +
              - `:hst_id` - `string` - lock's host identifier;
         
     | 
| 
      
 2208 
     | 
    
         
            +
              - `:lock_key` - `string` - lock name;
         
     | 
| 
      
 2209 
     | 
    
         
            +
              - `:ts` - `numeric`/`epoch` - the time when the lock was obtaiend;
         
     | 
| 
      
 2210 
     | 
    
         
            +
              - `:acq_time` - `float`/`milliseconds` - time spent on lock acquiring;
         
     | 
| 
      
 2211 
     | 
    
         
            +
              - `:instrument` - `nil`/`Any` - custom data passed to the `#lock`/`#lock!` method as `:instrument` attribute;
         
     | 
| 
      
 2212 
     | 
    
         
            +
             
     | 
| 
      
 2213 
     | 
    
         
            +
            ##### `"redis_queued_locks.extendable_reentrant_lock_obtained"`
         
     | 
| 
      
 2214 
     | 
    
         
            +
            - <sup>\[[back to the list](#instrumentation-events)\]</sup>
         
     | 
| 
      
 2215 
     | 
    
         
            +
            - an event signalizes about the "extendable reentrant lock" obtaining is happened;
         
     | 
| 
      
 2216 
     | 
    
         
            +
            - raised from `#lock`/`#lock!` when the lock was obtained as reentrant lock;
         
     | 
| 
      
 2217 
     | 
    
         
            +
            - payload:
         
     | 
| 
      
 2218 
     | 
    
         
            +
              - `:lock_key` - `string` - lock name;
         
     | 
| 
      
 2219 
     | 
    
         
            +
              - `:ttl` - `integer`/`milliseconds` - last lock ttl by reentrant locking;
         
     | 
| 
      
 2220 
     | 
    
         
            +
              - `:acq_id` - `string` - lock acquirer identifier;
         
     | 
| 
      
 2221 
     | 
    
         
            +
              - `:hst_id` - `string` - lock's host identifier;
         
     | 
| 
      
 2222 
     | 
    
         
            +
              - `:ts` - `numeric`/`epoch` - the time when the lock was obtaiend as extendable reentrant lock;
         
     | 
| 
      
 2223 
     | 
    
         
            +
              - `:acq_time` - `float`/`milliseconds` - time spent on lock acquiring;
         
     | 
| 
      
 2224 
     | 
    
         
            +
              - `:instrument` - `nil`/`Any` - custom data passed to the `#lock`/`#lock!` method as `:instrument` attribute;
         
     | 
| 
      
 2225 
     | 
    
         
            +
             
     | 
| 
      
 2226 
     | 
    
         
            +
            ##### `"redis_queued_locks.reentrant_lock_obtained"`
         
     | 
| 
      
 2227 
     | 
    
         
            +
            - <sup>\[[back to the list](#instrumentation-events)\]</sup>
         
     | 
| 
      
 2228 
     | 
    
         
            +
            - an event signalizes about the "reentrant lock" obtaining is happened (without TTL extension);
         
     | 
| 
      
 2229 
     | 
    
         
            +
            - raised from `#lock`/`#lock!` when the lock was obtained as reentrant lock;
         
     | 
| 
      
 2230 
     | 
    
         
            +
            - payload:
         
     | 
| 
      
 2231 
     | 
    
         
            +
              - `:lock_key` - `string` - lock name;
         
     | 
| 
      
 2232 
     | 
    
         
            +
              - `:ttl` - `integer`/`milliseconds` - last lock ttl by reentrant locking;
         
     | 
| 
      
 2233 
     | 
    
         
            +
              - `:acq_id` - `string` - lock acquirer identifier;
         
     | 
| 
      
 2234 
     | 
    
         
            +
              - `:hst_id` - `string` - lock's host identifier;
         
     | 
| 
      
 2235 
     | 
    
         
            +
              - `:ts` - `numeric`/`epoch` - the time when the lock was obtaiend as reentrant lock;
         
     | 
| 
      
 2236 
     | 
    
         
            +
              - `:acq_time` - `float`/`milliseconds` - time spent on lock acquiring;
         
     | 
| 
      
 2237 
     | 
    
         
            +
              - `:instrument` - `nil`/`Any` - custom data passed to the `#lock`/`#lock!` method as `:instrument` attribute;
         
     | 
| 
      
 2238 
     | 
    
         
            +
             
     | 
| 
      
 2239 
     | 
    
         
            +
            ##### `"redis_queued_locks.lock_hold_and_release"`
         
     | 
| 
      
 2240 
     | 
    
         
            +
            - <sup>\[[back to the list](#instrumentation-events)\]</sup>
         
     | 
| 
      
 2241 
     | 
    
         
            +
            - an event signalizes about the "hold+and+release" process is finished;
         
     | 
| 
      
 2242 
     | 
    
         
            +
            - raised from `#lock`/`#lock!` when invoked with a block of code;
         
     | 
| 
      
 2243 
     | 
    
         
            +
            - payload:
         
     | 
| 
      
 2244 
     | 
    
         
            +
              - `:hold_time` - `float`/`milliseconds` - lock hold time;
         
     | 
| 
      
 2245 
     | 
    
         
            +
              - `:ttl` - `integer`/`milliseconds` - lock ttl;
         
     | 
| 
      
 2246 
     | 
    
         
            +
              - `:acq_id` - `string` - lock acquirer identifier;
         
     | 
| 
      
 2247 
     | 
    
         
            +
              - `:hst_id` - `string` - lock's host identifier;
         
     | 
| 
      
 2248 
     | 
    
         
            +
              - `:lock_key` - `string` - lock name;
         
     | 
| 
      
 2249 
     | 
    
         
            +
              - `:ts` - `numeric`/`epoch` - the time when lock was obtained;
         
     | 
| 
      
 2250 
     | 
    
         
            +
              - `:acq_time` - `float`/`milliseconds` - time spent on lock acquiring;
         
     | 
| 
      
 2251 
     | 
    
         
            +
              - `:instrument` - `nil`/`Any` - custom data passed to the `#lock`/`#lock!` method as `:instrument` attribute;
         
     | 
| 
      
 2252 
     | 
    
         
            +
             
     | 
| 
      
 2253 
     | 
    
         
            +
            ##### `"redis_queued_locks.reentrant_lock_hold_completes"`
         
     | 
| 
      
 2254 
     | 
    
         
            +
            - <sup>\[[back to the list](#instrumentation-events)\]</sup>
         
     | 
| 
      
 2255 
     | 
    
         
            +
            - an event signalizes about the "reentrant lock hold" is complete (both extendable and non-extendable);
         
     | 
| 
      
 2256 
     | 
    
         
            +
            - lock re-entering can happen many times and this event happens for each of them separately;
         
     | 
| 
      
 2257 
     | 
    
         
            +
            - raised from `#lock`/`#lock!` when the lock was obtained as reentrant lock;
         
     | 
| 
      
 2258 
     | 
    
         
            +
            - payload:
         
     | 
| 
      
 2259 
     | 
    
         
            +
              - `:hold_time` - `float`/`milliseconds` - lock hold time;
         
     | 
| 
      
 2260 
     | 
    
         
            +
              - `:ttl` - `integer`/`milliseconds` - last lock ttl by reentrant locking;
         
     | 
| 
      
 2261 
     | 
    
         
            +
              - `:acq_id` - `string` - lock acquirer identifier;
         
     | 
| 
      
 2262 
     | 
    
         
            +
              - `:hst_id` - `string` - lock's host identifier;
         
     | 
| 
      
 2263 
     | 
    
         
            +
              - `:ts` - `numeric`/`epoch` - the time when the lock was obtaiend as reentrant lock;
         
     | 
| 
      
 2264 
     | 
    
         
            +
              - `:lock_key` - `string` - lock name;
         
     | 
| 
      
 2265 
     | 
    
         
            +
              - `:acq_time` - `float`/`milliseconds` - time spent on lock acquiring;
         
     | 
| 
      
 2266 
     | 
    
         
            +
              - `:instrument` - `nil`/`Any` - custom data passed to the `#lock`/`#lock!` method as `:instrument` attribute;
         
     | 
| 
      
 2267 
     | 
    
         
            +
             
     | 
| 
      
 2268 
     | 
    
         
            +
            ##### `"redis_queued_locks.explicit_lock_release"`
         
     | 
| 
      
 2269 
     | 
    
         
            +
            - <sup>\[[back to the list](#instrumentation-events)\]</sup>
         
     | 
| 
      
 2270 
     | 
    
         
            +
            - an event signalizes about the explicit lock release (invoked via `RedisQueuedLock#unlock`);
         
     | 
| 
      
 2271 
     | 
    
         
            +
            - raised from `#unlock`;
         
     | 
| 
      
 2272 
     | 
    
         
            +
            - payload:
         
     | 
| 
      
 2273 
     | 
    
         
            +
              - `:at` - `float`/`epoch` - the time when the lock was released;
         
     | 
| 
      
 2274 
     | 
    
         
            +
              - `:rel_time` - `float`/`milliseconds` - time spent on lock releasing;
         
     | 
| 
      
 2275 
     | 
    
         
            +
              - `:lock_key` - `string` - released lock (lock name);
         
     | 
| 
      
 2276 
     | 
    
         
            +
              - `:lock_key_queue` - `string` - released lock queue (lock queue name);
         
     | 
| 
      
 2277 
     | 
    
         
            +
             
     | 
| 
      
 2278 
     | 
    
         
            +
            ##### `"redis_queued_locks.explicit_all_locks_release"`
         
     | 
| 
      
 2279 
     | 
    
         
            +
            - <sup>\[[back to the list](#instrumentation-events)\]</sup>
         
     | 
| 
      
 2280 
     | 
    
         
            +
            - an event signalizes about the explicit all locks release (invoked via `RedisQueuedLock#clear_locks`);
         
     | 
| 
      
 2281 
     | 
    
         
            +
            - raised from `#clear_locks`;
         
     | 
| 
      
 2282 
     | 
    
         
            +
            - payload:
         
     | 
| 
      
 2283 
     | 
    
         
            +
              - `:rel_time` - `float`/`milliseconds` - time spent on "realese all locks" operation;
         
     | 
| 
      
 2284 
     | 
    
         
            +
              - `:at` - `float`/`epoch` - the time when the operation has ended;
         
     | 
| 
      
 2285 
     | 
    
         
            +
              - `:rel_keys` - `integer` - released redis keys count (`released queue keys` + `released lock keys`);
         
     | 
| 
      
 2286 
     | 
    
         
            +
             
     | 
| 
      
 2287 
     | 
    
         
            +
            ##### `"redis_queued_locks.release_locks_of"`
         
     | 
| 
      
 2288 
     | 
    
         
            +
            - <sup>\[[back to the list](#instrumentation-events)\]</sup>
         
     | 
| 
      
 2289 
     | 
    
         
            +
            - an event signalizes about the released locks (and removement from lock queues) of the concrete host and acquirer;
         
     | 
| 
      
 2290 
     | 
    
         
            +
            - raised from `#clear_locks_of` and `#clear_current_locks` (`#release_locks_of` and `#release_current_locks` respectively);
         
     | 
| 
      
 2291 
     | 
    
         
            +
            - payload:
         
     | 
| 
      
 2292 
     | 
    
         
            +
              - `:rel_time` - `float`/`milliseconds` - time spent on "release locks of" operation;
         
     | 
| 
      
 2293 
     | 
    
         
            +
              - `:at` - `float`/`epoch` - the time when the opertaion has ended; 
         
     | 
| 
      
 2294 
     | 
    
         
            +
              - `:acq_id` - `string` - refused acquirer identifier;
         
     | 
| 
      
 2295 
     | 
    
         
            +
              - `:hst_id` - `string` - refused host identifier;
         
     | 
| 
      
 2296 
     | 
    
         
            +
              - `:rel_key_cnt` - `integer` - released locks count;
         
     | 
| 
      
 2297 
     | 
    
         
            +
              - `:tch_queue_cnt` - `:integer` - the number of queues from which the concrete host/acquirer was removed;
         
     | 
| 
       2064 
2298 
     | 
    
         | 
| 
       2065 
2299 
     | 
    
         
             
            ---
         
     | 
| 
       2066 
2300 
     | 
    
         | 
| 
         @@ -2094,6 +2328,9 @@ Detalized event semantics and payload structure: 
     | 
|
| 
       2094 
2328 
     | 
    
         
             
                - `write` - waits - `write`;
         
     | 
| 
       2095 
2329 
     | 
    
         
             
                - **write** mode is a default behavior for all RQL locks;
         
     | 
| 
       2096 
2330 
     | 
    
         
             
            - **Minor**:
         
     | 
| 
      
 2331 
     | 
    
         
            +
              - add `hst_id` to all methods that works with queues info;
         
     | 
| 
      
 2332 
     | 
    
         
            +
              - try to return the `fiber object id` to the lock host identifier (we cant use fiber object id cuz `ObjectSpace` has no access to the fiber object space after the any ractor object initialization)
         
     | 
| 
      
 2333 
     | 
    
         
            +
              - named RQL's threads (`Thread#name`) and RQL's ractors (`Ractor#name`) in order to have an ability to find and work with RQL's threads and ractors outside of RQL logic (stop threads before process forking, for example);
         
     | 
| 
       2097 
2334 
     | 
    
         
             
              - `#lock`/`#lock!` - `timeout:` option: support for granular periods (it supports only `seconds` at the moment, but we need `milliseconds`);
         
     | 
| 
       2098 
2335 
     | 
    
         
             
              - Add `after timeout hook` ability for timeout errors with an ability to access the binding context (if it possibly) of the thread where it failed;
         
     | 
| 
       2099 
2336 
     | 
    
         
             
              - Add `ignore timeout errors` ability (for debug purposes);
         
     | 
| 
         @@ -2120,7 +2357,31 @@ Detalized event semantics and payload structure: 
     | 
|
| 
       2120 
2357 
     | 
    
         
             
              - `unlock_on:`-option in lock/lock! logic in order to support auto-unlocking on any exception rasaied under the invoked block (invoked under the lock);
         
     | 
| 
       2121 
2358 
     | 
    
         
             
              - **Research**: support for `Valkey` database backend (https://github.com/valkey-io/valkey) (https://valkey.io/);
         
     | 
| 
       2122 
2359 
     | 
    
         
             
              - **Research**: support for `Garnet` database backend (https://microsoft.github.io/) (https://github.com/microsoft/garnet);
         
     | 
| 
       2123 
     | 
    
         
            -
              - add a library-level exception, when RQL-related key (required for  
     | 
| 
      
 2360 
     | 
    
         
            +
              - add a library-level exception, when RQL-related key in Redis (required for its logic) has incompatible type (means: some other program uses our key with their own type and logic and RQL can't work properly);
         
     | 
| 
      
 2361 
     | 
    
         
            +
            ---
         
     | 
| 
      
 2362 
     | 
    
         
            +
             
     | 
| 
      
 2363 
     | 
    
         
            +
            ## Build and Develop
         
     | 
| 
      
 2364 
     | 
    
         
            +
             
     | 
| 
      
 2365 
     | 
    
         
            +
            - Tests (`RSpec`):
         
     | 
| 
      
 2366 
     | 
    
         
            +
            ```shell
         
     | 
| 
      
 2367 
     | 
    
         
            +
            bundle exec rake rspec
         
     | 
| 
      
 2368 
     | 
    
         
            +
            ```
         
     | 
| 
      
 2369 
     | 
    
         
            +
             
     | 
| 
      
 2370 
     | 
    
         
            +
            - Linting (`Rubocop`+`RBS`):
         
     | 
| 
      
 2371 
     | 
    
         
            +
            ```shell
         
     | 
| 
      
 2372 
     | 
    
         
            +
            bundle exec rake rubocop
         
     | 
| 
      
 2373 
     | 
    
         
            +
            ```
         
     | 
| 
      
 2374 
     | 
    
         
            +
             
     | 
| 
      
 2375 
     | 
    
         
            +
            - `Static` TypeChecking (`Steep`):
         
     | 
| 
      
 2376 
     | 
    
         
            +
            ```shell
         
     | 
| 
      
 2377 
     | 
    
         
            +
            bundle exec rake steep:check
         
     | 
| 
      
 2378 
     | 
    
         
            +
            ```
         
     | 
| 
      
 2379 
     | 
    
         
            +
             
     | 
| 
      
 2380 
     | 
    
         
            +
            - `Runtime` TypeChecking (`RBS`):
         
     | 
| 
      
 2381 
     | 
    
         
            +
            ```shell
         
     | 
| 
      
 2382 
     | 
    
         
            +
            bundle exec rbs collection install && RBS_TEST_RAISE=true RUBYOPT='-rrbs/test/setup' RBS_TEST_OPT='-I sig' RBS_TEST_LOGLEVEL=error RBS_TEST_TARGET='RedisQueuedLocks::*' bundle exec rspec --failure-exit-code=0
         
     | 
| 
      
 2383 
     | 
    
         
            +
            ```
         
     | 
| 
      
 2384 
     | 
    
         
            +
             
     | 
| 
       2124 
2385 
     | 
    
         
             
            ---
         
     | 
| 
       2125 
2386 
     | 
    
         | 
| 
       2126 
2387 
     | 
    
         
             
            ## Contributing
         
     | 
    
        data/Rakefile
    CHANGED