fastly_nsq 0.13.2 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +5 -5
  2. data/.env +4 -0
  3. data/.overcommit.yml +3 -3
  4. data/.rubocop.yml +11 -1
  5. data/.travis.yml +8 -1
  6. data/Gemfile +9 -0
  7. data/README.md +52 -82
  8. data/Rakefile +2 -0
  9. data/bin/fastly_nsq +1 -0
  10. data/docker-compose.yml +23 -0
  11. data/examples/.sample.env +0 -3
  12. data/fastly_nsq.gemspec +7 -8
  13. data/lib/fastly_nsq.rb +44 -50
  14. data/lib/fastly_nsq/cli.rb +20 -14
  15. data/lib/fastly_nsq/consumer.rb +26 -30
  16. data/lib/fastly_nsq/feeder.rb +16 -0
  17. data/lib/fastly_nsq/http/nsqd.rb +7 -1
  18. data/lib/fastly_nsq/http/nsqlookupd.rb +1 -1
  19. data/lib/fastly_nsq/launcher.rb +31 -23
  20. data/lib/fastly_nsq/listener.rb +34 -103
  21. data/lib/fastly_nsq/manager.rb +48 -72
  22. data/lib/fastly_nsq/message.rb +2 -0
  23. data/lib/fastly_nsq/messenger.rb +5 -5
  24. data/lib/fastly_nsq/priority_queue.rb +12 -0
  25. data/lib/fastly_nsq/priority_thread_pool.rb +32 -0
  26. data/lib/fastly_nsq/producer.rb +52 -32
  27. data/lib/fastly_nsq/testing.rb +239 -0
  28. data/lib/fastly_nsq/tls_options.rb +2 -0
  29. data/lib/fastly_nsq/version.rb +3 -1
  30. data/spec/{lib/fastly_nsq/cli_spec.rb → cli_spec.rb} +2 -0
  31. data/spec/consumer_spec.rb +59 -0
  32. data/spec/fastly_nsq_spec.rb +72 -0
  33. data/spec/feeder_spec.rb +22 -0
  34. data/spec/{lib/fastly_nsq/http → http}/nsqd_spec.rb +1 -1
  35. data/spec/{lib/fastly_nsq/http → http}/nsqlookupd_spec.rb +1 -1
  36. data/spec/{lib/fastly_nsq/http_spec.rb → http_spec.rb} +3 -1
  37. data/spec/integration_spec.rb +48 -0
  38. data/spec/launcher_spec.rb +50 -0
  39. data/spec/listener_spec.rb +184 -0
  40. data/spec/manager_spec.rb +111 -0
  41. data/spec/matchers/delegate.rb +32 -0
  42. data/spec/{lib/fastly_nsq/message_spec.rb → message_spec.rb} +2 -0
  43. data/spec/{lib/fastly_nsq/messenger_spec.rb → messenger_spec.rb} +7 -5
  44. data/spec/priority_thread_pool_spec.rb +19 -0
  45. data/spec/producer_spec.rb +94 -0
  46. data/spec/spec_helper.rb +32 -28
  47. data/spec/support/http.rb +37 -0
  48. data/spec/support/webmock.rb +22 -0
  49. data/spec/{lib/fastly_nsq/tls_options_spec.rb → tls_options_spec.rb} +2 -0
  50. metadata +54 -96
  51. data/env_configuration_for_local_gem_tests.yml +0 -5
  52. data/example_config_class.rb +0 -20
  53. data/examples/Rakefile +0 -41
  54. data/lib/fastly_nsq/fake_backend.rb +0 -114
  55. data/lib/fastly_nsq/listener/config.rb +0 -35
  56. data/lib/fastly_nsq/rake_task.rb +0 -78
  57. data/lib/fastly_nsq/strategy.rb +0 -36
  58. data/spec/lib/fastly_nsq/consumer_spec.rb +0 -72
  59. data/spec/lib/fastly_nsq/fake_backend_spec.rb +0 -135
  60. data/spec/lib/fastly_nsq/fastly_nsq_spec.rb +0 -10
  61. data/spec/lib/fastly_nsq/launcher_spec.rb +0 -56
  62. data/spec/lib/fastly_nsq/listener_spec.rb +0 -213
  63. data/spec/lib/fastly_nsq/manager_spec.rb +0 -127
  64. data/spec/lib/fastly_nsq/producer_spec.rb +0 -60
  65. data/spec/lib/fastly_nsq/rake_task_spec.rb +0 -142
  66. data/spec/lib/fastly_nsq/strategy_spec.rb +0 -36
  67. data/spec/lib/fastly_nsq_spec.rb +0 -18
  68. data/spec/support/env_helpers.rb +0 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 9e293af0d6cd86795807e1727fb3547085917dbf
4
- data.tar.gz: 08243ead04232661269fbb182be2087eaa0a6663
2
+ SHA256:
3
+ metadata.gz: d4e06ecec388c8a7d3f403fbb38ec03788522f25464a6b4a46815ccc584ba613
4
+ data.tar.gz: '04392e44b547924dfcba6df02b26ac86bc5580c32d30eb6b6ca8ecab313c39d0'
5
5
  SHA512:
6
- metadata.gz: a58cf76f4c36e5061080e65c819948ae78ca70595c01377ce4a2ba5745d45e28c7151c72dc23a0880832488ffae2cb0b681bd95a6fe16b1ea86a056cd0b34f5f
7
- data.tar.gz: 09915b030a22911a886b4f56ed345c6acd2d85b36f538626dc4e0133a998a77041b19ab6f820039bbbf94c6f2e5062466007c1647805099c7843c730aa7ff693
6
+ metadata.gz: de8962c909fd1cdd08c0182b4eac693c1d0dec1608c0c60826ace6232198d449e5780a2e4ca9f3aee9cdb0bbc6d73871fb25dabd8a419b62e9aaee65f4fbfdb9
7
+ data.tar.gz: b1bd13296fb6e13f285099374621c0af43485822b04eb3593ec5635f07fb6ff087aa304399b3f389de8b21ecba4304e16a38a716831cc084077fa29dcd5970ed
data/.env ADDED
@@ -0,0 +1,4 @@
1
+ NSQD_TCP_ADDRESS=127.0.0.1:4150
2
+ NSQD_HTTP_ADDRESS=127.0.0.1:4151
3
+ NSQLOOKUPD_TCP_ADDRESS=127.0.0.1:4160
4
+ NSQLOOKUPD_HTTP_ADDRESS=127.0.0.1:4161
data/.overcommit.yml CHANGED
@@ -27,8 +27,8 @@ CommitMsg:
27
27
  description: 'Prevent empty commit messages'
28
28
  enabled: true
29
29
  TextWidth:
30
- description: 'Ensure commit message subjects are <60 chars'
30
+ description: 'Ensure commit message subjects are <72 chars'
31
31
  enabled: true
32
32
  description: 'Checking text width'
33
- max_subject_width: 60
34
- max_body_width: 1000
33
+ max_subject_width: 72
34
+ max_body_width: 72
data/.rubocop.yml CHANGED
@@ -5,7 +5,7 @@ AllCops:
5
5
  - 'db/schema.rb'
6
6
  - 'vendor/**/*'
7
7
  - 'Gemfile'
8
- TargetRubyVersion: 2.2
8
+ TargetRubyVersion: 2.4
9
9
 
10
10
  Layout/DotPosition:
11
11
  Enabled: true
@@ -14,15 +14,25 @@ Layout/DotPosition:
14
14
  - leading
15
15
  - trailing
16
16
 
17
+ Lint/AmbiguousBlockAssociation:
18
+ Exclude:
19
+ - 'spec/**/*'
20
+
17
21
  Lint/RescueWithoutErrorClass:
18
22
  Enabled: false
19
23
 
20
24
  Metrics/MethodLength:
21
25
  Enabled: false
22
26
 
27
+ Metrics/AbcSize:
28
+ Enabled: false
29
+
23
30
  Metrics/LineLength:
24
31
  Enabled: false
25
32
 
33
+ Metrics/ParameterLists:
34
+ Enabled: false
35
+
26
36
  Metrics/BlockLength:
27
37
  ExcludedMethods: [describe, context, configure]
28
38
 
data/.travis.yml CHANGED
@@ -1,11 +1,18 @@
1
1
  language: ruby
2
2
  cache: bundler
3
+ sudo: false
3
4
  rvm:
4
- - 2.2.4
5
5
  - 2.3.5
6
6
  - 2.4.2
7
+ - 2.5.0
7
8
  script:
8
9
  - bundle exec rake
10
+ services:
11
+ - docker
12
+ before_install:
13
+ - docker-compose up -d
14
+ before_script:
15
+ - gem update --system
9
16
  notifications:
10
17
  slack:
11
18
  rooms:
data/Gemfile CHANGED
@@ -1,3 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  gemspec
6
+
7
+ gem 'bundler-audit', '~> 0.5.0'
8
+ gem 'overcommit', '~> 0.32.0'
9
+ gem 'rake', '~> 11.1.2'
10
+ gem 'rdoc', '~> 4.2.2'
11
+ gem 'rubocop', '~> 0.51.0'
12
+ gem 'rubygems-tasks', '~> 0.2'
data/README.md CHANGED
@@ -61,15 +61,39 @@ producer.write(message_data.to_json)
61
61
  ```
62
62
  The mock/real strategy used
63
63
  can be switched
64
- by adding an environment variable
65
- to your application:
64
+ by requiring the test file and configuring the mode.
66
65
 
67
66
  ```ruby
68
- # for the fake
69
- ENV['FAKE_QUEUE'] = true
67
+ require 'fastly_nsq/testing'
68
+ FastlyNsq::Testing.enabled? #=> true
69
+ FastlyNsq::Testing.disabled? #=> false
70
70
 
71
- # for the real thing
72
- ENV['FAKE_QUEUE'] = false
71
+ producer = FastlyNsq::Producer.new(topic: topic)
72
+ listener = FastlyNsq::Listener.new(topic: topic, channel: channel, processor: ->(m) { puts 'got: '+ m.body })
73
+
74
+ FastlyNsq::Testing.fake! # default, messages accumulate on the listeners
75
+
76
+ producer.write '{"foo":"bar"}'
77
+ listener.messages.size #=> 1
78
+
79
+ FastlyNsq::Testing.reset! # remove all accumulated messages
80
+
81
+ listener.messages.size #=> 0
82
+
83
+ producer.write '{"foo":"bar"}'
84
+ listener.messages.size #=> 1
85
+
86
+ listener.drain
87
+ # got: {"foo"=>"bar"}
88
+ listener.messages.size #=> 0
89
+
90
+ FastlyNsq::Testing.inline! # messages are processed as they are produced
91
+ producer.write '{"foo":"bar"}'
92
+ # got: {"foo"=>"bar"}
93
+ listener.messages.size #=> 0
94
+
95
+ FastlyNsq::Testing.disable! # do it live
96
+ FastlyNsq::Testing.enable! # re-enable testing mode
73
97
  ```
74
98
 
75
99
  ### `FastlyNsq::Consumer`
@@ -93,11 +117,6 @@ consumer.size #=> 0
93
117
  consumer.terminate
94
118
  ```
95
119
 
96
- As above,
97
- the mock/real strategy used
98
- can be switched by setting the
99
- `FAKE_QUEUE` environment variable appropriately.
100
-
101
120
  ### `FastlyNsq::Listener`
102
121
 
103
122
  To process the next message on the queue:
@@ -107,70 +126,49 @@ topic = 'user_created'
107
126
  channel = 'my_consuming_service'
108
127
  processor = MessageProcessor
109
128
 
110
- FastlyNsq::Listener.new(topic: topic, channel: channel, processor: processor).go(run_once: true)
129
+ FastlyNsq::Listener.new(topic: topic, channel: channel, processor: processor)
111
130
  ```
112
131
 
113
- This will pop the next message
132
+ This will send messages through `FastlyNsq.manager.pool`
114
133
  off of the queue
115
134
  and send the JSON text body
116
- to `MessageProcessor.process(message_body, topic)`.
135
+ to `MessageProcessor.call(message)`.
117
136
 
118
- To initiate a blocking loop to process messages continuously:
137
+ Specify a topic priority by providing a number (default is 0)
119
138
 
120
139
  ```ruby
121
140
  topic = 'user_created'
122
141
  channel = 'my_consuming_service'
123
142
  processor = MessageProcessor
143
+ priority = 1 # a little higher
124
144
 
125
- FastlyNsq::Listener.new(topic: topic, channel: channel, processor: processor).go
145
+ FastlyNsq::Listener.new(topic: topic, channel: channel, processor: processor, priority: priority)
126
146
  ```
127
147
 
128
- This will block until
129
- there is a new message on the queue,
130
- pop the next message
131
- off of the queue
132
- and send it to `MessageProcessor.process(message_body, topic)`.
133
-
134
- ### `FastlyNsq::RakeTask`
148
+ ### `FastlyNsq::CLI`
135
149
 
136
150
  To help facilitate running the `FastlyNsq::Listener` in a blocking fashion
137
- outside your application, a simple `RakeTask` is provided.
138
-
139
- The task will listen
140
- to all specified topics,
141
- each in a separate thread.
151
+ outside your application, a `CLI` and bin script [`fastly_nsq`](bin/fastly_nsq)
152
+ are provided.
142
153
 
143
- This task can be added into your `Rakefile` in one of two ways:
154
+ This can be setup ahead of time by calling `FastlyNsq.configure` and passing block.
144
155
 
145
- Using a block:
146
156
  ```ruby
147
- require 'fastly_nsq/rake_task'
148
-
149
- FastlyNsq::RakeTask.new(:listen_task) do |task|
150
- task.channel = 'some_channel'
151
- task.topics = {
152
- 'some_topic' => SomeMessageProcessor
153
- }
157
+ # config/fastly_nsq.rb
158
+ FastlyNsq.configure do |config|
159
+ config.channel = 'fnsq'
160
+ config.logger = Logger.new
161
+ config.preprocessor = ->(_) { FastlyNsq.logger.info 'PREPROCESSESES' }
162
+
163
+ lc.listen 'posts', ->(m) { puts "posts: #{m.body}" }
164
+ lc.listen 'blogs', ->(m) { puts "blogs: #{m.body}" }, priority: 3
154
165
  end
155
166
  ```
156
167
 
157
- The task can also define a `call`-able "preprocessor" (called before any `Processor.process`) and a custom `logger`.
158
-
159
- See the [`Rakefile`](examples/Rakefile) file
160
- for more detail.
161
-
162
- ### `FastlyNsq::CLI`
163
-
164
- To help facilitate running the `FastlyNsq::Listener` in a blocking fashion
165
- outside your application, a `CLI` and bin script [`fastly_nsq`](bin/fastly_nsq)
166
- are provided.
167
-
168
- This can be setup ahead of time by calling `FastlyNsq.configure` and passing
169
- block. An exmaple of this can be found here: [`Example Config`](exmaple_config_class.rb)
170
-
171
168
  An example of using the cli:
169
+
172
170
  ```bash
173
- ./bin/fastly_nsq -r ./example_config_class.rb -L ./test.log -P ./fastly_nsq.pid -v -d -t 4
171
+ ./bin/fastly_nsq -r config/fastly_nsq.rb -L ./test.log -P ./fastly_nsq.pid -v -d -t 4 -c 10
174
172
  ```
175
173
 
176
174
  ### `FastlyNsq::Messenger`
@@ -178,13 +176,13 @@ An example of using the cli:
178
176
  Wrapper around a producer for sending messages and persisting producer objects.
179
177
 
180
178
  ```ruby
181
- FastlyNsq::Messenger.deliver(message: msg, on_topic: 'my_topic', originating_service: 'my service')
179
+ FastlyNsq::Messenger.deliver(message: msg, topic: 'my_topic', originating_service: 'my service')
182
180
  ```
183
181
 
184
182
  You can also optionally pass custom metadata.
185
183
 
186
184
  ```ruby
187
- FastlyNsq::Messenger.deliver(message: msg, on_topic: 'my_topic', originating_service: 'my service', meta: { test: 'test' })
185
+ FastlyNsq::Messenger.deliver(message: msg, topic: 'my_topic', originating_service: 'my service', meta: { test: 'test' })
188
186
  ```
189
187
 
190
188
  This will use a FastlyNsq::Producer for the given topic or create on if it isn't
@@ -282,34 +280,6 @@ NSQLOOKUPD_HTTP_ADDRESS='127.0.0.1:4161, 10.1.1.101:4161'
282
280
  See the [`.sample.env`](examples/.sample.env) file
283
281
  for more detail.
284
282
 
285
- ### Testing Against the Fake
286
-
287
- In the gem's test suite,
288
- the fake message queue is used.
289
-
290
- If you would like to force
291
- use of the real NSQ adapter,
292
- ensure `FAKE_QUEUE` is set to `false`.
293
-
294
- When you are developing your application,
295
- it is recommended to
296
- start by using the fake queue:
297
-
298
- ```shell
299
- FAKE_QUEUE=true
300
- ```
301
-
302
- Also be sure call
303
- `FakeBackend.reset!`
304
- before each test in your app to ensure
305
- there are no leftover messages.
306
-
307
- Also note that during gem tests,
308
- we are aliasing `MessageProcessor` to `SampleMessageProcessor`.
309
- You can also refer to the latter
310
- as an example of how
311
- you might write your own processor.
312
-
313
283
  ## Contributors
314
284
 
315
285
  * Adarsh Pandit ([@adarsh](https://github.com/adarsh))
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rubygems'
2
4
 
3
5
  begin
data/bin/fastly_nsq CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'pry'
4
5
  require 'fastly_nsq/cli'
@@ -0,0 +1,23 @@
1
+ version: '3'
2
+ services:
3
+ nsqlookupd:
4
+ image: nsqio/nsq
5
+ command: /nsqlookupd
6
+ ports:
7
+ - "4160:4160"
8
+ - "4161:4161"
9
+ nsqd:
10
+ image: nsqio/nsq
11
+ command: /nsqd --lookupd-tcp-address=nsqlookupd:4160 --broadcast-address localhost
12
+ depends_on:
13
+ - nsqlookupd
14
+ ports:
15
+ - "4150:4150"
16
+ - "4151:4151"
17
+ nsqadmin:
18
+ image: nsqio/nsq
19
+ command: /nsqadmin --lookupd-http-address=nsqlookupd:4161
20
+ depends_on:
21
+ - nsqlookupd
22
+ ports:
23
+ - "4171:4171"
data/examples/.sample.env CHANGED
@@ -11,6 +11,3 @@ NSQD_HTTP_ADDRESS='127.0.0.1:4151'
11
11
  NSQLOOKUPD_TCP_ADDRESS='127.0.0.1:4160'
12
12
  ## NSQLOOKUPD_HTTP_ADDRESS can be a single address or a comma seperated list
13
13
  NSQLOOKUPD_HTTP_ADDRESS='127.0.0.1:4161, 10.0.0.101:4161'
14
-
15
- # Uncomment to test against a live queue
16
- #LIVE_QUEUE=true
data/fastly_nsq.gemspec CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  lib = File.expand_path('../lib', __FILE__)
2
4
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
5
  require 'fastly_nsq/version'
@@ -20,16 +22,13 @@ Gem::Specification.new do |gem|
20
22
 
21
23
  gem.add_development_dependency 'awesome_print', '~> 1.6'
22
24
  gem.add_development_dependency 'bundler', '~> 1.12'
23
- gem.add_development_dependency 'bundler-audit', '~> 0.5.0'
24
25
  gem.add_development_dependency 'dotenv'
25
- gem.add_development_dependency 'overcommit', '~> 0.32.0'
26
26
  gem.add_development_dependency 'pry-byebug', '~> 3.3'
27
- gem.add_development_dependency 'rake', '~> 11.1.2'
28
- gem.add_development_dependency 'rdoc', '~> 4.2.2'
29
- gem.add_development_dependency 'rspec', '~> 3.4.0'
30
- gem.add_development_dependency 'rubocop', '~> 0.51.0'
31
- gem.add_development_dependency 'rubygems-tasks', '~> 0.2'
32
- gem.add_development_dependency 'webmock'
27
+ gem.add_development_dependency 'rspec', '~> 3.4'
28
+ gem.add_development_dependency 'rspec-eventually', '0.2'
29
+ gem.add_development_dependency 'webmock', '~> 3.0'
33
30
 
31
+ gem.add_dependency 'concurrent-ruby', '~> 1.0'
34
32
  gem.add_dependency 'nsq-ruby', '~> 2.0', '>= 2.0.5'
33
+ gem.add_dependency 'priority_queue_cxx', '~> 0.3'
35
34
  end
data/lib/fastly_nsq.rb CHANGED
@@ -1,62 +1,56 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'nsq'
2
- require 'fastly_nsq/consumer'
3
- require 'fastly_nsq/fake_backend'
4
- require 'fastly_nsq/listener'
5
- require 'fastly_nsq/message'
6
- require 'fastly_nsq/messenger'
7
- require 'fastly_nsq/producer'
8
- require 'fastly_nsq/strategy'
9
- require 'fastly_nsq/tls_options'
10
- require 'fastly_nsq/version'
4
+ require 'concurrent'
5
+ require 'fc'
6
+ require 'set'
7
+ require 'logger'
8
+ require 'forwardable'
11
9
 
12
10
  module FastlyNsq
13
- module_function
11
+ NotConnectedError = Class.new(StandardError)
12
+ ConnectionFailed = Class.new(StandardError)
14
13
 
15
- @preprocessor = nil
14
+ class << self
15
+ attr_accessor :channel, :preprocessor
16
+ attr_writer :logger
16
17
 
17
- def channel=(channel)
18
- @channel ||= channel
19
- end
20
-
21
- def logger=(logger)
22
- strategy.logger = logger
23
- end
18
+ def listen(topic, processor, **options)
19
+ FastlyNsq::Listener.new(topic: topic, processor: processor, **options)
20
+ end
24
21
 
25
- def preprocessor=(preprocessor)
26
- @preprocessor ||= preprocessor
27
- end
22
+ def logger
23
+ @logger ||= Logger.new(nil)
24
+ end
28
25
 
29
- def channel
30
- @channel
31
- end
26
+ def configure
27
+ yield self
28
+ end
32
29
 
33
- def logger
34
- strategy.logger
35
- end
30
+ def manager
31
+ @manager ||= FastlyNsq::Manager.new
32
+ end
36
33
 
37
- def preprocessor
38
- @preprocessor
39
- end
34
+ def manager=(manager)
35
+ @manager&.transfer(manager)
36
+ @manager = manager
37
+ end
40
38
 
41
- def strategy
42
- Strategy.for_queue
43
- end
44
-
45
- def configure
46
- yield self
47
- end
48
-
49
- def topic_map
50
- @listener_config.topic_map
51
- end
52
-
53
- def listener_config
54
- @listener_config ||= FastlyNsq::Listener::Config.new
55
- yield @listener_config if block_given?
56
- @listener_config
57
- end
58
-
59
- def reset_config
60
- @listener_config = nil
39
+ def lookupd_http_addresses
40
+ ENV.fetch('NSQLOOKUPD_HTTP_ADDRESS').split(',').map(&:strip)
41
+ end
61
42
  end
62
43
  end
44
+
45
+ require 'fastly_nsq/consumer'
46
+ require 'fastly_nsq/feeder'
47
+ require 'fastly_nsq/launcher'
48
+ require 'fastly_nsq/listener'
49
+ require 'fastly_nsq/manager'
50
+ require 'fastly_nsq/message'
51
+ require 'fastly_nsq/messenger'
52
+ require 'fastly_nsq/priority_queue'
53
+ require 'fastly_nsq/priority_thread_pool'
54
+ require 'fastly_nsq/producer'
55
+ require 'fastly_nsq/tls_options'
56
+ require 'fastly_nsq/version'