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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5b53937122c80fdbbb0dc3fc53316b7626e712b582082b50eac68d4bdf75d37f
4
- data.tar.gz: 3d1ea9b242ad223c8e9f4186ef1b88bad5ee50d97bab382de4712ffdc36d355f
3
+ metadata.gz: 626a515c92546cb68ff4378393f6bdf02af48e022c0cb481990eab35cdcdedbd
4
+ data.tar.gz: e4c2a3d80b9585ab9ae554a6cc470b37f66223f374a09876c5e35bddd0c4aa44
5
5
  SHA512:
6
- metadata.gz: 370012160a8f0a0de2b52c820fb6eb02dd51afaad589980dd297396d348aa16c035cf728ebfa5cd0aa8071401ce254ccd05e0bce1de5ea85d098ee42469b01b9
7
- data.tar.gz: 36cff8ca197aab39a0a74e00f9d136497fd210f2a098ef0d885c29b21fdd5bb3d857adc6586ffdce9726c2eec8a792ad757bd9a6afa2508a63b2f534d5e15438
6
+ metadata.gz: 35cdba9ff17f1c868b0968b17d4ccd1c90842d4a06b0c8cae7dd4ea9c9b2726b3480c056ef505ca9fdf3d961d54721015d4d2a667f6f6e3a91c2d5f61bca3ea8
7
+ data.tar.gz: d52567dfc1112d99a91809ef3edb754269ef0cccc4d7988293c3a74e1a333ef33578bac596d5074625ec59a0a405bfffd5c992a4954fe4a2151c751716d29d69
data/docker-compose.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  version: '3'
2
2
  services:
3
3
  redis:
4
- image: redis:4.0
4
+ image: redis:6.0
5
5
  ports:
6
6
  - "0.0.0.0:6379:6379"
@@ -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
- client = Redlock::Client.new(
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
- until (lock = client.lock("specwrk-lock-#{key}", lock_ttl))
30
- sleep(rand(0.001..0.09))
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
- yield.tap { client.unlock(lock) }
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("GET", encode_key(key))
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("SET", encode_key(key), JSON.generate(value))
65
+ redis.call("HSET", scope, key, JSON.generate(value))
82
66
  end
83
67
  end
84
68
 
85
69
  def keys
86
- [].tap do |collected|
87
- scan_for("#{scope}#{REDIS_KEY_DELIMITER}*") { |k| collected << decode_key(k) }
70
+ with_connection do |redis|
71
+ redis.call("HKEYS", scope)
88
72
  end
89
73
  end
90
74
 
91
75
  def clear
92
- delete(*keys)
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("DEL", *keys.map { |key| encode_key key })
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("MGET", *read_keys.map { |key| encode_key(key) })
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("MSET", *hash.flat_map { |key, value| [encode_key(key), JSON.generate(value)] })
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
- keys.length.zero?
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
- self.class.connection_pool_for(uri).with do |connection|
140
- yield connection
141
- end
142
- end
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.3
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