redis-ick 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- 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 ![TravisCI](https://travis-ci.org/ProsperWorks/redis-ick.svg?branch=master)
|
1
|
+
# Redis::Ick An Indexing Queue ![TravisCI](https://travis-ci.org/ProsperWorks/redis-ick.svg?branch=master)
|
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'
|