redis-ick 0.0.3 → 0.0.4
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 +142 -1
- data/.travis.yml +3 -1
- data/Gemfile +1 -1
- data/LICENSE +1 -1
- data/README.md +250 -30
- data/Rakefile +5 -5
- data/bin/console +4 -4
- data/lib/redis/ick.rb +22 -16
- data/lib/redis/ick/version.rb +17 -4
- data/redis-ick.gemspec +11 -9
- metadata +45 -4
- data/.rubocop_todo.yml +0 -296
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 67d1648e28624b1ed5c0a9f475412deb102f2b5b
|
4
|
+
data.tar.gz: 97754295aead271f4748adef41f93eee3e081b11
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 020f83530d8dc2579d4343d32fdceec98dc1575f9137d2e0678ec0484a36fbfad14c3222cc1bddffa3548e8aa20bcffb0dd25b6ffc2b47c90bf76428c7405e70
|
7
|
+
data.tar.gz: e000d81edb08fefa4204c167d0adb3aae8f773892222681de2498e947e41a1af57370c83d3c29e2b5be504b3d2541c69836c8f1dc41b43c5d2301dabd1eb3b81
|
data/.rubocop.yml
CHANGED
@@ -1,6 +1,147 @@
|
|
1
|
-
|
1
|
+
|
2
2
|
AllCops:
|
3
3
|
Include:
|
4
4
|
- Rakefile
|
5
5
|
- Gemfile
|
6
6
|
- '*.gemspec'
|
7
|
+
|
8
|
+
# Broadly speaking, test code gets a pass for most of the Metrics family.
|
9
|
+
#
|
10
|
+
# IMO test code is not the place get pedantic about class length,
|
11
|
+
# method complexity, etc. One should be encouraged to add more tests
|
12
|
+
# with minimal friction, not forced to make a hard choice between
|
13
|
+
# cutting tests or splitting up my test suites.
|
14
|
+
#
|
15
|
+
Metrics/ClassLength:
|
16
|
+
Max: 400
|
17
|
+
Exclude:
|
18
|
+
- 'test/**/*.rb'
|
19
|
+
|
20
|
+
# I like this Metric in principle, but I don't like the default max of
|
21
|
+
# 15.
|
22
|
+
#
|
23
|
+
# Also, as per Metrics/ClassLength IMO this kind of limit should not
|
24
|
+
# apply to test code (I get up to 318 over there).
|
25
|
+
#
|
26
|
+
Metrics/AbcSize:
|
27
|
+
Max: 30
|
28
|
+
Exclude:
|
29
|
+
- 'test/**/*.rb'
|
30
|
+
|
31
|
+
# I like this Metric in principle, but I don't like the default max of
|
32
|
+
# 10.
|
33
|
+
#
|
34
|
+
# Also, as per Metrics/ClassLength IMO this kind of limit should not
|
35
|
+
# apply to test code.
|
36
|
+
#
|
37
|
+
Metrics/MethodLength:
|
38
|
+
Max: 50
|
39
|
+
Exclude:
|
40
|
+
- 'test/**/*.rb'
|
41
|
+
|
42
|
+
# I put extra spaces in a lot of expressions for a lot of different
|
43
|
+
# reasons, including especially readability.
|
44
|
+
#
|
45
|
+
# I reject these cops.
|
46
|
+
#
|
47
|
+
Layout:
|
48
|
+
Enabled: false
|
49
|
+
|
50
|
+
# I like a lot of the Lint tests, but not these.
|
51
|
+
#
|
52
|
+
Lint/AmbiguousBlockAssociation: # obnoxiously rejects idiomatic Ruby
|
53
|
+
Enabled: false
|
54
|
+
|
55
|
+
# Ick#ickreserve returns an Array of Arrays.
|
56
|
+
#
|
57
|
+
# Performance/HashEachMethods complains that:
|
58
|
+
#
|
59
|
+
# ick.ickreserve('key',num).each do |message,score|
|
60
|
+
# ...
|
61
|
+
# end
|
62
|
+
#
|
63
|
+
# would be more efficient as a each_key loop.
|
64
|
+
#
|
65
|
+
# This cop inappropriately requires us to change working code to
|
66
|
+
# broken code. This is a known issue which the authors of Rubocop do
|
67
|
+
# not intend to change:
|
68
|
+
#
|
69
|
+
# https://github.com/bbatsov/rubocop/issues/4732
|
70
|
+
#
|
71
|
+
# My reaction is to blacklist this cop.
|
72
|
+
#
|
73
|
+
Performance/HashEachMethods:
|
74
|
+
Enabled: false
|
75
|
+
|
76
|
+
# This does no more than insist I type "format" instead of "sprintf",
|
77
|
+
# where the two are aliases.
|
78
|
+
#
|
79
|
+
Style/FormatString:
|
80
|
+
Enabled: false
|
81
|
+
|
82
|
+
# There is nothing wrong with Ruby 1.9 Hash syntax.
|
83
|
+
#
|
84
|
+
Style/HashSyntax:
|
85
|
+
Enabled: false
|
86
|
+
|
87
|
+
# No. Indeed, postfix if can often drive a line over 80 columns wide.
|
88
|
+
#
|
89
|
+
Style/IfUnlessModifier:
|
90
|
+
Enabled: false
|
91
|
+
|
92
|
+
# No. There is nothing wrong with "if !foo".
|
93
|
+
#
|
94
|
+
# As far as I'm concerned, "unless" is in poor taste because it means
|
95
|
+
# I have to think in English in two different logical senses - and
|
96
|
+
# English is a poor language for logical senses.
|
97
|
+
#
|
98
|
+
Style/NegatedIf:
|
99
|
+
Enabled: false
|
100
|
+
|
101
|
+
# "Do not use semicolons to terminate expressions."
|
102
|
+
#
|
103
|
+
# That's great when I terminate a single-line expression with a
|
104
|
+
# redundant semicolo because I forget I'm not using C.
|
105
|
+
#
|
106
|
+
# But when I'm using a semicolon to separate two expressions there is
|
107
|
+
# no other choice. So this really ought to be Style/OneExprPerLine,
|
108
|
+
# which I reject.
|
109
|
+
#
|
110
|
+
Style/Semicolon:
|
111
|
+
Enabled: false
|
112
|
+
|
113
|
+
# No.
|
114
|
+
#
|
115
|
+
# Some lines must have '\"'. It is ugly to use a mix of '"' and '\''
|
116
|
+
# in LoCs which are close to one another. Therefore, banning '"' if
|
117
|
+
# '"' is not strictly necessary drives visual inconsistency.
|
118
|
+
#
|
119
|
+
Style/StringLiterals:
|
120
|
+
Enabled: false
|
121
|
+
|
122
|
+
# This is the same kind of obnoxious pedantry which drove Hungarian
|
123
|
+
# Notation.
|
124
|
+
#
|
125
|
+
# The [] literal syntax is perfectly servicable and there is no point
|
126
|
+
# _tightly_ coupling it to the content of the array. That's why we
|
127
|
+
# have context-free grammers!
|
128
|
+
#
|
129
|
+
Style/SymbolArray:
|
130
|
+
Enabled: false
|
131
|
+
|
132
|
+
# Shockingly, this cop requires us to *OMIT*, not *INCLUDE* parens in
|
133
|
+
# ternery conditons.
|
134
|
+
#
|
135
|
+
# IMO this one is actively harmful in that it discourages attention to
|
136
|
+
# clarity and avoiding some nasty precedence surprises.
|
137
|
+
#
|
138
|
+
Style/TernaryParentheses:
|
139
|
+
Enabled: false
|
140
|
+
|
141
|
+
# I am a huge fan of using trailing commas when I break an argument
|
142
|
+
# list down one-per line.
|
143
|
+
#
|
144
|
+
# As such, I reject this test.
|
145
|
+
#
|
146
|
+
Style/TrailingCommaInLiteral:
|
147
|
+
Enabled: false
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -1,45 +1,264 @@
|
|
1
|
-
# Redis::Ick 
|
1
|
+
# Redis::Ick An Indexing Queue 
|
2
2
|
|
3
|
-
Ick
|
3
|
+
Redis::Ick implements a priority queue in Redis which supports:
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
* multiple producers
|
6
|
+
* write-folding
|
7
|
+
* two-phase commit for a single consumer
|
7
8
|
|
8
|
-
|
9
|
+
Ick solves a variety of race condition and starvation issues which can
|
10
|
+
arise between the producers and the consumer.
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
+
Icks are similar to (and built from) Redis sorted sets. They are
|
13
|
+
well-suited for dirty lists in data sync systems.
|
12
14
|
|
13
|
-
Ick
|
14
|
-
|
15
|
-
|
15
|
+
Ick has been live in production at ProsperWorks since 2015-10-21. We
|
16
|
+
use them at the heart of our PG-to-ES and PG-to-Neo4j pipelines, for
|
17
|
+
data migration and repair, and a variety of other crawler systems.
|
16
18
|
|
17
|
-
|
18
|
-
in queue does not increase the size of the queue. It may, or may not,
|
19
|
-
rearrange that member's position within the queue.
|
19
|
+
## Background: The Original Pattern
|
20
20
|
|
21
|
-
Ick
|
22
|
-
|
23
|
-
later committing all, some, or none of them.
|
21
|
+
Long before Ick, our indexer queue was a simple Redis sorted set which
|
22
|
+
used current time for scores. It looked like:
|
24
23
|
|
25
|
-
|
26
|
-
|
24
|
+
# in any process whenever a document is dirtied
|
25
|
+
redis.zadd(queue_key,Time.now.to_f,document_id)
|
27
26
|
|
28
|
-
|
29
|
-
|
27
|
+
# in the indexer process
|
28
|
+
batch = redis.zrangebyrank(queue_key,0,batch_size) # critical section start
|
29
|
+
process_batch_slowly(batch)
|
30
|
+
# burn down the queue only if the batch succeeded
|
31
|
+
redis.zrem(queue_key,*members_of(batch)) # critical section end
|
30
32
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
33
|
+
**Big Advantage**: Failover. Because we defer ZREM until after
|
34
|
+
success, when we fail in process_batch_slowly() (such as via an
|
35
|
+
exception or SIGKILL), all document_ids in the batch are still in
|
36
|
+
Redis. When the indexer process resumes, those document_ids will run
|
37
|
+
again.
|
36
38
|
|
37
|
-
|
38
|
-
|
39
|
-
|
39
|
+
**Big Advantage**: Write Folding. Because we use Redis sorted sets,
|
40
|
+
when a document is dirtied twice in quick succession, we only get 1
|
41
|
+
entry in the queue. We change the timestamp but we do not end up
|
42
|
+
with 2 entries in the queue. Thus, the queue grows only in the number
|
43
|
+
of dirty _documents_ per unit time, not in the number of dirty
|
44
|
+
_operations_ per unit time. In a sense, the more we fall behind the
|
45
|
+
slower we fall.
|
40
46
|
|
41
|
-
|
42
|
-
|
47
|
+
**Big Problem**: The Forgotten Dirtiness Problem. If some document is
|
48
|
+
dirtied a second time after the start of process_batch_slowly(), when
|
49
|
+
process_batch_slowly() end we will drop that document from the queue.
|
50
|
+
Thus, the document will be dirty but no longer in the queue!
|
51
|
+
|
52
|
+
**Small Problem**: The Hot Data Starvation Problem. Because we score
|
53
|
+
by time-of-dirtiness and we use ZRANGEBYRANK starting at 0, each batch
|
54
|
+
is the _coldest_ dirty documents. Most of the time this is a good
|
55
|
+
proxy for what we really care about: the _oldest_ dirty documents.
|
56
|
+
But when a document is re-dirtied, its old timestamp is replaced with
|
57
|
+
a new timestamp. In effect, it jumps from the cold end of the queue
|
58
|
+
to the hot end of the queue. If the queue is big enough that it is
|
59
|
+
always larger than one batch and a document is hot enough that it gets
|
60
|
+
updated in queue more often than our batches, the document will never
|
61
|
+
be popped out into a batch.
|
62
|
+
|
63
|
+
## Background: The Intermediate Pattern
|
64
|
+
|
65
|
+
A year before Ick, August 2014, Gerald made a huge improvement which
|
66
|
+
mostly mitigated the Forgotten Dirtiness Problem:
|
67
|
+
|
68
|
+
# in any process: whenever a document is dirtied
|
69
|
+
redis.zadd(queue_key,Time.now.to_f,document_id)
|
70
|
+
|
71
|
+
# in the indexer process:
|
72
|
+
batch1 = redis.zrangebyrank(queue_key,0,batch_size)
|
73
|
+
process_batch_slowly(batch)
|
74
|
+
# burn down the queue only if the batch succeeded
|
75
|
+
batch2 = redis.zrangebyrank(queue_key,0,batch_size) # critical section start
|
76
|
+
unchanged_keys = batch1.keys - keys_whose_score_changed_in(batch1,batch2)
|
77
|
+
redis.zrem(queue_key,*members_of(unchanged_keys)) # critical section end
|
78
|
+
|
79
|
+
Gerald changed it so a second snapshot of the cold end of the queue is
|
80
|
+
taken after process_batch_slowly(). Only documents whose timestamps
|
81
|
+
did not change between the two snapshots are removed from the queue.
|
82
|
+
|
83
|
+
Notice how the critical section no longer includes
|
84
|
+
process_batch_slowly(). Instead it only spans two Redis ops and some
|
85
|
+
local set arithmetic which.
|
86
|
+
|
87
|
+
The critical section and the Forgotten Dirtiness Problem which it
|
88
|
+
causes is still there, but is much smaller. In practice we have
|
89
|
+
process_batch_slowly() taking minutes, but even in extreme situations
|
90
|
+
this critical section never took more than 3 seconds.
|
91
|
+
|
92
|
+
## Proposal: The Ick Pattern
|
93
|
+
|
94
|
+
In October 2015, while reviewing the Forgotten Dirtiness problem, we
|
95
|
+
identified the Hot Data Starvation Problem. We developed Ick and
|
96
|
+
switched to this almost familiar pattern:
|
97
|
+
|
98
|
+
# in any process: whenever a document is dirtied
|
99
|
+
Ick.ickadd(redis,queue_key,Time.now.to_f,document_id)
|
100
|
+
|
101
|
+
# in the indexer process:
|
102
|
+
batch = Ick.ickreserve(redis,queue_key,batch_size)
|
103
|
+
process_batch_slowly(batch)
|
104
|
+
# burn down the queue only if the batch succeeded
|
105
|
+
Ick.ickcommit(redis,queue_key,*members_of(batch)) # critical section gone
|
106
|
+
|
107
|
+
|
108
|
+
Ick solves for failover via a two phase commit protocol between
|
109
|
+
**ickreserve** and **ickcommit**. If there is a failure during
|
110
|
+
process_batch_slowly(batch), the next time time we call **ickreserve**
|
111
|
+
we will just get the same batch - it will have resided unchanged in
|
112
|
+
the consumer set until we get happy and call **ickcommit**.
|
113
|
+
|
114
|
+
Ick solves the Forgotten Dirtiness Problem by virtue of
|
115
|
+
**ickreserve**’s implicit atomicity and the fact that **ickcommit** is
|
116
|
+
only ever called from the indexer and producers do not mutate the
|
117
|
+
consumer set.
|
118
|
+
|
119
|
+
Ick solves the Hot Data Starvation Problem by a subtle change in
|
120
|
+
ICKADD. Unlike ZADD, which overwrites the old score when a message is
|
121
|
+
re-added, or ZADD NX which always preserves the old score, ICKADD
|
122
|
+
always takes the _min_ of the old and new scores. Thus, Ick tracks
|
123
|
+
the first-known ditry time for a message even when there is time skew
|
124
|
+
in the producers. The longer entries stay in the consumer set, the
|
125
|
+
more they implicitly percolate toward the cold end regardless of how
|
126
|
+
many updates they receive. Ditto in the consumer set. Provided that
|
127
|
+
all producers make a best effort to use only current or future
|
128
|
+
timestamps when they call ICKADD, the ICKRESERVE batch will always
|
129
|
+
include the oldest entries and there will be no starvation.
|
130
|
+
|
131
|
+
Apology: I know that [Two-Phase
|
132
|
+
Commit](https://en.wikipedia.org/wiki/Two-phase_commit_protocol) has a
|
133
|
+
different technical meaning than what Ick does. Unfortunately I can't
|
134
|
+
find a better name for this very common failsafe queue pattern. I
|
135
|
+
suppose we could think of the Redis sorted set as the coordinator and
|
136
|
+
the consumer process as the (single) participant node and, generously,
|
137
|
+
Two-Phase Commit might be taken to describe Ick.
|
138
|
+
|
139
|
+
|
140
|
+
## What is Ick?
|
141
|
+
|
142
|
+
An Ick is a collection of three Redis keys which all live on the same
|
143
|
+
[Redis hash slot](https://redis.io/topics/cluster-spec):
|
144
|
+
|
145
|
+
* version flag, a string
|
146
|
+
* producer set, a sorted set into which we flag keys as dirty with timestamps
|
147
|
+
* consumer set, a sorted set from which the indexer pulls batches to index
|
148
|
+
|
149
|
+
### Ick defines 5 operations on this data via Lua on Redis:
|
150
|
+
|
151
|
+
* **ickdel**: removes all keys associated with a given Ick structure
|
152
|
+
* **ickstats**: returns a hash of stats including version and size
|
153
|
+
* **ickadd**: add a batch of members with scores to the producer set
|
154
|
+
* implements write-folding: a message can only appear once in the producer set
|
155
|
+
* when a member is re-added, it takes the lowest of 2 scores
|
156
|
+
* **ickreserve**: moves members from the producer set to the consumer
|
157
|
+
set until the consumer set is size N or the producer set is empty
|
158
|
+
* implements write-folding: a message can only appear once in the consumer set
|
159
|
+
* when a member-is re-added it takes the lowest of 2 scores
|
160
|
+
* returns the results as an array
|
161
|
+
* **ickcommit**: deletes members from the consumer set
|
162
|
+
|
163
|
+
Reminder: With few exceptions, all Redis commands are atomic and
|
164
|
+
transactional. This includes any Lua scripts such as those which
|
165
|
+
implement Ick. This atomicity guarantee is important to the
|
166
|
+
correctness of Ick, but because it is inherent in Redis/Lua, does not
|
167
|
+
appear explicitly in any of the Ick sources.
|
168
|
+
|
169
|
+
## Fabulous Diagram
|
170
|
+
|
171
|
+
Here is a coarse dataflow for members moving through an Ick.
|
172
|
+
|
173
|
+
app
|
174
|
+
|
|
175
|
+
+-- **ickadd** --> producer set
|
176
|
+
|
|
177
|
+
+-- **ickreserve** --> consumer set
|
178
|
+
|
|
179
|
+
+-- **ickcommit** --> forgotten
|
180
|
+
|
181
|
+
## Miscellanea
|
182
|
+
|
183
|
+
### Ready for Redis Cluster
|
184
|
+
|
185
|
+
Even though one Ick uses three Redis keys, Ick is compatible with
|
186
|
+
Redis Cluster. At ProsperWorks we use it with RedisLabs Enterprise
|
187
|
+
Cluster.
|
188
|
+
|
189
|
+
Ick does some very tricky things to compute the producer set and
|
190
|
+
consumer set keys from the master key in a way which puts them all on
|
191
|
+
the same slot in both Redis Cluster and with RLEC's default
|
192
|
+
prescriptive hashing algorithm.
|
193
|
+
|
194
|
+
See [redis-key_hash](https://github.com/ProsperWorks/redis-key_hash)
|
195
|
+
for how test this.
|
196
|
+
|
197
|
+
### Scalability
|
198
|
+
|
199
|
+
Ick supports only a single consumer: there is only one consumer set.
|
200
|
+
|
201
|
+
If your application need more than one consumer for throughput or
|
202
|
+
other reasons, you should shard across multiple Icks, each with one
|
203
|
+
consumer loop each.
|
204
|
+
|
205
|
+
This is exactly how we use Icks at ProsperWorks. Our application code
|
206
|
+
does not simply push to an individual Ick. We push to a bit of code
|
207
|
+
which knows that one "channel" is really N Icks. To select an Ick,
|
208
|
+
that code does a stable hash of our document_ids, modulo N.
|
209
|
+
|
210
|
+
This way, each Ick is able to dedupe across only its dedicated subset
|
211
|
+
of all messages.
|
212
|
+
|
213
|
+
We considered a more complicated Ick which supported multiple
|
214
|
+
consumers, but a lot of new problems come up once we take that step:
|
215
|
+
can one message be in multiple consumer sets? If not, what happens
|
216
|
+
when one consumer halts? How do we prevent the cold end of the
|
217
|
+
producer set from getting clogged up with messages destined for the
|
218
|
+
idle consumer?
|
219
|
+
|
220
|
+
We prefer handling those issues in higher-level code. Thus, Ick by
|
221
|
+
itself does not attempt to solve scalability.
|
222
|
+
|
223
|
+
|
224
|
+
### Some Surprises Which Can Be Gotchas in Test
|
225
|
+
|
226
|
+
Because ICKADD uses write-folding semantics over the producer set,
|
227
|
+
ICKADD might or might not grow the total size of the queue.
|
228
|
+
|
229
|
+
ICKRESERVE is not a read-only operation. It can mutate both the
|
230
|
+
producer set and the consumer set. Because ICKRESERVE uses
|
231
|
+
write-folding semantics between the producer set and the consumer set,
|
232
|
+
ICKRESERVE(N) might:
|
233
|
+
|
234
|
+
* shrink the producer set by N and grow the consumer set by N
|
235
|
+
* shrink the producer set by 0 and grow the consumer set by 0
|
236
|
+
* shrink the producer set by N and grow the consumer set by 0
|
237
|
+
* or anything in between
|
238
|
+
|
239
|
+
Because Ick always uses the min when multiple scores are present for
|
240
|
+
one message, ICKADD can rearrange the order of the producer set and
|
241
|
+
ICKRESERVE can rearrange the order of the consumer set in surprising
|
242
|
+
ways.
|
243
|
+
|
244
|
+
ICKADD write-folds in the producer set but not in the consumer set.
|
245
|
+
Thus, one message can appear in both the producer set and the consumer
|
246
|
+
set. At first this seems wrong and inefficient, but in fact it is a
|
247
|
+
desirable property. When a message is in both sets, it means it was
|
248
|
+
included in a batch by ICKRESERVE, then added by ICKADD, but has yet
|
249
|
+
to be ICKCOMMITed. The interpretation for this is that the consumer
|
250
|
+
is actively engaged in updating the downstream systems. But that
|
251
|
+
means, at the Ick it is indeterminate whether the message is still
|
252
|
+
dirty or has been cleaned. That is, being in both queues corresponds
|
253
|
+
exactly to a message being in the critical section where a race
|
254
|
+
condition is possible. Thus, we _want_ it to still be dirty and to
|
255
|
+
appear in a future batch.
|
256
|
+
|
257
|
+
None of these surprises is a bug in Ick: they are all consistent with
|
258
|
+
the design and the intent. But they are surprises nonetheless and can
|
259
|
+
(and have) led to bugs in code which makes an unwarranted assumption.
|
260
|
+
|
261
|
+
## Installation
|
43
262
|
|
44
263
|
```ruby
|
45
264
|
gem 'redis-ick'
|
@@ -67,6 +286,7 @@ Usage example for producers:
|
|
67
286
|
ick = Ick.new(redis)
|
68
287
|
ick.ickadd("mykey",12.8,"foo")
|
69
288
|
ick.ickadd("mykey",123.4,"baz")
|
289
|
+
ick.ickadd("mykey",Time.now.to_f,"bang") # Time.now recommended for scores
|
70
290
|
|
71
291
|
Usage example for consumer:
|
72
292
|
|
data/Rakefile
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rake/testtask'
|
3
3
|
|
4
4
|
Rake::TestTask.new(:test) do |t|
|
5
|
-
t.libs <<
|
6
|
-
t.libs <<
|
7
|
-
t.test_files = FileList[
|
5
|
+
t.libs << 'test'
|
6
|
+
t.libs << 'lib'
|
7
|
+
t.test_files = FileList['test/**/*_test.rb']
|
8
8
|
end
|
9
9
|
|
10
10
|
task :default => :test
|
data/bin/console
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'redis/ick'
|
5
5
|
|
6
6
|
# You can add fixtures and/or initialization code here to make experimenting
|
7
7
|
# with your gem easier. You can also use a different console, if you like.
|
8
8
|
|
9
9
|
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
-
# require
|
10
|
+
# require 'pry'
|
11
11
|
# Pry.start
|
12
12
|
|
13
|
-
require
|
13
|
+
require 'irb'
|
14
14
|
IRB.start(__FILE__)
|
data/lib/redis/ick.rb
CHANGED
@@ -2,9 +2,11 @@ require 'redis/ick/version'
|
|
2
2
|
require 'redis/script_manager'
|
3
3
|
|
4
4
|
class Redis
|
5
|
+
|
6
|
+
# Binds Lua code to provide the Ick operations in Redis.
|
7
|
+
#
|
5
8
|
class Ick
|
6
9
|
|
7
|
-
# TODO: rubocop
|
8
10
|
# TODO: rdoc
|
9
11
|
|
10
12
|
# Creates an Ick accessor.
|
@@ -18,14 +20,16 @@ class Redis
|
|
18
20
|
if !redis.is_a?(Redis)
|
19
21
|
raise ArgumentError, "not a Redis: #{redis}"
|
20
22
|
end
|
21
|
-
if statsd
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
23
|
+
if statsd
|
24
|
+
if !statsd.respond_to?(:increment)
|
25
|
+
raise ArgumentError, 'no statsd.increment'
|
26
|
+
end
|
27
|
+
if !statsd.respond_to?(:timing)
|
28
|
+
raise ArgumentError, 'no statsd.timeing'
|
29
|
+
end
|
30
|
+
if !statsd.respond_to?(:time)
|
31
|
+
raise ArgumentError, 'no statsd.time'
|
32
|
+
end
|
29
33
|
end
|
30
34
|
@redis = redis
|
31
35
|
@statsd = statsd
|
@@ -61,10 +65,10 @@ class Redis
|
|
61
65
|
def _statsd_time(metric)
|
62
66
|
if statsd
|
63
67
|
statsd.time(metric) do
|
64
|
-
|
68
|
+
block_given? ? yield : nil
|
65
69
|
end
|
66
70
|
else
|
67
|
-
|
71
|
+
block_given? ? yield : nil
|
68
72
|
end
|
69
73
|
end
|
70
74
|
|
@@ -258,16 +262,16 @@ class Redis
|
|
258
262
|
class << raw_ickreserve_results
|
259
263
|
alias_method :original_value, :value
|
260
264
|
def value
|
261
|
-
original_value.each_slice(2).map
|
265
|
+
original_value.each_slice(2).map do |p|
|
262
266
|
[ p[0], ::Redis::Ick._floatify(p[1]) ]
|
263
|
-
|
267
|
+
end
|
264
268
|
end
|
265
269
|
end
|
266
270
|
raw_ickreserve_results
|
267
271
|
else
|
268
|
-
results = raw_ickreserve_results.each_slice(2).map
|
272
|
+
results = raw_ickreserve_results.each_slice(2).map do |p|
|
269
273
|
[ p[0], ::Redis::Ick._floatify(p[1]) ]
|
270
|
-
|
274
|
+
end
|
271
275
|
_statsd_timing('profile.ick.ickreserve.num_results',results.size)
|
272
276
|
results
|
273
277
|
end
|
@@ -472,6 +476,7 @@ class Redis
|
|
472
476
|
local ick_cset_size = redis.call('ZCARD',ick_cset_key)
|
473
477
|
local ick_stats = {
|
474
478
|
'key', ick_key,
|
479
|
+
'keys', { ick_key, ick_pset_key, ick_cset_key },
|
475
480
|
'ver', ick_ver,
|
476
481
|
'cset_size', ick_cset_size,
|
477
482
|
'pset_size', ick_pset_size,
|
@@ -588,7 +593,8 @@ class Redis
|
|
588
593
|
if ick_cset_size and target_cset_size <= ick_cset_size then
|
589
594
|
break
|
590
595
|
end
|
591
|
-
local first_in_pset =
|
596
|
+
local first_in_pset =
|
597
|
+
redis.call('ZRANGE',ick_pset_key,0,0,'WITHSCORES')
|
592
598
|
if 0 == table.getn(first_in_pset) then
|
593
599
|
break
|
594
600
|
end
|
data/lib/redis/ick/version.rb
CHANGED
@@ -7,15 +7,28 @@ class Redis
|
|
7
7
|
#
|
8
8
|
# 0.0.2 - Broke out into Prosperworks/redis-ick, make public.
|
9
9
|
#
|
10
|
-
# 0.0.3 - Got .travis.yml working with a live redis-server
|
11
|
-
#
|
12
|
-
#
|
10
|
+
# 0.0.3 - Got .travis.yml working with a live redis-server.
|
11
|
+
#
|
12
|
+
# Runtime dependency on redis-script_manager for
|
13
|
+
# Ick._eval.
|
14
|
+
#
|
15
|
+
# Initial Rubocop integration.
|
16
|
+
#
|
17
|
+
# Misc cleanup.
|
18
|
+
#
|
19
|
+
# 0.0.4 - Imported text from original design doc to README.md, polish.
|
20
|
+
#
|
21
|
+
# Rubocop polish and defiance.
|
22
|
+
#
|
23
|
+
# Development dependency on redis-key_hash to test
|
24
|
+
# prescriptive hash claims. Identified limits of
|
25
|
+
# prescriptive hash robustness.
|
13
26
|
#
|
14
27
|
# 0.1.0 - (future) Big README.md and Rdoc update, solicit feedback
|
15
28
|
# from select external beta users.
|
16
29
|
#
|
17
30
|
# 0.2.0 - (future) Incorporate feedback, announce.
|
18
31
|
#
|
19
|
-
VERSION = '0.0.
|
32
|
+
VERSION = '0.0.4'.freeze
|
20
33
|
end
|
21
34
|
end
|
data/redis-ick.gemspec
CHANGED
@@ -1,16 +1,15 @@
|
|
1
|
-
|
2
|
-
lib = File.expand_path("../lib", __FILE__)
|
1
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require
|
3
|
+
require 'redis/ick/version'
|
5
4
|
|
6
5
|
Gem::Specification.new do |spec|
|
7
6
|
|
8
|
-
spec.name =
|
7
|
+
spec.name = 'redis-ick'
|
9
8
|
spec.version = Redis::Ick::VERSION
|
10
9
|
spec.platform = Gem::Platform::RUBY
|
11
10
|
|
12
|
-
spec.authors = [
|
13
|
-
spec.email = [
|
11
|
+
spec.authors = ['jhwillett']
|
12
|
+
spec.email = ['jhw@prosperworks.com']
|
14
13
|
|
15
14
|
spec.summary = 'Redis queues with two-phase commit and write-folding.'
|
16
15
|
spec.homepage = 'https://github.com/ProsperWorks/redis-ick'
|
@@ -18,15 +17,18 @@ Gem::Specification.new do |spec|
|
|
18
17
|
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
19
18
|
f.match(%r{^(test|spec|features)/})
|
20
19
|
end
|
21
|
-
spec.bindir =
|
20
|
+
spec.bindir = 'exe'
|
22
21
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
23
|
-
spec.require_paths = [
|
22
|
+
spec.require_paths = ['lib']
|
24
23
|
|
25
24
|
spec.add_development_dependency 'bundler', '~> 1.14'
|
26
25
|
spec.add_development_dependency 'rake', '~> 10.0'
|
27
26
|
spec.add_development_dependency 'minitest', '~> 5.0'
|
28
|
-
spec.add_development_dependency 'redis',
|
27
|
+
spec.add_development_dependency 'redis-key_hash', '~> 0.0.4'
|
28
|
+
spec.add_development_dependency 'redis-namespace', '~> 1.5'
|
29
|
+
spec.add_development_dependency 'rubocop', '~> 0.50.0'
|
29
30
|
|
31
|
+
spec.add_dependency 'redis', '~> 3.2'
|
30
32
|
spec.add_runtime_dependency 'redis-script_manager', '~> 0.0.2'
|
31
33
|
|
32
34
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redis-ick
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- jhwillett
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-09-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -52,6 +52,48 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '5.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: redis-key_hash
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.0.4
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.0.4
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: redis-namespace
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.5'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.5'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rubocop
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 0.50.0
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 0.50.0
|
55
97
|
- !ruby/object:Gem::Dependency
|
56
98
|
name: redis
|
57
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -59,7 +101,7 @@ dependencies:
|
|
59
101
|
- - "~>"
|
60
102
|
- !ruby/object:Gem::Version
|
61
103
|
version: '3.2'
|
62
|
-
type: :
|
104
|
+
type: :runtime
|
63
105
|
prerelease: false
|
64
106
|
version_requirements: !ruby/object:Gem::Requirement
|
65
107
|
requirements:
|
@@ -89,7 +131,6 @@ extra_rdoc_files: []
|
|
89
131
|
files:
|
90
132
|
- ".gitignore"
|
91
133
|
- ".rubocop.yml"
|
92
|
-
- ".rubocop_todo.yml"
|
93
134
|
- ".travis.yml"
|
94
135
|
- Gemfile
|
95
136
|
- LICENSE
|
data/.rubocop_todo.yml
DELETED
@@ -1,296 +0,0 @@
|
|
1
|
-
# This configuration was generated by
|
2
|
-
# `rubocop --auto-gen-config`
|
3
|
-
# on 2017-08-29 15:15:59 -0700 using RuboCop version 0.49.1.
|
4
|
-
# The point is for the user to remove these configuration records
|
5
|
-
# one by one as the offenses are removed from the code base.
|
6
|
-
# Note that changes in the inspected code, or installation of new
|
7
|
-
# versions of RuboCop, may require this file to be generated again.
|
8
|
-
|
9
|
-
# Offense count: 1
|
10
|
-
# Cop supports --auto-correct.
|
11
|
-
Layout/EmptyLineAfterMagicComment:
|
12
|
-
Exclude:
|
13
|
-
- 'redis-ick.gemspec'
|
14
|
-
|
15
|
-
# Offense count: 6
|
16
|
-
# Cop supports --auto-correct.
|
17
|
-
# Configuration parameters: AllowAdjacentOneLineDefs, NumberOfEmptyLines.
|
18
|
-
Layout/EmptyLineBetweenDefs:
|
19
|
-
Exclude:
|
20
|
-
- 'test/redis/ick_test.rb'
|
21
|
-
|
22
|
-
# Offense count: 1
|
23
|
-
# Cop supports --auto-correct.
|
24
|
-
Layout/EmptyLines:
|
25
|
-
Exclude:
|
26
|
-
- 'lib/redis/ick.rb'
|
27
|
-
|
28
|
-
# Offense count: 2
|
29
|
-
# Cop supports --auto-correct.
|
30
|
-
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
31
|
-
# SupportedStyles: empty_lines, no_empty_lines
|
32
|
-
Layout/EmptyLinesAroundBlockBody:
|
33
|
-
Exclude:
|
34
|
-
- 'redis-ick.gemspec'
|
35
|
-
|
36
|
-
# Offense count: 4
|
37
|
-
# Cop supports --auto-correct.
|
38
|
-
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
39
|
-
# SupportedStyles: empty_lines, empty_lines_except_namespace, empty_lines_special, no_empty_lines
|
40
|
-
Layout/EmptyLinesAroundClassBody:
|
41
|
-
Exclude:
|
42
|
-
- 'lib/redis/ick.rb'
|
43
|
-
- 'test/redis/ick_test.rb'
|
44
|
-
|
45
|
-
# Offense count: 15
|
46
|
-
# Cop supports --auto-correct.
|
47
|
-
# Configuration parameters: AllowForAlignment, ForceEqualSignAlignment.
|
48
|
-
Layout/ExtraSpacing:
|
49
|
-
Exclude:
|
50
|
-
- 'test/redis/ick_test.rb'
|
51
|
-
|
52
|
-
# Offense count: 1
|
53
|
-
# Cop supports --auto-correct.
|
54
|
-
Layout/LeadingCommentSpace:
|
55
|
-
Exclude:
|
56
|
-
- 'test/redis/ick_test.rb'
|
57
|
-
|
58
|
-
# Offense count: 276
|
59
|
-
# Cop supports --auto-correct.
|
60
|
-
Layout/SpaceAfterComma:
|
61
|
-
Exclude:
|
62
|
-
- 'lib/redis/ick.rb'
|
63
|
-
- 'test/redis/ick_test.rb'
|
64
|
-
|
65
|
-
# Offense count: 2
|
66
|
-
# Cop supports --auto-correct.
|
67
|
-
Layout/SpaceAfterNot:
|
68
|
-
Exclude:
|
69
|
-
- 'lib/redis/ick.rb'
|
70
|
-
|
71
|
-
# Offense count: 1
|
72
|
-
# Cop supports --auto-correct.
|
73
|
-
# Configuration parameters: EnforcedStyleInsidePipes, SupportedStylesInsidePipes.
|
74
|
-
# SupportedStylesInsidePipes: space, no_space
|
75
|
-
Layout/SpaceAroundBlockParameters:
|
76
|
-
Exclude:
|
77
|
-
- 'lib/redis/ick.rb'
|
78
|
-
|
79
|
-
# Offense count: 1
|
80
|
-
# Cop supports --auto-correct.
|
81
|
-
# Configuration parameters: SupportedStyles.
|
82
|
-
# SupportedStyles: space, no_space
|
83
|
-
Layout/SpaceAroundEqualsInParameterDefault:
|
84
|
-
EnforcedStyle: no_space
|
85
|
-
|
86
|
-
# Offense count: 5
|
87
|
-
# Cop supports --auto-correct.
|
88
|
-
# Configuration parameters: AllowForAlignment.
|
89
|
-
Layout/SpaceAroundOperators:
|
90
|
-
Exclude:
|
91
|
-
- 'test/redis/ick_test.rb'
|
92
|
-
|
93
|
-
# Offense count: 2
|
94
|
-
# Cop supports --auto-correct.
|
95
|
-
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
96
|
-
# SupportedStyles: space, no_space
|
97
|
-
Layout/SpaceBeforeBlockBraces:
|
98
|
-
Exclude:
|
99
|
-
- 'lib/redis/ick.rb'
|
100
|
-
- 'test/redis/ick_test.rb'
|
101
|
-
|
102
|
-
# Offense count: 4
|
103
|
-
# Cop supports --auto-correct.
|
104
|
-
# Configuration parameters: AllowForAlignment.
|
105
|
-
Layout/SpaceBeforeFirstArg:
|
106
|
-
Exclude:
|
107
|
-
- 'test/redis/ick_test.rb'
|
108
|
-
|
109
|
-
# Offense count: 4
|
110
|
-
# Cop supports --auto-correct.
|
111
|
-
# Configuration parameters: EnforcedStyle, SupportedStyles, EnforcedStyleForEmptyBraces, SupportedStylesForEmptyBraces, SpaceBeforeBlockParameters.
|
112
|
-
# SupportedStyles: space, no_space
|
113
|
-
# SupportedStylesForEmptyBraces: space, no_space
|
114
|
-
Layout/SpaceInsideBlockBraces:
|
115
|
-
Exclude:
|
116
|
-
- 'Gemfile'
|
117
|
-
- 'lib/redis/ick.rb'
|
118
|
-
- 'test/redis/ick_test.rb'
|
119
|
-
|
120
|
-
# Offense count: 10
|
121
|
-
# Cop supports --auto-correct.
|
122
|
-
Layout/SpaceInsideBrackets:
|
123
|
-
Exclude:
|
124
|
-
- 'lib/redis/ick.rb'
|
125
|
-
- 'test/redis/ick_test.rb'
|
126
|
-
|
127
|
-
# Offense count: 1
|
128
|
-
Lint/AmbiguousBlockAssociation:
|
129
|
-
Exclude:
|
130
|
-
- 'test/redis/ick_test.rb'
|
131
|
-
|
132
|
-
# Offense count: 18
|
133
|
-
Metrics/AbcSize:
|
134
|
-
Max: 318
|
135
|
-
|
136
|
-
# Offense count: 2
|
137
|
-
# Configuration parameters: CountComments.
|
138
|
-
Metrics/ClassLength:
|
139
|
-
Max: 609
|
140
|
-
|
141
|
-
# Offense count: 1
|
142
|
-
Metrics/CyclomaticComplexity:
|
143
|
-
Max: 8
|
144
|
-
|
145
|
-
# Offense count: 3
|
146
|
-
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
|
147
|
-
# URISchemes: http, https
|
148
|
-
Metrics/LineLength:
|
149
|
-
Max: 81
|
150
|
-
|
151
|
-
# Offense count: 19
|
152
|
-
# Configuration parameters: CountComments.
|
153
|
-
Metrics/MethodLength:
|
154
|
-
Max: 175
|
155
|
-
|
156
|
-
# Offense count: 1
|
157
|
-
Metrics/PerceivedComplexity:
|
158
|
-
Max: 8
|
159
|
-
|
160
|
-
# Offense count: 1
|
161
|
-
# Cop supports --auto-correct.
|
162
|
-
Performance/TimesMap:
|
163
|
-
Exclude:
|
164
|
-
- 'test/redis/ick_test.rb'
|
165
|
-
|
166
|
-
# Offense count: 2
|
167
|
-
# Cop supports --auto-correct.
|
168
|
-
# Configuration parameters: EnforcedStyle, SupportedStyles, ProceduralMethods, FunctionalMethods, IgnoredMethods.
|
169
|
-
# SupportedStyles: line_count_based, semantic, braces_for_chaining
|
170
|
-
# ProceduralMethods: benchmark, bm, bmbm, create, each_with_object, measure, new, realtime, tap, with_object
|
171
|
-
# FunctionalMethods: let, let!, subject, watch
|
172
|
-
# IgnoredMethods: lambda, proc, it
|
173
|
-
Style/BlockDelimiters:
|
174
|
-
Exclude:
|
175
|
-
- 'lib/redis/ick.rb'
|
176
|
-
|
177
|
-
# Offense count: 1
|
178
|
-
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
179
|
-
# SupportedStyles: nested, compact
|
180
|
-
Style/ClassAndModuleChildren:
|
181
|
-
Exclude:
|
182
|
-
- 'test/redis/ick_test.rb'
|
183
|
-
|
184
|
-
# Offense count: 2
|
185
|
-
Style/ClassVars:
|
186
|
-
Exclude:
|
187
|
-
- 'test/redis/ick_test.rb'
|
188
|
-
|
189
|
-
# Offense count: 1
|
190
|
-
Style/Documentation:
|
191
|
-
Exclude:
|
192
|
-
- 'spec/**/*'
|
193
|
-
- 'test/**/*'
|
194
|
-
- 'lib/redis/ick.rb'
|
195
|
-
|
196
|
-
# Offense count: 1
|
197
|
-
# Cop supports --auto-correct.
|
198
|
-
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
199
|
-
# SupportedStyles: format, sprintf, percent
|
200
|
-
Style/FormatString:
|
201
|
-
Exclude:
|
202
|
-
- 'test/redis/ick_test.rb'
|
203
|
-
|
204
|
-
# Offense count: 1
|
205
|
-
# Configuration parameters: MinBodyLength.
|
206
|
-
Style/GuardClause:
|
207
|
-
Exclude:
|
208
|
-
- 'lib/redis/ick.rb'
|
209
|
-
|
210
|
-
# Offense count: 3
|
211
|
-
# Cop supports --auto-correct.
|
212
|
-
# Configuration parameters: EnforcedStyle, SupportedStyles, UseHashRocketsWithSymbolValues, PreferHashRocketsForNonAlnumEndingSymbols.
|
213
|
-
# SupportedStyles: ruby19, hash_rockets, no_mixed_keys, ruby19_no_mixed_keys
|
214
|
-
Style/HashSyntax:
|
215
|
-
Exclude:
|
216
|
-
- 'Rakefile'
|
217
|
-
- 'test/redis/ick_test.rb'
|
218
|
-
|
219
|
-
# Offense count: 3
|
220
|
-
# Cop supports --auto-correct.
|
221
|
-
# Configuration parameters: MaxLineLength.
|
222
|
-
Style/IfUnlessModifier:
|
223
|
-
Exclude:
|
224
|
-
- 'lib/redis/ick.rb'
|
225
|
-
|
226
|
-
# Offense count: 6
|
227
|
-
# Configuration parameters: SupportedStyles.
|
228
|
-
# SupportedStyles: snake_case, camelCase
|
229
|
-
Style/MethodName:
|
230
|
-
EnforcedStyle: snake_case
|
231
|
-
|
232
|
-
# Offense count: 1
|
233
|
-
# Cop supports --auto-correct.
|
234
|
-
Style/MutableConstant:
|
235
|
-
Exclude:
|
236
|
-
- 'lib/redis/ick/version.rb'
|
237
|
-
|
238
|
-
# Offense count: 15
|
239
|
-
# Cop supports --auto-correct.
|
240
|
-
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
241
|
-
# SupportedStyles: both, prefix, postfix
|
242
|
-
Style/NegatedIf:
|
243
|
-
Exclude:
|
244
|
-
- 'lib/redis/ick.rb'
|
245
|
-
- 'test/redis/ick_test.rb'
|
246
|
-
|
247
|
-
# Offense count: 1
|
248
|
-
# Cop supports --auto-correct.
|
249
|
-
# Configuration parameters: AllowMultipleReturnValues.
|
250
|
-
Style/RedundantReturn:
|
251
|
-
Exclude:
|
252
|
-
- 'lib/redis/ick.rb'
|
253
|
-
|
254
|
-
# Offense count: 1
|
255
|
-
# Cop supports --auto-correct.
|
256
|
-
# Configuration parameters: AllowAsExpressionSeparator.
|
257
|
-
Style/Semicolon:
|
258
|
-
Exclude:
|
259
|
-
- 'test/redis/ick_test.rb'
|
260
|
-
|
261
|
-
# Offense count: 28
|
262
|
-
# Cop supports --auto-correct.
|
263
|
-
# Configuration parameters: EnforcedStyle, SupportedStyles, ConsistentQuotesInMultiline.
|
264
|
-
# SupportedStyles: single_quotes, double_quotes
|
265
|
-
Style/StringLiterals:
|
266
|
-
Exclude:
|
267
|
-
- 'Gemfile'
|
268
|
-
- 'Rakefile'
|
269
|
-
- 'bin/console'
|
270
|
-
- 'lib/redis/ick.rb'
|
271
|
-
- 'redis-ick.gemspec'
|
272
|
-
- 'test/redis/ick_test.rb'
|
273
|
-
- 'test/test_helper.rb'
|
274
|
-
|
275
|
-
# Offense count: 1
|
276
|
-
# Cop supports --auto-correct.
|
277
|
-
# Configuration parameters: MinSize, SupportedStyles.
|
278
|
-
# SupportedStyles: percent, brackets
|
279
|
-
Style/SymbolArray:
|
280
|
-
EnforcedStyle: brackets
|
281
|
-
|
282
|
-
# Offense count: 1
|
283
|
-
# Cop supports --auto-correct.
|
284
|
-
# Configuration parameters: EnforcedStyle, SupportedStyles, AllowSafeAssignment.
|
285
|
-
# SupportedStyles: require_parentheses, require_no_parentheses, require_parentheses_when_complex
|
286
|
-
Style/TernaryParentheses:
|
287
|
-
Exclude:
|
288
|
-
- 'lib/redis/ick.rb'
|
289
|
-
|
290
|
-
# Offense count: 11
|
291
|
-
# Cop supports --auto-correct.
|
292
|
-
# Configuration parameters: EnforcedStyleForMultiline, SupportedStylesForMultiline.
|
293
|
-
# SupportedStylesForMultiline: comma, consistent_comma, no_comma
|
294
|
-
Style/TrailingCommaInLiteral:
|
295
|
-
Exclude:
|
296
|
-
- 'test/redis/ick_test.rb'
|