krakow 0.2.2 → 0.3.0
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.
- data/CHANGELOG.md +16 -0
- data/CONTRIBUTING.md +25 -0
- data/LICENSE +13 -0
- data/README.md +62 -9
- data/krakow.gemspec +3 -1
- data/lib/krakow/command/cls.rb +3 -4
- data/lib/krakow/command/fin.rb +13 -4
- data/lib/krakow/command/identify.rb +22 -9
- data/lib/krakow/command/mpub.rb +14 -4
- data/lib/krakow/command/nop.rb +3 -4
- data/lib/krakow/command/pub.rb +15 -5
- data/lib/krakow/command/rdy.rb +13 -4
- data/lib/krakow/command/req.rb +14 -4
- data/lib/krakow/command/sub.rb +14 -4
- data/lib/krakow/command/touch.rb +13 -4
- data/lib/krakow/command.rb +25 -3
- data/lib/krakow/connection.rb +286 -60
- data/lib/krakow/connection_features/deflate.rb +26 -1
- data/lib/krakow/connection_features/snappy_frames.rb +34 -3
- data/lib/krakow/connection_features/ssl.rb +43 -1
- data/lib/krakow/connection_features.rb +1 -0
- data/lib/krakow/consumer.rb +162 -49
- data/lib/krakow/discovery.rb +17 -6
- data/lib/krakow/distribution/default.rb +61 -33
- data/lib/krakow/distribution.rb +107 -57
- data/lib/krakow/exceptions.rb +14 -0
- data/lib/krakow/frame_type/error.rb +13 -7
- data/lib/krakow/frame_type/message.rb +47 -4
- data/lib/krakow/frame_type/response.rb +14 -4
- data/lib/krakow/frame_type.rb +20 -8
- data/lib/krakow/producer/http.rb +95 -6
- data/lib/krakow/producer.rb +60 -17
- data/lib/krakow/utils/lazy.rb +99 -40
- data/lib/krakow/utils/logging.rb +11 -0
- data/lib/krakow/utils.rb +3 -0
- data/lib/krakow/version.rb +3 -1
- data/lib/krakow.rb +1 -0
- metadata +11 -11
- data/Gemfile +0 -5
- data/Gemfile.lock +0 -34
- data/test/spec.rb +0 -81
- data/test/specs/consumer.rb +0 -49
- data/test/specs/http_producer.rb +0 -123
- data/test/specs/producer.rb +0 -20
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,19 @@
|
|
1
|
+
## v0.3.0
|
2
|
+
* Include jitter to discovery interval lookups
|
3
|
+
* Typecast to String on PUB and MPUB
|
4
|
+
* Update exception types used for not implemented methods
|
5
|
+
* Add #confirm, #requeue, and #touch helpers to FrameType::Message instances
|
6
|
+
* Update Utils::Lazy implementation to be faster and clearer
|
7
|
+
* Add #safe_socket method on Connection to add stability
|
8
|
+
* Rebuild connections on error to prevent consumer teardown
|
9
|
+
* Reference connections without requirement of connection instance being alive
|
10
|
+
* Use #read over #recv on underlying socket to ensure proper number of bytes (thanks @thomas-holmes)
|
11
|
+
* Expand spec testing
|
12
|
+
|
13
|
+
A big thanks to @bschwartz for a large contribution in this changeset
|
14
|
+
including expanded spec coverage, message proxy helper methods, and
|
15
|
+
isolation of instability around Connection interactions.
|
16
|
+
|
1
17
|
## v0.2.2
|
2
18
|
* Fix `nsqlookupd` attribute in `Consumer` and `Discovery`
|
3
19
|
|
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# Contributing
|
2
|
+
|
3
|
+
## Branches
|
4
|
+
|
5
|
+
### `master` branch
|
6
|
+
|
7
|
+
The master branch is the current stable released version.
|
8
|
+
|
9
|
+
### `develop` branch
|
10
|
+
|
11
|
+
The develop branch is the current edge of development.
|
12
|
+
|
13
|
+
## Pull requests
|
14
|
+
|
15
|
+
* https://github.com/chrisroberts/krakow/pulls
|
16
|
+
|
17
|
+
Please base all pull requests of the `develop` branch. Merges to
|
18
|
+
`master` only occur through the `develop` branch. Pull requests
|
19
|
+
based on `master` will likely be cherry picked.
|
20
|
+
|
21
|
+
## Issues
|
22
|
+
|
23
|
+
Need to report an issue? Use the github issues:
|
24
|
+
|
25
|
+
* https://github.com/chrisroberts/krakow/issues
|
data/LICENSE
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright 2014 Chris Roberts
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
data/README.md
CHANGED
@@ -86,7 +86,8 @@ Krakow::Utils::Logging.level = :warn # :debug / :info / :warn / :error / :fatal
|
|
86
86
|
|
87
87
|
### Why is it forcing something called an "unready state"?
|
88
88
|
|
89
|
-
Because forcing starvation is mean.
|
89
|
+
Because forcing starvation is mean. We don't want to be mean, so we'll ensure we
|
90
|
+
are consuming from all registered connections.
|
90
91
|
|
91
92
|
### I just want to connect to a producer, not a lookup service
|
92
93
|
|
@@ -133,8 +134,10 @@ consumer = Krakow::Consumer.new(
|
|
133
134
|
:nsqlookupd => 'http://HOST:PORT',
|
134
135
|
:topic => 'target',
|
135
136
|
:channel => 'ship',
|
136
|
-
:
|
137
|
-
:
|
137
|
+
:connection_options => {
|
138
|
+
:features => {
|
139
|
+
:tls_v1 => true
|
140
|
+
}
|
138
141
|
}
|
139
142
|
)
|
140
143
|
```
|
@@ -148,8 +151,10 @@ consumer = Krakow::Consumer.new(
|
|
148
151
|
:nsqlookupd => 'http://HOST:PORT',
|
149
152
|
:topic => 'target',
|
150
153
|
:channel => 'ship',
|
151
|
-
:
|
152
|
-
:
|
154
|
+
:connection_options => {
|
155
|
+
:features => {
|
156
|
+
:snappy => true
|
157
|
+
}
|
153
158
|
}
|
154
159
|
)
|
155
160
|
```
|
@@ -163,23 +168,71 @@ consumer = Krakow::Consumer.new(
|
|
163
168
|
:nsqlookupd => 'http://HOST:PORT',
|
164
169
|
:topic => 'target',
|
165
170
|
:channel => 'ship',
|
166
|
-
:
|
167
|
-
:
|
171
|
+
:connection_options => {
|
172
|
+
:features => {
|
173
|
+
:deflate => true
|
174
|
+
}
|
168
175
|
}
|
169
176
|
)
|
170
177
|
```
|
171
178
|
|
179
|
+
### I want to use TLS based authentication!
|
180
|
+
|
181
|
+
OK!
|
182
|
+
|
183
|
+
```ruby
|
184
|
+
consumer = Krakow::Consumer.new(
|
185
|
+
:nsqlookupd => 'http://HOST:PORT',
|
186
|
+
:topic => 'target',
|
187
|
+
:channel => 'ship',
|
188
|
+
:connection_options => {
|
189
|
+
:features => {
|
190
|
+
:tls_v1 => true
|
191
|
+
},
|
192
|
+
:config => {
|
193
|
+
:ssl_context => {
|
194
|
+
:certificate => '/path/to/cert',
|
195
|
+
:key => '/path/to/key'
|
196
|
+
}
|
197
|
+
}
|
198
|
+
}
|
199
|
+
)
|
200
|
+
```
|
201
|
+
|
202
|
+
### Running the tests
|
203
|
+
|
204
|
+
Run them all!
|
205
|
+
|
206
|
+
```
|
207
|
+
bundle exec ruby test/run.rb
|
208
|
+
```
|
209
|
+
|
210
|
+
Or, run part of them:
|
211
|
+
|
212
|
+
```
|
213
|
+
bundle exec ruby test/specs/consumer_spec.rb
|
214
|
+
```
|
215
|
+
|
172
216
|
### It doesn't work
|
173
217
|
|
174
|
-
Create an issue on the github repository
|
218
|
+
Create an issue on the github repository
|
219
|
+
* https://github.com/chrisroberts/krakow/issues
|
175
220
|
|
176
221
|
### It doesn't do `x`
|
177
222
|
|
178
|
-
Create an issue, or even better, send a PR.
|
223
|
+
Create an issue, or even better, send a PR.
|
224
|
+
* https://github.com/chrisroberts/krakow/pulls
|
179
225
|
|
180
226
|
# Info
|
181
227
|
* Repo: https://github.com/chrisroberts/krakow
|
228
|
+
* Docs: http://code.chrisroberts.org/krakow
|
182
229
|
* IRC: Freenode @ spox
|
183
230
|
|
184
231
|
[1]: http://bitly.github.io/nsq/ "NSQ: a realtime distributed messaging platform"
|
185
232
|
[2]: http://celluloid.io "Celluloid: Actor-based concurrent object framework for Ruby"
|
233
|
+
|
234
|
+
# Contributors
|
235
|
+
|
236
|
+
* Brendan Schwartz (@bschwartz)
|
237
|
+
* Thomas Holmes (@thomas-holmes)
|
238
|
+
* Jeremy Hinegardner (@copiousfreetime)
|
data/krakow.gemspec
CHANGED
@@ -8,11 +8,13 @@ Gem::Specification.new do |s|
|
|
8
8
|
s.email = 'code@chrisroberts.org'
|
9
9
|
s.homepage = 'http://github.com/chrisroberts/krakow'
|
10
10
|
s.description = 'NSQ ruby library'
|
11
|
+
s.license = 'Apache 2.0'
|
11
12
|
s.require_path = 'lib'
|
12
13
|
s.add_dependency 'celluloid-io'
|
13
14
|
s.add_dependency 'http'
|
14
15
|
s.add_dependency 'multi_json'
|
15
16
|
s.add_dependency 'snappy'
|
16
17
|
s.add_dependency 'digest-crc'
|
17
|
-
s.files = Dir['
|
18
|
+
s.files = Dir['lib/**/*'] + %w(krakow.gemspec README.md CHANGELOG.md CONTRIBUTING.md LICENSE)
|
19
|
+
s.extra_rdoc_files = %w(CHANGELOG.md CONTRIBUTING.md LICENSE)
|
18
20
|
end
|
data/lib/krakow/command/cls.rb
CHANGED
data/lib/krakow/command/fin.rb
CHANGED
@@ -1,11 +1,20 @@
|
|
1
|
+
require 'krakow'
|
2
|
+
|
1
3
|
module Krakow
|
2
4
|
class Command
|
5
|
+
# Finish a message
|
3
6
|
class Fin < Command
|
4
7
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
8
|
+
# @!group Attributes
|
9
|
+
|
10
|
+
# @!macro [attach] attribute
|
11
|
+
# @!method $1
|
12
|
+
# @return [$2] the $1 $0
|
13
|
+
# @!method $1?
|
14
|
+
# @return [TrueClass, FalseClass] truthiness of the $1 $0
|
15
|
+
attribute :message_id, String, :required => true
|
16
|
+
|
17
|
+
# @!endgroup
|
9
18
|
|
10
19
|
def to_line
|
11
20
|
"#{name} #{message_id}\n"
|
@@ -1,18 +1,31 @@
|
|
1
1
|
require 'multi_json'
|
2
|
+
require 'krakow'
|
2
3
|
|
3
4
|
module Krakow
|
4
5
|
class Command
|
6
|
+
# Update client metadata on server / negotiate features
|
5
7
|
class Identify < Command
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
9
|
+
# @!group Attributes
|
10
|
+
|
11
|
+
# @!macro [attach] attribute
|
12
|
+
# @!method $1
|
13
|
+
# @return [$2] the $1 $0
|
14
|
+
# @!method $1?
|
15
|
+
# @return [TrueClass, FalseClass] truthiness of the $1 $0
|
16
|
+
attribute :short_id, [String, Numeric], :required => true
|
17
|
+
attribute :long_id, [String, Numeric], :required => true
|
18
|
+
attribute :feature_negotiation, [TrueClass, FalseClass]
|
19
|
+
attribute :heartbeat_interval, Numeric
|
20
|
+
attribute :output_buffer_size, Integer
|
21
|
+
attribute :output_buffer_timeout, Integer
|
22
|
+
attribute :tls_v1, [TrueClass, FalseClass]
|
23
|
+
attribute :snappy, [TrueClass, FalseClass]
|
24
|
+
attribute :deflate, [TrueClass, FalseClass]
|
25
|
+
attribute :deflate_level, Integer
|
26
|
+
attribute :sample_rate, Integer
|
27
|
+
|
28
|
+
# @!endgroup
|
16
29
|
|
17
30
|
def to_line
|
18
31
|
filtered = Hash[*
|
data/lib/krakow/command/mpub.rb
CHANGED
@@ -1,14 +1,24 @@
|
|
1
|
+
require 'krakow'
|
2
|
+
|
1
3
|
module Krakow
|
2
4
|
class Command
|
5
|
+
# Publish multiple messages
|
3
6
|
class Mpub < Command
|
4
7
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
8
|
+
# @!group Attributes
|
9
|
+
|
10
|
+
# @!macro [attach] attribute
|
11
|
+
# @!method $1
|
12
|
+
# @return [$2] the $1 $0
|
13
|
+
# @!method $1?
|
14
|
+
# @return [TrueClass, FalseClass] truthiness of the $1 $0
|
15
|
+
attribute :topic_name, String, :required => true
|
16
|
+
attribute :messages, Array, :required => true
|
9
17
|
|
18
|
+
# @!endgroup
|
10
19
|
def to_line
|
11
20
|
formatted_messages = messages.map do |message|
|
21
|
+
message = message.to_s
|
12
22
|
[message.length, message].pack('l>a*')
|
13
23
|
end.join
|
14
24
|
[name, ' ', topic_name, "\n", formatted_messages.length, messages.size, formatted_messages].pack('a*a*a*a*l>l>a*')
|
data/lib/krakow/command/nop.rb
CHANGED
data/lib/krakow/command/pub.rb
CHANGED
@@ -1,15 +1,25 @@
|
|
1
|
+
require 'krakow'
|
1
2
|
|
2
3
|
module Krakow
|
3
4
|
class Command
|
5
|
+
# Publish single message
|
4
6
|
class Pub < Command
|
5
7
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
8
|
+
# @!group Attributes
|
9
|
+
|
10
|
+
# @!macro [attach] attribute
|
11
|
+
# @!method $1
|
12
|
+
# @return [$2] the $1 $0
|
13
|
+
# @!method $1?
|
14
|
+
# @return [TrueClass, FalseClass] truthiness of the $1 $0
|
15
|
+
attribute :topic_name, String, :required => true
|
16
|
+
attribute :message, Object, :required => true
|
17
|
+
|
18
|
+
# @!endgroup
|
10
19
|
|
11
20
|
def to_line
|
12
|
-
|
21
|
+
msg = message.to_s
|
22
|
+
[name, ' ', topic_name, "\n", msg.length, msg].pack('a*a*a*a*l>a*')
|
13
23
|
end
|
14
24
|
|
15
25
|
class << self
|
data/lib/krakow/command/rdy.rb
CHANGED
@@ -1,11 +1,20 @@
|
|
1
|
+
require 'krakow'
|
2
|
+
|
1
3
|
module Krakow
|
2
4
|
class Command
|
5
|
+
# Update RDY state
|
3
6
|
class Rdy < Command
|
4
7
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
8
|
+
# @!group Attributes
|
9
|
+
|
10
|
+
# @!macro [attach] attribute
|
11
|
+
# @!method $1
|
12
|
+
# @return [$2] the $1 $0
|
13
|
+
# @!method $1?
|
14
|
+
# @return [TrueClass, FalseClass] truthiness of the $1 $0
|
15
|
+
attribute :count, Integer, :required => true
|
16
|
+
|
17
|
+
# @!endgroup
|
9
18
|
|
10
19
|
def to_line
|
11
20
|
"#{name} #{count}\n"
|
data/lib/krakow/command/req.rb
CHANGED
@@ -1,11 +1,21 @@
|
|
1
|
+
require 'krakow'
|
2
|
+
|
1
3
|
module Krakow
|
2
4
|
class Command
|
5
|
+
# Re-queue a message
|
3
6
|
class Req < Command
|
4
7
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
8
|
+
# @!group Attributes
|
9
|
+
|
10
|
+
# @!macro [attach] attribute
|
11
|
+
# @!method $1
|
12
|
+
# @return [$2] the $1 $0
|
13
|
+
# @!method $1?
|
14
|
+
# @return [TrueClass, FalseClass] truthiness of the $1 $0
|
15
|
+
attribute :message_id, String, :required => true
|
16
|
+
attribute :timeout, Integer, :required => true
|
17
|
+
|
18
|
+
# @!endgroup
|
9
19
|
|
10
20
|
def to_line
|
11
21
|
"#{name} #{message_id} #{self.timeout}\n"
|
data/lib/krakow/command/sub.rb
CHANGED
@@ -1,11 +1,21 @@
|
|
1
|
+
require 'krakow'
|
2
|
+
|
1
3
|
module Krakow
|
2
4
|
class Command
|
5
|
+
# Subscribe to topic/channel
|
3
6
|
class Sub < Command
|
4
7
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
8
|
+
# @!group Attributes
|
9
|
+
|
10
|
+
# @!macro [attach] attribute
|
11
|
+
# @!method $1
|
12
|
+
# @return [$2] the $1 $0
|
13
|
+
# @!method $1?
|
14
|
+
# @return [TrueClass, FalseClass] truthiness of the $1 $0
|
15
|
+
attribute :topic_name, String, :required => true
|
16
|
+
attribute :channel_name, String, :required => true
|
17
|
+
|
18
|
+
# @!endgroup
|
9
19
|
|
10
20
|
def to_line
|
11
21
|
"#{name} #{topic_name} #{channel_name}\n"
|
data/lib/krakow/command/touch.rb
CHANGED
@@ -1,11 +1,20 @@
|
|
1
|
+
require 'krakow'
|
2
|
+
|
1
3
|
module Krakow
|
2
4
|
class Command
|
5
|
+
# Reset timeout for in-flight message
|
3
6
|
class Touch < Command
|
4
7
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
8
|
+
# @!group Attributes
|
9
|
+
|
10
|
+
# @!macro [attach] attribute
|
11
|
+
# @!method $1
|
12
|
+
# @return [$2] the $1 $0
|
13
|
+
# @!method $1?
|
14
|
+
# @return [TrueClass, FalseClass] truthiness of the $1 $0
|
15
|
+
attribute :message_id, String, :required => true
|
16
|
+
|
17
|
+
# @!endgroup
|
9
18
|
|
10
19
|
def to_line
|
11
20
|
"#{name} #{message_id}\n"
|
data/lib/krakow/command.rb
CHANGED
@@ -1,20 +1,33 @@
|
|
1
|
+
require 'krakow'
|
2
|
+
|
1
3
|
module Krakow
|
4
|
+
# Messages for sending to remote server
|
2
5
|
class Command
|
3
6
|
|
4
7
|
include Utils::Lazy
|
8
|
+
# @!parse include Utils::Lazy::InstanceMethods
|
9
|
+
# @!parse extend Utils::Lazy::ClassMethods
|
5
10
|
|
6
11
|
class << self
|
7
12
|
|
13
|
+
# Allowed OK return values
|
14
|
+
#
|
15
|
+
# @return [Array<String>]
|
8
16
|
def ok
|
9
17
|
[]
|
10
18
|
end
|
11
19
|
|
20
|
+
# Allowed ERROR return values
|
21
|
+
#
|
22
|
+
# @return [Array<String>]
|
12
23
|
def error
|
13
24
|
[]
|
14
25
|
end
|
15
26
|
|
16
|
-
#
|
17
|
-
#
|
27
|
+
# Response type expected
|
28
|
+
#
|
29
|
+
# @param message [Krakow::Message] message to check
|
30
|
+
# @return [Symbol] response expected (:none, :error_only, :required)
|
18
31
|
def response_for(message)
|
19
32
|
if(message.class.ok.empty?)
|
20
33
|
if(message.class.error.empty?)
|
@@ -29,23 +42,32 @@ module Krakow
|
|
29
42
|
|
30
43
|
end
|
31
44
|
|
45
|
+
# @return [Krakow::FrameType] response to command
|
32
46
|
attr_accessor :response
|
33
47
|
|
34
|
-
#
|
48
|
+
# @return [String] name of command
|
35
49
|
def name
|
36
50
|
self.class.name.split('::').last.upcase
|
37
51
|
end
|
38
52
|
|
39
53
|
# Convert to line output
|
54
|
+
#
|
55
|
+
# @return [String] socket ready string
|
40
56
|
def to_line(*args)
|
41
57
|
raise NotImplementedError.new 'No line conversion method defined!'
|
42
58
|
end
|
43
59
|
|
60
|
+
# Is response OK
|
61
|
+
#
|
62
|
+
# @return [TrueClass, FalseClass]
|
44
63
|
def ok?(response)
|
45
64
|
response = response.content if response.is_a?(FrameType)
|
46
65
|
self.class.ok.include?(response)
|
47
66
|
end
|
48
67
|
|
68
|
+
# Is response ERROR
|
69
|
+
#
|
70
|
+
# @return [TrueClass, FalseClass]
|
49
71
|
def error?(response)
|
50
72
|
response = response.content if response.is_a?(FrameType)
|
51
73
|
self.class.error.include?(response)
|