redis_queued_locks 1.11.0 → 1.12.1
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/CHANGELOG.md +15 -1
- data/README.md +11 -2
- data/lib/redis_queued_locks/acquier/acquire_lock/with_acq_timeout.rb +2 -4
- data/lib/redis_queued_locks/acquier/acquire_lock/yield_expire.rb +7 -13
- data/lib/redis_queued_locks/acquier/acquire_lock.rb +2 -2
- data/lib/redis_queued_locks/errors.rb +4 -0
- data/lib/redis_queued_locks/utilities/lock.rb +4 -2
- data/lib/redis_queued_locks/version.rb +2 -2
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 419bb42dc0f90c9cfac1107f3eb93ab4e5185d17efa53f78012eed09aee03931
|
4
|
+
data.tar.gz: c9e1471bc65375cbabe88276c7144460b05bb3e0cb4880a75b061514578a4e3d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aa5e610820ffb105003d09918ee5df8c51989de24a0473eb0d9056deb5e0c2de0cc8c23c220bd4b8da14a7ff0d2b2c7271cc521862263251c03382d4f246f302
|
7
|
+
data.tar.gz: dc14d292c361c798c1cd5a375ff48f271d96a35246c2e463d331dfe9dcb116b64f3b17ad95e12a5e5f72f8aad2a243a17cc0ed10a2ab4521773385bc51d2c77d
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,20 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
-
|
3
|
+
## [1.12.1]
|
4
|
+
### Changed
|
5
|
+
- Internal Private API: an internal Reentrant's Lock utility (`RedisQueuedLocks::Utilities::Lock`) basis
|
6
|
+
is changed from `::Mutex` to `::Monitor` in order to use Ruby's Core C-based
|
7
|
+
implementation (prevent some Ruby-runtime based GVL-oriented locking) of re-entrant locks
|
8
|
+
instead of the custom Ruby-based implementation;
|
9
|
+
### Fixed
|
10
|
+
- `redis_queued_locks.lock_hold_and_release` instrumentation event has incorrect `acq_time` payload value
|
11
|
+
(it incorrectly stores `lock_key` payload value);
|
12
|
+
|
13
|
+
## [1.12.0] - 2024-08-11
|
14
|
+
### Changed
|
15
|
+
- Timed blocks of code and their timeout errors: reduced error message object allocations;
|
16
|
+
|
17
|
+
## [1.11.0] - 2024-08-11
|
4
18
|
### Changed
|
5
19
|
- Lock Acquierment Timeout (`acq_timeout`/`queue_ttl`): more correct timeout error interception
|
6
20
|
inside the `RedisQueuedLocks::Acquier::AcquireLock::WithAcqTimeout` logic that now raises and
|
data/README.md
CHANGED
@@ -2073,25 +2073,34 @@ Detalized event semantics and payload structure:
|
|
2073
2073
|
trying to ressurect unexpectedly terminated swarm elements, and will notify about this;
|
2074
2074
|
- swarm logs (thread/ractor has some limitations so the initial implementation does not include swarm logging);
|
2075
2075
|
- swarm instrumentation (thread/ractor has some limitations so the initial implementation does not include swarm instrumentation);
|
2076
|
+
- isolated timeouts which are independent of internal Ruby's timeout implementation (where all timeouts are hostend inside
|
2077
|
+
the global "timeout request" queue and managed by a single global "timeout wathcer" thread). it should prevent any logic and timeout intersections,
|
2078
|
+
some GVL-related things and problem situations when the global watcher thread is "dead";
|
2076
2079
|
- lock request prioritization;
|
2077
|
-
- **strict redlock algorithm support** (support for many `RedisClient` instances);
|
2080
|
+
- **strict redlock algorithm support** (support for many `RedisClient` instances that are fully independent (distributed redis instances));
|
2078
2081
|
- `#lock_series` - acquire a series of locks:
|
2079
2082
|
```ruby
|
2080
2083
|
rql.lock_series('lock_a', 'lock_b', 'lock_c') { puts 'locked' }
|
2081
2084
|
```
|
2082
|
-
-
|
2085
|
+
- `light mode`: an ability to work without any debug and instrumentation logic and data (totally reduced debugging and instrumenting possibilities, but better performance);
|
2083
2086
|
- **Minor**:
|
2087
|
+
- support for `Dragonfly` database backend (https://github.com/dragonflydb/dragonfly) (https://www.dragonflydb.io/);
|
2088
|
+
- (_research_) GVL-isolation for lock acquirement logic (try to bypass Ruby's "context-switching" in order to prevent any time-based affects on lock-acquirement logic);
|
2084
2089
|
- Semantic error objects for unexpected Redis errors;
|
2085
2090
|
- **Experimental feature**: (non-`timed` locks): per-ruby-block-holding-the-lock sidecar `Ractor` and `in progress queue` in RedisDB that will extend
|
2086
2091
|
the acquired lock for long-running blocks of code (that invoked "under" the lock
|
2087
2092
|
whose ttl may expire before the block execution completes). It makes sense for non-`timed` locks *only*;
|
2093
|
+
- sized lock queues (with an ability of dynamically growing size);
|
2088
2094
|
- better code stylization (+ some refactorings);
|
2089
2095
|
- `RedisQueuedLocks::Acquier::Try.try_to_lock` - detailed successful result analization;
|
2090
2096
|
- Support for LIFO strategy;
|
2091
2097
|
- better specs with 100% test coverage (total specs rework);
|
2092
2098
|
- statistics with UI;
|
2093
2099
|
- JSON log formatter;
|
2100
|
+
- RBS type signatures;
|
2101
|
+
- **automatic** deadlock detection;
|
2094
2102
|
- `go`-lang implementation;
|
2103
|
+
- (_research_) simplification and speedup of the internal "redis-communuication-and-data-storing"-based algorithms;
|
2095
2104
|
|
2096
2105
|
---
|
2097
2106
|
|
@@ -19,6 +19,8 @@ module RedisQueuedLocks::Acquier::AcquireLock::WithAcqTimeout
|
|
19
19
|
# Callback invoked on Timeout::Error.
|
20
20
|
# @return [Any]
|
21
21
|
#
|
22
|
+
# @raise [RedisQueuedLocks::LockAcquiermentIntermediateTimeoutError]
|
23
|
+
#
|
22
24
|
# @api private
|
23
25
|
# @since 1.0.0
|
24
26
|
# @version 1.11.0
|
@@ -32,10 +34,6 @@ module RedisQueuedLocks::Acquier::AcquireLock::WithAcqTimeout
|
|
32
34
|
on_timeout: nil,
|
33
35
|
&block
|
34
36
|
)
|
35
|
-
# TODO:
|
36
|
-
# think about the runtime error class-object creation that perevent any timeout error
|
37
|
-
# interception collisions (but remember: it can lead to regular internal ruby method/constant
|
38
|
-
# cache invalidation);
|
39
37
|
::Timeout.timeout(timeout, RedisQueuedLocks::LockAcquiermentIntermediateTimeoutError, &block)
|
40
38
|
rescue RedisQueuedLocks::LockAcquiermentIntermediateTimeoutError
|
41
39
|
on_timeout.call unless on_timeout == nil
|
@@ -107,28 +107,22 @@ module RedisQueuedLocks::Acquier::AcquireLock::YieldExpire
|
|
107
107
|
# @param block [Blcok]
|
108
108
|
# @return [Any]
|
109
109
|
#
|
110
|
+
# @raise [RedisQueuedLocks::TimedLockTimeoutError]
|
111
|
+
#
|
110
112
|
# @api private
|
111
113
|
# @since 1.3.0
|
112
|
-
# @version 1.
|
114
|
+
# @version 1.12.0
|
113
115
|
def yield_with_timeout(timeout, lock_key, lock_ttl, acquier_id, host_id, meta, &block)
|
114
|
-
::Timeout.timeout(
|
115
|
-
|
116
|
+
::Timeout.timeout(timeout, RedisQueuedLocks::TimedLockIntermediateTimeoutError, &block)
|
117
|
+
rescue RedisQueuedLocks::TimedLockIntermediateTimeoutError
|
118
|
+
raise(
|
116
119
|
RedisQueuedLocks::TimedLockTimeoutError,
|
117
|
-
# NOTE:
|
118
|
-
# - this string is generated on each invocation cuz we need to raise custom exception
|
119
|
-
# from the Timeout API in order to prevent incorred Timeout::Error interception when
|
120
|
-
# the intercepted error is caused from the block not from the RQL;
|
121
|
-
# - we can't omit this string object creation at the moment via original Ruby's Timeout API;
|
122
|
-
# TODO:
|
123
|
-
# - refine Timeout#timeout (via Ruby's Refinement API) in order to provide lazy exception
|
124
|
-
# message initialization;
|
125
120
|
"Passed <timed> block of code exceeded the lock TTL " \
|
126
121
|
"(lock: \"#{lock_key}\", " \
|
127
122
|
"ttl: #{lock_ttl}, " \
|
128
123
|
"meta: #{meta ? meta.inspect : '<no-meta>'}, " \
|
129
124
|
"acq_id: \"#{acquier_id}\", " \
|
130
|
-
"hst_id: \"#{host_id}\")"
|
131
|
-
&block
|
125
|
+
"hst_id: \"#{host_id}\")"
|
132
126
|
)
|
133
127
|
end
|
134
128
|
end
|
@@ -154,7 +154,7 @@ module RedisQueuedLocks::Acquier::AcquireLock
|
|
154
154
|
#
|
155
155
|
# @api private
|
156
156
|
# @since 1.0.0
|
157
|
-
# @version 1.
|
157
|
+
# @version 1.12.1
|
158
158
|
def acquire_lock(
|
159
159
|
redis,
|
160
160
|
lock_name,
|
@@ -531,8 +531,8 @@ module RedisQueuedLocks::Acquier::AcquireLock
|
|
531
531
|
acq_process[:lock_info][:acq_id],
|
532
532
|
acq_process[:lock_info][:hst_id],
|
533
533
|
acq_process[:lock_info][:ts],
|
534
|
-
acq_process[:lock_info][:lock_key],
|
535
534
|
acq_process[:acq_time],
|
535
|
+
acq_process[:hold_time],
|
536
536
|
instrument
|
537
537
|
)
|
538
538
|
end
|
@@ -25,6 +25,10 @@ module RedisQueuedLocks
|
|
25
25
|
# @since 1.0.0
|
26
26
|
LockAcquiermentRetryLimitError = Class.new(Error)
|
27
27
|
|
28
|
+
# @api private
|
29
|
+
# @since 1.12.0
|
30
|
+
TimedLockIntermediateTimeoutError = Class.new(::Timeout::Error)
|
31
|
+
|
28
32
|
# @api pulic
|
29
33
|
# @since 1.0.0
|
30
34
|
TimedLockTimeoutError = Class.new(Error)
|
@@ -7,8 +7,9 @@ class RedisQueuedLocks::Utilities::Lock
|
|
7
7
|
#
|
8
8
|
# @api private
|
9
9
|
# @since 1.9.0
|
10
|
+
# @version 1.13.0
|
10
11
|
def initialize
|
11
|
-
@lock = ::
|
12
|
+
@lock = ::Monitor.new
|
12
13
|
end
|
13
14
|
|
14
15
|
# @param block [Block]
|
@@ -16,7 +17,8 @@ class RedisQueuedLocks::Utilities::Lock
|
|
16
17
|
#
|
17
18
|
# @api private
|
18
19
|
# @since 1.9.0
|
20
|
+
# @version 1.13.0
|
19
21
|
def synchronize(&block)
|
20
|
-
@lock.
|
22
|
+
@lock.synchronize(&block)
|
21
23
|
end
|
22
24
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redis_queued_locks
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.12.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rustam Ibragimov
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-09-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis-client
|
@@ -135,7 +135,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
135
135
|
- !ruby/object:Gem::Version
|
136
136
|
version: '0'
|
137
137
|
requirements: []
|
138
|
-
rubygems_version: 3.5.
|
138
|
+
rubygems_version: 3.5.17
|
139
139
|
signing_key:
|
140
140
|
specification_version: 4
|
141
141
|
summary: Distributed locks with "prioritized lock acquisition queue" capabilities
|