nsq-krakow 0.1.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.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +84 -0
  3. data/CONTRIBUTING.md +25 -0
  4. data/LICENSE +13 -0
  5. data/README.md +249 -0
  6. data/krakow.gemspec +22 -0
  7. data/lib/krakow.rb +25 -0
  8. data/lib/krakow/command.rb +89 -0
  9. data/lib/krakow/command/auth.rb +36 -0
  10. data/lib/krakow/command/cls.rb +24 -0
  11. data/lib/krakow/command/fin.rb +31 -0
  12. data/lib/krakow/command/identify.rb +55 -0
  13. data/lib/krakow/command/mpub.rb +39 -0
  14. data/lib/krakow/command/nop.rb +14 -0
  15. data/lib/krakow/command/pub.rb +37 -0
  16. data/lib/krakow/command/rdy.rb +31 -0
  17. data/lib/krakow/command/req.rb +32 -0
  18. data/lib/krakow/command/sub.rb +36 -0
  19. data/lib/krakow/command/touch.rb +31 -0
  20. data/lib/krakow/connection.rb +417 -0
  21. data/lib/krakow/connection_features.rb +10 -0
  22. data/lib/krakow/connection_features/deflate.rb +82 -0
  23. data/lib/krakow/connection_features/snappy_frames.rb +129 -0
  24. data/lib/krakow/connection_features/ssl.rb +75 -0
  25. data/lib/krakow/consumer.rb +355 -0
  26. data/lib/krakow/consumer/queue.rb +151 -0
  27. data/lib/krakow/discovery.rb +57 -0
  28. data/lib/krakow/distribution.rb +229 -0
  29. data/lib/krakow/distribution/default.rb +159 -0
  30. data/lib/krakow/exceptions.rb +30 -0
  31. data/lib/krakow/frame_type.rb +66 -0
  32. data/lib/krakow/frame_type/error.rb +26 -0
  33. data/lib/krakow/frame_type/message.rb +74 -0
  34. data/lib/krakow/frame_type/response.rb +26 -0
  35. data/lib/krakow/ksocket.rb +102 -0
  36. data/lib/krakow/producer.rb +162 -0
  37. data/lib/krakow/producer/http.rb +224 -0
  38. data/lib/krakow/utils.rb +9 -0
  39. data/lib/krakow/utils/lazy.rb +125 -0
  40. data/lib/krakow/utils/logging.rb +43 -0
  41. data/lib/krakow/version.rb +4 -0
  42. metadata +184 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 27cdf9c39570b9a623614f40d8337722d76e3f5e
4
+ data.tar.gz: 96b61e498c662d817dddd4c4e560127b40724b27
5
+ SHA512:
6
+ metadata.gz: 30f924e9a9521464dab1afffa017bcf8e5cfc2661a66f056e18954b699f436b7222d0ee52ee603d35080d9cb29ffd429df207b61886585ea4b8e2c96a73cef10
7
+ data.tar.gz: 82e1d149c54b245df61b36babe1c94c318cc98c2573104900c41a7cdd7cffcee7ede68e15ee1511173a647df0bc6312c6986eaf3af5356a50687c4be8b152ea9
@@ -0,0 +1,84 @@
1
+ ## v0.4.2
2
+ * Update command subclass loading to be explicit (remove glob loading)
3
+
4
+ ## v0.4.0
5
+ * Prevent duplicate connection consumption loops (#23) (thanks @phopkins)
6
+ * Refactor connection implementation to prevent crashing blocks (#22) (thanks @phopkins)
7
+ * Properly calculate message sizes using byte length, not string length (#24) (thanks @phopkins)
8
+ * Clear responses prior to message transmission (#20) (thanks @i2amsam)
9
+ * Rebuild testing specs (not fully covered, but a good start)
10
+ * Consumer and Producer provide better connection failure recovery
11
+ * Fix in-flight issues within distribution on connection failures
12
+
13
+ _NOTE: Large portions of `Krakow::Connection` has been refactored_
14
+
15
+ ## v0.3.12
16
+ * Update Consumer#confirm and Consumer#touch to rescue out lookups and abort
17
+
18
+ ## v0.3.10
19
+ * Remove exclusive from Connection#init!
20
+
21
+ ## v0.3.8
22
+ * Remove locks and move logic to connection access
23
+ * Check for result within response prior to access (prevent slaying actor)
24
+
25
+ ## v0.3.6
26
+ * Allow `:options` key within `Producer` to set low level connection settings
27
+ * Make snappy an optional dependency
28
+ * Add initial support for authentication
29
+ * Update allowed types for optional notifier
30
+
31
+ ## v0.3.4
32
+ * Explicitly require version file (#11 and #12)
33
+
34
+ ## v0.3.2
35
+ * Fix return value from Connection#wait_time_for (#9) (thanks @AlphaB and @davidpelaez)
36
+
37
+ ## v0.3.0
38
+ * Include jitter to discovery interval lookups
39
+ * Typecast to String on PUB and MPUB
40
+ * Update exception types used for not implemented methods
41
+ * Add #confirm, #requeue, and #touch helpers to FrameType::Message instances
42
+ * Update Utils::Lazy implementation to be faster and clearer
43
+ * Add #safe_socket method on Connection to add stability
44
+ * Rebuild connections on error to prevent consumer teardown
45
+ * Reference connections without requirement of connection instance being alive
46
+ * Use #read over #recv on underlying socket to ensure proper number of bytes (thanks @thomas-holmes)
47
+ * Expand spec testing
48
+
49
+ A big thanks to @bschwartz for a large contribution in this changeset
50
+ including expanded spec coverage, message proxy helper methods, and
51
+ isolation of instability around Connection interactions.
52
+
53
+ ## v0.2.2
54
+ * Fix `nsqlookupd` attribute in `Consumer` and `Discovery`
55
+
56
+ ## v0.2.0
57
+ * Fix the rest of the namespacing issues
58
+ * Start adding some tests
59
+ * Use better exception types (NotImplementedError instead of NoMethodError)
60
+ * Be smart about responses within connections
61
+ * Add snappy support
62
+ * Add deflate support
63
+ * Add TLS support
64
+ * Prevent division by zero in distribution
65
+ * Add query methods to lazy helper (`attribute_name`?)
66
+
67
+ ## v0.1.2
68
+ * Include backoff support
69
+ * Remove `method_missing` magic
70
+ * Force message redistribution when connection removed
71
+ * Make discovery interval configurable
72
+ * Add support for HTTP producer
73
+ * Include namespace for custom exceptions #1 (thanks @copiousfreetime)
74
+ * Fix timeout method access in req command #1 (thanks @copiousfreetime)
75
+
76
+ ## v0.1.0
77
+ * Add logging support
78
+ * Include valid responses within commands
79
+ * Segregate responses from messages
80
+ * Manage connections in consumer (closed/reconnect)
81
+ * Add message distribution support
82
+
83
+ ## v0.0.1
84
+ * Initial release
@@ -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.
@@ -0,0 +1,249 @@
1
+ # Krakow
2
+
3
+ "KRAKOW! KRAKOW! Two direct hits!"
4
+
5
+ ## Spiff
6
+
7
+ ```ruby
8
+ require 'krakow'
9
+
10
+ producer = Krakow::Producer.new(
11
+ :host => 'HOST',
12
+ :port => 'PORT',
13
+ :topic => 'target'
14
+ )
15
+ producer.write('KRAKOW!', 'KRAKOW!')
16
+ ```
17
+
18
+ ## Zargons
19
+
20
+ ```ruby
21
+ require 'krakow'
22
+
23
+ consumer = Krakow::Consumer.new(
24
+ :nsqlookupd => 'http://HOST:PORT',
25
+ :topic => 'target',
26
+ :channel => 'ship'
27
+ )
28
+
29
+ consumer.queue.size # => 2
30
+ 2.times do
31
+ msg = consumer.queue.pop
32
+ puts "Received: #{msg}"
33
+ consumer.confirm(msg.message_id)
34
+ end
35
+ ```
36
+
37
+ ## What is this?
38
+
39
+ It's a Ruby library for [NSQ][1] using [Celluloid][2] under the hood.
40
+
41
+ ## Information and FAQ that I totally made up
42
+
43
+ ### Max in flight for consumers is 1, regardless of number of producers
44
+
45
+ Yep, that's right. Just one lowly message at a time. And that's probably not what
46
+ you want, so adjust it when you create your consumer instance.
47
+
48
+ ```ruby
49
+ require 'krakow'
50
+
51
+ consumer = Krakow::Consumer.new(
52
+ :nsqlookupd => 'http://HOST:PORT',
53
+ :topic => 'target',
54
+ :channel => 'ship',
55
+ :max_in_flight => 30
56
+ )
57
+ ```
58
+
59
+ ### Clean up after yourself
60
+
61
+ Since [Celluloid][2] is in use under the hood, and the main interaction points are
62
+ Actors (`Consumer` and `Producer`) you'll need to be sure you clean up. This simply
63
+ means terminating the instance (since falling out of scope will not cause it to be
64
+ garbage collected).
65
+
66
+ ```ruby
67
+ consumer = Krakow::Consumer.new(
68
+ :nsqlookupd => 'http://HOST:PORT',
69
+ :topic => 'target',
70
+ :channel => 'ship',
71
+ :max_in_flight => 30
72
+ )
73
+
74
+ # do stuff
75
+
76
+ consumer.terminate
77
+ ```
78
+
79
+ ### Please make it shutup!
80
+
81
+ Sure:
82
+
83
+ ```ruby
84
+ Krakow::Utils::Logging.level = :warn # :debug / :info / :warn / :error / :fatal
85
+ ```
86
+
87
+ ### Why is it forcing something called an "unready state"?
88
+
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.
91
+
92
+ ### I just want to connect to a producer, not a lookup service
93
+
94
+ Fine!
95
+
96
+ ```ruby
97
+ consumer = Krakow::Consumer.new(
98
+ :host => 'HOST',
99
+ :port => 'PORT',
100
+ :topic => 'target',
101
+ :channel => 'ship',
102
+ :max_in_flight => 30
103
+ )
104
+ ```
105
+ Great for testing, but you really should use the lookup service in the "real world"
106
+
107
+ ### Backoff support
108
+
109
+ NSQ has this backoff notion. It's pretty swell. Basically, if messages from a specific
110
+ producer get re-queued (fail), then message consumption from that producer is halted,
111
+ and slowly ramped back up. It gives time for downstream issues to work themselves out,
112
+ if possible, instead of just keeping the firehose of gasoline on. Neat.
113
+
114
+ By default backoff support is disabled. It can be enabled by setting the `:backoff_interval`
115
+ when constructing the `Consumer`. The interval is in seconds (and yes, floats are allowed
116
+ for sub-second intervals):
117
+
118
+ ```ruby
119
+ consumer = Krakow::Consumer.new(
120
+ :nsqlookupd => 'http://HOST:PORT',
121
+ :topic => 'target',
122
+ :channel => 'ship',
123
+ :max_in_flight => 30,
124
+ :backoff_interval => 1
125
+ )
126
+ ```
127
+
128
+ ### I need TLS!
129
+
130
+ OK!
131
+
132
+ ```ruby
133
+ consumer = Krakow::Consumer.new(
134
+ :nsqlookupd => 'http://HOST:PORT',
135
+ :topic => 'target',
136
+ :channel => 'ship',
137
+ :connection_options => {
138
+ :features => {
139
+ :tls_v1 => true
140
+ }
141
+ }
142
+ )
143
+ ```
144
+
145
+ ### I need Snappy compression!
146
+
147
+ OK!
148
+
149
+ ```ruby
150
+ consumer = Krakow::Consumer.new(
151
+ :nsqlookupd => 'http://HOST:PORT',
152
+ :topic => 'target',
153
+ :channel => 'ship',
154
+ :connection_options => {
155
+ :features => {
156
+ :snappy => true
157
+ }
158
+ }
159
+ )
160
+ ```
161
+
162
+ *NOTE*: snappy support requires the snappy
163
+ gem and is not provided by default, so you
164
+ will need to ensure it is installed either
165
+ on the system, or within the bundle.
166
+
167
+ ### I need Deflate compression!
168
+
169
+ OK!
170
+
171
+ ```ruby
172
+ consumer = Krakow::Consumer.new(
173
+ :nsqlookupd => 'http://HOST:PORT',
174
+ :topic => 'target',
175
+ :channel => 'ship',
176
+ :connection_options => {
177
+ :features => {
178
+ :deflate => true
179
+ }
180
+ }
181
+ )
182
+ ```
183
+
184
+ ### I want to use TLS based authentication!
185
+
186
+ OK!
187
+
188
+ ```ruby
189
+ consumer = Krakow::Consumer.new(
190
+ :nsqlookupd => 'http://HOST:PORT',
191
+ :topic => 'target',
192
+ :channel => 'ship',
193
+ :connection_options => {
194
+ :features => {
195
+ :tls_v1 => true
196
+ },
197
+ :config => {
198
+ :ssl_context => {
199
+ :certificate => '/path/to/cert',
200
+ :key => '/path/to/key'
201
+ }
202
+ }
203
+ }
204
+ )
205
+ ```
206
+
207
+ ### Running the tests
208
+
209
+ Run them all!
210
+
211
+ ```
212
+ bundle exec ruby test/run.rb
213
+ ```
214
+
215
+ Or, run part of them:
216
+
217
+ ```
218
+ bundle exec ruby test/specs/consumer_spec.rb
219
+ ```
220
+
221
+ *NOTE*: the specs expect that `nsqd` and `nsqlookupd` are available in `$PATH`
222
+
223
+ ### It doesn't work
224
+
225
+ Create an issue on the github repository
226
+
227
+ * https://github.com/chrisroberts/krakow/issues
228
+
229
+ ### It doesn't do `x`
230
+
231
+ Create an issue, or even better, send a PR.
232
+
233
+ * https://github.com/chrisroberts/krakow/pulls
234
+
235
+ # Info
236
+ * Repo: https://github.com/chrisroberts/krakow
237
+ * Docs: http://code.chrisroberts.org/krakow
238
+ * IRC: Freenode @ spox
239
+
240
+ [1]: http://bitly.github.io/nsq/ "NSQ: a realtime distributed messaging platform"
241
+ [2]: http://celluloid.io "Celluloid: Actor-based concurrent object framework for Ruby"
242
+
243
+ # Contributors
244
+
245
+ * Pete Hopkins (@phopkins)
246
+ * Sam Phillips (@i2amsam)
247
+ * Brendan Schwartz (@bschwartz)
248
+ * Thomas Holmes (@thomas-holmes)
249
+ * Jeremy Hinegardner (@copiousfreetime)
@@ -0,0 +1,22 @@
1
+ $LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__)) + '/lib/'
2
+ require 'krakow/version'
3
+ Gem::Specification.new do |s|
4
+ s.name = 'nsq-krakow'
5
+ s.version = Krakow::VERSION.version
6
+ s.summary = 'NSQ library'
7
+ s.author = 'Chris Roberts'
8
+ s.email = 'code@chrisroberts.org'
9
+ s.homepage = 'http://github.com/chrisroberts/krakow'
10
+ s.description = 'NSQ ruby library'
11
+ s.license = 'Apache 2.0'
12
+ s.require_path = 'lib'
13
+ s.add_runtime_dependency 'celluloid', '~> 0.16.0'
14
+ s.add_runtime_dependency 'http'
15
+ s.add_runtime_dependency 'multi_json'
16
+ s.add_runtime_dependency 'digest-crc'
17
+ s.add_development_dependency 'childprocess'
18
+ s.add_development_dependency 'snappy'
19
+ s.add_development_dependency 'minitest'
20
+ s.files = Dir['lib/**/*'] + %w(krakow.gemspec README.md CHANGELOG.md CONTRIBUTING.md LICENSE)
21
+ s.extra_rdoc_files = %w(CHANGELOG.md CONTRIBUTING.md LICENSE)
22
+ end
@@ -0,0 +1,25 @@
1
+ require 'celluloid'
2
+
3
+ if(ENV['DEBUG'])
4
+ Celluloid.task_class = Celluloid::TaskThread
5
+ end
6
+
7
+ require 'celluloid/autostart'
8
+ require 'multi_json'
9
+
10
+ # NSQ client and producer library
11
+ module Krakow
12
+ autoload :Command, 'krakow/command'
13
+ autoload :Connection, 'krakow/connection'
14
+ autoload :ConnectionFeatures, 'krakow/connection_features'
15
+ autoload :Consumer, 'krakow/consumer'
16
+ autoload :Discovery, 'krakow/discovery'
17
+ autoload :Distribution, 'krakow/distribution'
18
+ autoload :Error, 'krakow/exceptions'
19
+ autoload :FrameType, 'krakow/frame_type'
20
+ autoload :Ksocket, 'krakow/ksocket'
21
+ autoload :Producer, 'krakow/producer'
22
+ autoload :Utils, 'krakow/utils'
23
+ end
24
+
25
+ require 'krakow/version'
@@ -0,0 +1,89 @@
1
+ require 'krakow'
2
+
3
+ module Krakow
4
+ # Messages for sending to remote server
5
+ class Command
6
+
7
+ include Utils::Lazy
8
+ # @!parse include Utils::Lazy::InstanceMethods
9
+ # @!parse extend Utils::Lazy::ClassMethods
10
+
11
+ autoload :Auth, 'krakow/command/auth'
12
+ autoload :Cls, 'krakow/command/cls'
13
+ autoload :Fin, 'krakow/command/fin'
14
+ autoload :Identify, 'krakow/command/identify'
15
+ autoload :Mpub, 'krakow/command/mpub'
16
+ autoload :Nop, 'krakow/command/nop'
17
+ autoload :Pub, 'krakow/command/pub'
18
+ autoload :Rdy, 'krakow/command/rdy'
19
+ autoload :Req, 'krakow/command/req'
20
+ autoload :Sub, 'krakow/command/sub'
21
+ autoload :Touch, 'krakow/command/touch'
22
+
23
+ class << self
24
+
25
+ # Allowed OK return values
26
+ #
27
+ # @return [Array<String>]
28
+ def ok
29
+ []
30
+ end
31
+
32
+ # Allowed ERROR return values
33
+ #
34
+ # @return [Array<String>]
35
+ def error
36
+ []
37
+ end
38
+
39
+ # Response type expected
40
+ #
41
+ # @param message [Krakow::Message] message to check
42
+ # @return [Symbol] response expected (:none, :error_only, :required)
43
+ def response_for(message)
44
+ if(message.class.ok.empty?)
45
+ if(message.class.error.empty?)
46
+ :none
47
+ else
48
+ :error_only
49
+ end
50
+ else
51
+ :required
52
+ end
53
+ end
54
+
55
+ end
56
+
57
+ # @return [Krakow::FrameType] response to command
58
+ attr_accessor :response
59
+
60
+ # @return [String] name of command
61
+ def name
62
+ self.class.name.split('::').last.upcase
63
+ end
64
+
65
+ # Convert to line output
66
+ #
67
+ # @return [String] socket ready string
68
+ def to_line(*args)
69
+ raise NotImplementedError.new 'No line conversion method defined!'
70
+ end
71
+
72
+ # Is response OK
73
+ #
74
+ # @return [TrueClass, FalseClass]
75
+ def ok?(response)
76
+ response = response.content if response.is_a?(FrameType)
77
+ self.class.ok.include?(response)
78
+ end
79
+
80
+ # Is response ERROR
81
+ #
82
+ # @return [TrueClass, FalseClass]
83
+ def error?(response)
84
+ response = response.content if response.is_a?(FrameType)
85
+ self.class.error.include?(response)
86
+ end
87
+
88
+ end
89
+ end