specwrk-store-redis_adapter 0.0.3 → 0.0.5
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/docker-compose.yml +1 -1
- data/lib/specwrk/store/redis_adapter.rb +37 -64
- metadata +1 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 626a515c92546cb68ff4378393f6bdf02af48e022c0cb481990eab35cdcdedbd
|
4
|
+
data.tar.gz: e4c2a3d80b9585ab9ae554a6cc470b37f66223f374a09876c5e35bddd0c4aa44
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 35cdba9ff17f1c868b0968b17d4ccd1c90842d4a06b0c8cae7dd4ea9c9b2726b3480c056ef505ca9fdf3d961d54721015d4d2a667f6f6e3a91c2d5f61bca3ea8
|
7
|
+
data.tar.gz: d52567dfc1112d99a91809ef3edb754269ef0cccc4d7988293c3a74e1a333ef33578bac596d5074625ec59a0a405bfffd5c992a4954fe4a2151c751716d29d69
|
data/docker-compose.yml
CHANGED
@@ -1,36 +1,40 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "json"
|
4
|
+
require "securerandom"
|
4
5
|
|
5
6
|
require "specwrk/store/base_adapter"
|
6
7
|
require "redis-client"
|
7
|
-
require "redlock"
|
8
8
|
|
9
9
|
module Specwrk
|
10
10
|
class Store
|
11
11
|
class RedisAdapter < Specwrk::Store::BaseAdapter
|
12
|
-
VERSION = "0.1.0"
|
13
|
-
|
14
|
-
REDIS_KEY_DELIMITER = "||||"
|
15
|
-
|
16
12
|
@connection_pools = {}
|
17
13
|
@mutex = Mutex.new
|
18
14
|
|
19
15
|
class << self
|
20
16
|
def with_lock(uri, key)
|
21
17
|
connection_pool_for(uri).with do |connection|
|
22
|
-
|
23
|
-
[connection],
|
24
|
-
retry_count: lock_retry_count,
|
25
|
-
retry_delay: lock_retry_delay,
|
26
|
-
retry_jitter: lock_retry_jitter
|
27
|
-
)
|
18
|
+
Thread.current[:connection] = connection
|
28
19
|
|
29
|
-
|
30
|
-
|
20
|
+
id = SecureRandom.uuid
|
21
|
+
queue = "specwrk-lock-#{key}"
|
22
|
+
connection.pipelined do |pipeline|
|
23
|
+
pipeline.call("RPUSH", queue, id)
|
24
|
+
pipeline.call("EXPIRE", queue, 10) # only set if no expireat already
|
31
25
|
end
|
32
26
|
|
33
|
-
|
27
|
+
# wait for our id to be first in line or the queue to expire
|
28
|
+
Thread.pass until [id, nil].include? connection.call("LINDEX", queue, 0)
|
29
|
+
|
30
|
+
yield
|
31
|
+
ensure
|
32
|
+
connection.pipelined do |pipeline|
|
33
|
+
pipeline.call("LPOP", queue)
|
34
|
+
pipeline.call("EXPIRE", queue, 10) # keeps the queue fresh when things are moving
|
35
|
+
end
|
36
|
+
|
37
|
+
Thread.current[:connection] = nil
|
34
38
|
end
|
35
39
|
end
|
36
40
|
|
@@ -39,7 +43,7 @@ module Specwrk
|
|
39
43
|
|
40
44
|
@mutex.synchronize do
|
41
45
|
@connection_pools[uri] ||= RedisClient.config(url: uri).new_pool(
|
42
|
-
size: ENV.fetch("SPECWRK_THREAD_COUNT", "4").to_i
|
46
|
+
size: ENV.fetch("SPECWRK_THREAD_COUNT", ENV.fetch("SPECWRK_COUNT", "4")).to_i
|
43
47
|
)
|
44
48
|
end
|
45
49
|
end
|
@@ -47,56 +51,38 @@ module Specwrk
|
|
47
51
|
def reset_connections!
|
48
52
|
@connection_pools.clear
|
49
53
|
end
|
50
|
-
|
51
|
-
private
|
52
|
-
|
53
|
-
# In ms
|
54
|
-
def lock_ttl
|
55
|
-
ENV.fetch("SPECWRK_REDIS_ADAPTER_LOCK_TTL", "5000").to_i
|
56
|
-
end
|
57
|
-
|
58
|
-
# See https://www.rubydoc.info/gems/redlock/Redlock/Client#initialize-instance_method
|
59
|
-
def lock_retry_count
|
60
|
-
ENV.fetch("SPECWRK_REDIS_ADAPTER_LOCK_RETRY_COUNT", "3").to_i
|
61
|
-
end
|
62
|
-
|
63
|
-
def lock_retry_delay
|
64
|
-
ENV.fetch("SPECWRK_REDIS_ADAPTER_LOCK_RETRY_DELAY", "100").to_i
|
65
|
-
end
|
66
|
-
|
67
|
-
def lock_retry_jitter
|
68
|
-
ENV.fetch("SPECWRK_REDIS_ADAPTER_LOCK_RETRY_JITTER", "10").to_i
|
69
|
-
end
|
70
54
|
end
|
71
55
|
|
72
56
|
def [](key)
|
73
57
|
with_connection do |redis|
|
74
|
-
value = redis.call("
|
58
|
+
value = redis.call("HGET", scope, key)
|
75
59
|
JSON.parse(value, symbolize_names: true) if value
|
76
60
|
end
|
77
61
|
end
|
78
62
|
|
79
63
|
def []=(key, value)
|
80
64
|
with_connection do |redis|
|
81
|
-
redis.call("
|
65
|
+
redis.call("HSET", scope, key, JSON.generate(value))
|
82
66
|
end
|
83
67
|
end
|
84
68
|
|
85
69
|
def keys
|
86
|
-
|
87
|
-
|
70
|
+
with_connection do |redis|
|
71
|
+
redis.call("HKEYS", scope)
|
88
72
|
end
|
89
73
|
end
|
90
74
|
|
91
75
|
def clear
|
92
|
-
|
76
|
+
with_connection do |redis|
|
77
|
+
redis.call("DEL", scope)
|
78
|
+
end
|
93
79
|
end
|
94
80
|
|
95
81
|
def delete(*keys)
|
96
82
|
return if keys.length.zero?
|
97
83
|
|
98
84
|
with_connection do |redis|
|
99
|
-
redis.call("
|
85
|
+
redis.call("HDEL", scope, *keys)
|
100
86
|
end
|
101
87
|
end
|
102
88
|
|
@@ -108,7 +94,7 @@ module Specwrk
|
|
108
94
|
return {} if read_keys.length.zero?
|
109
95
|
|
110
96
|
values = with_connection do |redis|
|
111
|
-
redis.call("
|
97
|
+
redis.call("HMGET", scope, *read_keys)
|
112
98
|
end
|
113
99
|
|
114
100
|
result = {}
|
@@ -125,37 +111,24 @@ module Specwrk
|
|
125
111
|
return if hash.nil? || hash.length.zero?
|
126
112
|
|
127
113
|
with_connection do |redis|
|
128
|
-
redis.call("
|
114
|
+
redis.call("HMSET", scope, *hash.flat_map { |key, value| [key, JSON.generate(value)] })
|
129
115
|
end
|
130
116
|
end
|
131
117
|
|
132
118
|
def empty?
|
133
|
-
|
119
|
+
with_connection do |redis|
|
120
|
+
redis.call("HLEN", scope).zero?
|
121
|
+
end
|
134
122
|
end
|
135
123
|
|
136
124
|
private
|
137
125
|
|
138
126
|
def with_connection
|
139
|
-
|
140
|
-
yield connection
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
def encode_key(key)
|
145
|
-
[scope, REDIS_KEY_DELIMITER, key].join
|
146
|
-
end
|
147
|
-
|
148
|
-
def decode_key(key)
|
149
|
-
key.split(REDIS_KEY_DELIMITER).last
|
150
|
-
end
|
151
|
-
|
152
|
-
def scan_for(match)
|
153
|
-
with_connection do |redis|
|
154
|
-
cursor = "0"
|
155
|
-
loop do
|
156
|
-
cursor, batch = redis.call("SCAN", cursor, "MATCH", match, "COUNT", 5_000)
|
157
|
-
batch.each { |k| yield k }
|
158
|
-
break if cursor == "0"
|
127
|
+
if Thread.current[:connection]
|
128
|
+
yield Thread.current[:connection]
|
129
|
+
else
|
130
|
+
self.class.connection_pool_for(uri).with do |connection|
|
131
|
+
yield connection
|
159
132
|
end
|
160
133
|
end
|
161
134
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: specwrk-store-redis_adapter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Westendorf
|
@@ -37,20 +37,6 @@ dependencies:
|
|
37
37
|
- - ">="
|
38
38
|
- !ruby/object:Gem::Version
|
39
39
|
version: '0'
|
40
|
-
- !ruby/object:Gem::Dependency
|
41
|
-
name: redlock
|
42
|
-
requirement: !ruby/object:Gem::Requirement
|
43
|
-
requirements:
|
44
|
-
- - ">="
|
45
|
-
- !ruby/object:Gem::Version
|
46
|
-
version: '0'
|
47
|
-
type: :runtime
|
48
|
-
prerelease: false
|
49
|
-
version_requirements: !ruby/object:Gem::Requirement
|
50
|
-
requirements:
|
51
|
-
- - ">="
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: '0'
|
54
40
|
- !ruby/object:Gem::Dependency
|
55
41
|
name: standard
|
56
42
|
requirement: !ruby/object:Gem::Requirement
|