fastly_nsq 0.12.4 → 0.13.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.
- checksums.yaml +4 -4
- data/README.md +34 -2
- data/fastly_nsq.gemspec +1 -0
- data/lib/fastly_nsq/fake_backend.rb +10 -8
- data/lib/fastly_nsq/http.rb +57 -0
- data/lib/fastly_nsq/http/nsqd.rb +197 -0
- data/lib/fastly_nsq/http/nsqlookupd.rb +99 -0
- data/lib/fastly_nsq/version.rb +1 -1
- data/spec/lib/fastly_nsq/fake_backend_spec.rb +9 -2
- data/spec/lib/fastly_nsq/http/nsqd_spec.rb +79 -0
- data/spec/lib/fastly_nsq/http/nsqlookupd_spec.rb +68 -0
- data/spec/lib/fastly_nsq/http_spec.rb +76 -0
- data/spec/spec_helper.rb +2 -0
- metadata +22 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 160f5ed48ad6dba8fa1805abc9bd75d9f3c8b738
|
4
|
+
data.tar.gz: bd0ba1550ed27f8d9ced75e5b202fc16bf4d4af0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7870d124317e9ff43e3e40f766699565332d94fdea25741226a9d57613dac542da392cc51407db0a65c31fab4563dc0362a6e1f9d70f26cc26aa32a33c898b90
|
7
|
+
data.tar.gz: 9bbc2b875f8ec619a8ca0732e77c9ecc713a0d5762a61122a372f0fbbc4f52d52bcb04fe45b050ee06e0e27b9341e7caac1ae213265953cf0d32214cc414b344
|
data/README.md
CHANGED
@@ -173,7 +173,7 @@ An example of using the cli:
|
|
173
173
|
./bin/fastly_nsq -r ./example_config_class.rb -L ./test.log -P ./fastly_nsq.pid -v -d -t 4
|
174
174
|
```
|
175
175
|
|
176
|
-
### FastlyNsq::
|
176
|
+
### `FastlyNsq::Messenger`
|
177
177
|
|
178
178
|
Wrapper around a producer for sending messages and persisting producer objects.
|
179
179
|
|
@@ -207,7 +207,39 @@ FastlyNsq::Messenger.terminate_producer(topic: 'hot_topic')
|
|
207
207
|
FastlyNsq::Messenger.terminate_all_producers
|
208
208
|
```
|
209
209
|
|
210
|
-
###
|
210
|
+
### `FastlyNsq::Http`
|
211
|
+
|
212
|
+
Wrappers around `nsqd` and `nsqlookupd` http api's described here:
|
213
|
+
* [NSQD API](http://nsq.io/components/nsqd.html)
|
214
|
+
* [NSQLOOKUPD API](http://nsq.io/components/nsqlookupd.html)
|
215
|
+
|
216
|
+
#### `Nsqd`
|
217
|
+
|
218
|
+
Implements most of the Nsqd api.
|
219
|
+
|
220
|
+
Example usage:
|
221
|
+
```ruby
|
222
|
+
FastlyNsq::Http::Nsqd.ping
|
223
|
+
FastlyNsq::Http::Nsqd.create_channel(topic: 'foo', channel: 'bar')
|
224
|
+
FastlyNsq::Http::Nsqd.stats(topic: 'foo', format: '')
|
225
|
+
```
|
226
|
+
|
227
|
+
TODO:
|
228
|
+
1. Debug endpoints (`/debug/*`)
|
229
|
+
2. Config PUT (`/config/nsqlookupd_tcp_address`)
|
230
|
+
3. Correct Handling of `mpub` `binary` mode
|
231
|
+
|
232
|
+
#### `Nsqlookupd`
|
233
|
+
|
234
|
+
Implements all of the Nsqlookupd api.
|
235
|
+
|
236
|
+
Example usage:
|
237
|
+
```ruby
|
238
|
+
FastlyNsq::Http::Nsqlookupd.nodes
|
239
|
+
FastlyNsq::Http::Nsqlookupd.lookup(topic: 'foo')
|
240
|
+
```
|
241
|
+
|
242
|
+
### `Real vs. Fake`
|
211
243
|
|
212
244
|
The real strategy
|
213
245
|
creates a connection
|
data/fastly_nsq.gemspec
CHANGED
@@ -31,6 +31,7 @@ Gem::Specification.new do |gem|
|
|
31
31
|
gem.add_development_dependency 'rspec', '~> 3.4.0'
|
32
32
|
gem.add_development_dependency 'rubocop', '~> 0.39.0'
|
33
33
|
gem.add_development_dependency 'rubygems-tasks', '~> 0.2'
|
34
|
+
gem.add_development_dependency 'webmock'
|
34
35
|
|
35
36
|
gem.add_dependency 'nsq-ruby', '~> 2.0', '>= 2.0.5'
|
36
37
|
end
|
@@ -33,7 +33,10 @@ module FastlyNsq
|
|
33
33
|
end
|
34
34
|
|
35
35
|
class Producer
|
36
|
-
|
36
|
+
attr_reader :topic
|
37
|
+
|
38
|
+
def initialize(topic:, **)
|
39
|
+
@topic = topic
|
37
40
|
end
|
38
41
|
|
39
42
|
def connected?
|
@@ -41,7 +44,7 @@ module FastlyNsq
|
|
41
44
|
end
|
42
45
|
|
43
46
|
def write(string)
|
44
|
-
message = Message.new(string)
|
47
|
+
message = Message.new(string, topic: topic)
|
45
48
|
queue.push(message)
|
46
49
|
end
|
47
50
|
|
@@ -57,8 +60,7 @@ module FastlyNsq
|
|
57
60
|
end
|
58
61
|
|
59
62
|
class Consumer
|
60
|
-
def initialize(nsqlookupd: nil, topic:, channel:, tls_v1: nil, tls_options: nil)
|
61
|
-
end
|
63
|
+
def initialize(nsqlookupd: nil, topic:, channel:, tls_v1: nil, tls_options: nil); end
|
62
64
|
|
63
65
|
def connected?
|
64
66
|
true
|
@@ -99,14 +101,14 @@ module FastlyNsq
|
|
99
101
|
end
|
100
102
|
|
101
103
|
class Message
|
102
|
-
attr_reader :body
|
104
|
+
attr_reader :topic, :body
|
103
105
|
|
104
|
-
def initialize(body)
|
106
|
+
def initialize(body, topic: nil)
|
107
|
+
@topic = topic
|
105
108
|
@body = body
|
106
109
|
end
|
107
110
|
|
108
|
-
def finish
|
109
|
-
end
|
111
|
+
def finish; end
|
110
112
|
end
|
111
113
|
end
|
112
114
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'net/https'
|
4
|
+
require 'fastly_nsq/http/nsqd'
|
5
|
+
require 'fastly_nsq/http/nsqlookupd'
|
6
|
+
|
7
|
+
class FastlyNsq::Http
|
8
|
+
def initialize(uri:, cert_filename: ENV['NSQ_SSL_CERTIFICATE'], key_filename: ENV['NSQ_SSL_KEY'])
|
9
|
+
@uri = uri.is_a?(URI) ? uri : URI.parse(uri)
|
10
|
+
@cert_filename = cert_filename
|
11
|
+
@key_filename = key_filename
|
12
|
+
end
|
13
|
+
|
14
|
+
def get(data = nil)
|
15
|
+
if data
|
16
|
+
params = URI.encode_www_form(data)
|
17
|
+
uri.query = params
|
18
|
+
end
|
19
|
+
req = Net::HTTP::Get.new(uri.request_uri)
|
20
|
+
http.request(req)
|
21
|
+
end
|
22
|
+
|
23
|
+
def post(data, body = nil)
|
24
|
+
params = URI.encode_www_form(data)
|
25
|
+
uri.query = params
|
26
|
+
req = Net::HTTP::Post.new(uri.request_uri)
|
27
|
+
http.request(req, body)
|
28
|
+
end
|
29
|
+
|
30
|
+
def use_ssl
|
31
|
+
return unless can_use_ssl?
|
32
|
+
http.use_ssl = true
|
33
|
+
http.cert = cert
|
34
|
+
http.key = key
|
35
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
attr_reader :cert_filename, :key_filename, :uri
|
41
|
+
|
42
|
+
def http
|
43
|
+
@http ||= Net::HTTP.new(uri.host, uri.port)
|
44
|
+
end
|
45
|
+
|
46
|
+
def can_use_ssl?
|
47
|
+
!(cert_filename.nil? || key_filename.nil?)
|
48
|
+
end
|
49
|
+
|
50
|
+
def cert
|
51
|
+
@cert ||= OpenSSL::X509::Certificate.new(File.read(cert_filename))
|
52
|
+
end
|
53
|
+
|
54
|
+
def key
|
55
|
+
@key ||= OpenSSL::PKey::RSA.new(File.read(key_filename))
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,197 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'fastly_nsq/http'
|
4
|
+
|
5
|
+
class FastlyNsq::Http
|
6
|
+
class Nsqd
|
7
|
+
extend Forwardable
|
8
|
+
def_delegator :client, :get
|
9
|
+
def_delegator :client, :post
|
10
|
+
|
11
|
+
BASE_NSQD_URL = ENV.fetch 'NSQD_URL', "https://#{ENV.fetch('NSQD_HTTPS_ADDRESS', '')}"
|
12
|
+
VALID_FORMATS = %w(text json).freeze
|
13
|
+
|
14
|
+
##
|
15
|
+
# Monitoring endpoint, should return 200 OK. It returns an HTTP 500 if it is not healthy.
|
16
|
+
#
|
17
|
+
# NOTE: The only "unhealthy" state is if nsqd failed to write messages to disk when overflow occurred.
|
18
|
+
def self.ping(**args)
|
19
|
+
new(request_uri: '/ping', **args).get
|
20
|
+
end
|
21
|
+
|
22
|
+
##
|
23
|
+
# NSQ version information
|
24
|
+
def self.info(**args)
|
25
|
+
new(request_uri: '/info', **args).get
|
26
|
+
end
|
27
|
+
|
28
|
+
##
|
29
|
+
# Return Internal Statistics
|
30
|
+
#
|
31
|
+
# @param topic [String] filter to topic
|
32
|
+
# @param channel [String] filter to channel
|
33
|
+
# @param format [String] can be +text+ or +json+
|
34
|
+
#
|
35
|
+
# @raise [InvaildFormatError] provided format is not in list of valid formats
|
36
|
+
#
|
37
|
+
# @example Fetch Statistics for topic: 'foo', channel: 'bar' as text
|
38
|
+
# Nsqd.stats(topic: 'foo', channel: 'bar', format: 'text')
|
39
|
+
def self.stats(topic: nil, channel: nil, format: 'json', **args)
|
40
|
+
raise InvalidFormatError unless VALID_FORMATS.include?(format)
|
41
|
+
params = { format: format }
|
42
|
+
params[:topic] = topic if topic
|
43
|
+
params[:channel] = channel if channel
|
44
|
+
new(request_uri: '/stats', **args).get(params)
|
45
|
+
end
|
46
|
+
|
47
|
+
##
|
48
|
+
# Publish a message
|
49
|
+
#
|
50
|
+
# @param topic [String] the topic to publish to
|
51
|
+
# @param defer [String] the time in ms to delay message delivery
|
52
|
+
# @param message the message body
|
53
|
+
def self.pub(topic:, message:, defer: nil, **args)
|
54
|
+
params = { topic: topic }
|
55
|
+
params[:defer] = defer if defer
|
56
|
+
new(request_uri: '/pub', **args).post(params, message)
|
57
|
+
end
|
58
|
+
|
59
|
+
##
|
60
|
+
# Publish multiple messages in one roundtrip
|
61
|
+
#
|
62
|
+
# NOTE: by default +/mpub+ expects messages to be delimited by +\n+, use the
|
63
|
+
# +binary: true+ parameter to enable binary mode where message body
|
64
|
+
# is expected to be in the following format (the HTTP Content-Length
|
65
|
+
# header should be sent as the total size of the POST body):
|
66
|
+
# [ 4-byte num messages ]
|
67
|
+
# [ 4-byte message #1 size ][ N-byte binary data ]
|
68
|
+
# ... (repeated <num_messages> times)
|
69
|
+
#
|
70
|
+
# TODO: setup +Content-Legth+ header when binary is passed.
|
71
|
+
#
|
72
|
+
# @param topic [String] the topic to publish to
|
73
|
+
# @param binary [Boolean] enables binary mode
|
74
|
+
# @param message the messages to send with \n used to seperate messages
|
75
|
+
def self.mpub(topic:, binary: false, message:, **args)
|
76
|
+
binary_param = binary ? 'true' : 'false'
|
77
|
+
raise NotImplementedError, 'binary mode has yet to be implemented' if binary
|
78
|
+
params = { topic: topic, binary: binary_param }
|
79
|
+
new(request_uri: '/mpub', **args).post(params, message)
|
80
|
+
end
|
81
|
+
|
82
|
+
##
|
83
|
+
# List of nsqlookupd TCP addresses
|
84
|
+
def self.config_nsqlookupd_tcp_addresses(**args)
|
85
|
+
new(request_uri: '/config/nsqlookupd_tcp_addresses', **args).get
|
86
|
+
end
|
87
|
+
|
88
|
+
##
|
89
|
+
# Create a topic
|
90
|
+
#
|
91
|
+
# @param topic [String] the topic to create
|
92
|
+
def self.topic_create(topic:, **args)
|
93
|
+
new(request_uri: '/topic/create', **args).post(topic: topic)
|
94
|
+
end
|
95
|
+
|
96
|
+
##
|
97
|
+
# Delete a topic (and all of its channels)
|
98
|
+
#
|
99
|
+
# @param topic [String] the existing topic to delete
|
100
|
+
def self.topic_delete(topic:, **args)
|
101
|
+
new(request_uri: '/topic/delete', **args).post(topic: topic)
|
102
|
+
end
|
103
|
+
|
104
|
+
##
|
105
|
+
# Empty all the queued messages (in-memory and disk) for an existing topic
|
106
|
+
#
|
107
|
+
# @param topic [String] the existing topic to empty
|
108
|
+
def self.topic_empty(topic:, **args)
|
109
|
+
new(request_uri: '/topic/empty', **args).post(topic: topic)
|
110
|
+
end
|
111
|
+
|
112
|
+
##
|
113
|
+
# Pause message flow to all channels on an existing topic
|
114
|
+
# (messages will queue at the *topic*)
|
115
|
+
#
|
116
|
+
# @param topic [String] the existing topic to pause
|
117
|
+
def self.topic_pause(topic:, **args)
|
118
|
+
new(request_uri: '/topic/pause', **args).post(topic: topic)
|
119
|
+
end
|
120
|
+
|
121
|
+
##
|
122
|
+
# Unpause message flow to all channels of an existing, paused, topic
|
123
|
+
#
|
124
|
+
# @param topic [String] the existing, paused topic to unpause
|
125
|
+
def self.topic_unpause(topic:, **args)
|
126
|
+
new(request_uri: '/topic/unpause', **args).post(topic: topic)
|
127
|
+
end
|
128
|
+
|
129
|
+
##
|
130
|
+
# Create a channel for an existing topic
|
131
|
+
#
|
132
|
+
# @param topic [String] the existing topic
|
133
|
+
# @param channel [String] the channel to create
|
134
|
+
def self.channel_create(topic:, channel:, **args)
|
135
|
+
new(request_uri: '/channel/create', **args).post(topic: topic, channel: channel)
|
136
|
+
end
|
137
|
+
|
138
|
+
##
|
139
|
+
# Delete an existing channel for an existing topic
|
140
|
+
#
|
141
|
+
# @param topic [String] the existing topic
|
142
|
+
# @param channel [String] the channel to delete
|
143
|
+
def self.channel_delete(topic:, channel:, **args)
|
144
|
+
new(request_uri: '/channel/delete', **args).post(topic: topic, channel: channel)
|
145
|
+
end
|
146
|
+
|
147
|
+
##
|
148
|
+
# Empty all queued messages (in-memory and disk) for an existing channel
|
149
|
+
#
|
150
|
+
# @param topic [String] the existing topic
|
151
|
+
# @param channel [String] the channel to empty
|
152
|
+
def self.channel_empty(topic:, channel:, **args)
|
153
|
+
new(request_uri: '/channel/empty', **args).post(topic: topic, channel: channel)
|
154
|
+
end
|
155
|
+
|
156
|
+
##
|
157
|
+
# Pause message flow to consumers of an existing channel
|
158
|
+
# (messages will queue at the *channel*)
|
159
|
+
#
|
160
|
+
# @param topic [String] the existing topic
|
161
|
+
# @param channel [String] the channel to pause
|
162
|
+
def self.channel_pause(topic:, channel:, **args)
|
163
|
+
new(request_uri: '/channel/pause', **args).post(topic: topic, channel: channel)
|
164
|
+
end
|
165
|
+
|
166
|
+
##
|
167
|
+
# Resume message flow to consumers of and existing, paused, channel
|
168
|
+
#
|
169
|
+
# @param topic [String] the existing topic
|
170
|
+
# @param channel [String] the existing, paused, channel to unpause
|
171
|
+
def self.channel_unpause(topic:, channel:, **args)
|
172
|
+
new(request_uri: '/channel/unpause', **args).post(topic: topic, channel: channel)
|
173
|
+
end
|
174
|
+
|
175
|
+
##
|
176
|
+
# Nsqd http wrapper. Provides a simple interface to all NSQD http api's
|
177
|
+
# @see http://nsq.io/components/nsqd.html
|
178
|
+
#
|
179
|
+
# @attr [String] request_uri the request you would like to call ie: '/thing'
|
180
|
+
# @attr [String] base_uri the host, port, and protocol of your nsqd
|
181
|
+
# @attr [Object] adapter the http adapter you would like to use...
|
182
|
+
def initialize(request_uri:, base_uri: BASE_NSQD_URL, adapter: FastlyNsq::Http)
|
183
|
+
@base_uri = base_uri
|
184
|
+
@adapter = adapter
|
185
|
+
uri = URI.join(@base_uri, request_uri)
|
186
|
+
|
187
|
+
@client = @adapter.new(uri: uri)
|
188
|
+
@client.use_ssl
|
189
|
+
end
|
190
|
+
|
191
|
+
private
|
192
|
+
|
193
|
+
attr_accessor :client
|
194
|
+
|
195
|
+
class InvalidFormatError < StandardError; end
|
196
|
+
end
|
197
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'fastly_nsq/http'
|
4
|
+
|
5
|
+
class FastlyNsq::Http
|
6
|
+
class Nsqlookupd
|
7
|
+
extend Forwardable
|
8
|
+
def_delegator :client, :get
|
9
|
+
|
10
|
+
BASE_NSQLOOKUPD_URL = "http://#{ENV.fetch('NSQLOOKUPD_HTTP_ADDRESS', '').split(',')[0]}".freeze
|
11
|
+
|
12
|
+
##
|
13
|
+
# List of producers for a given topic
|
14
|
+
#
|
15
|
+
# @param topic [String] the topic for which to list producers
|
16
|
+
def self.lookup(topic:, **args)
|
17
|
+
new(request_uri: '/lookup', **args).get(topic: topic)
|
18
|
+
end
|
19
|
+
|
20
|
+
##
|
21
|
+
# List of all known topics
|
22
|
+
def self.topics(**args)
|
23
|
+
new(request_uri: '/topics', **args).get
|
24
|
+
end
|
25
|
+
|
26
|
+
##
|
27
|
+
# List of channels for a given topic
|
28
|
+
#
|
29
|
+
# @param topic [String] the topic for which to list channels
|
30
|
+
def self.channels(topic:, **args)
|
31
|
+
new(request_uri: '/channels', **args).get(topic: topic)
|
32
|
+
end
|
33
|
+
|
34
|
+
##
|
35
|
+
# List all known nsqd nodes
|
36
|
+
def self.nodes(**args)
|
37
|
+
new(request_uri: '/nodes', **args).get
|
38
|
+
end
|
39
|
+
|
40
|
+
##
|
41
|
+
# Deletes an existing topic
|
42
|
+
#
|
43
|
+
# @param topic [String] the exsiting topic to delete
|
44
|
+
def self.delete_topic(topic:, **args)
|
45
|
+
new(request_uri: '/delete_topic', **args).get(topic: topic)
|
46
|
+
end
|
47
|
+
|
48
|
+
##
|
49
|
+
# Deletes an existing channel of an existing topic
|
50
|
+
#
|
51
|
+
# @param topic [String] an exsiting topic
|
52
|
+
# @param channel [String] the exsiting channel to delete
|
53
|
+
def self.delete_channel(topic:, channel:, **args)
|
54
|
+
new(request_uri: '/delete_channel', **args).get(topic: topic, channel: channel)
|
55
|
+
end
|
56
|
+
|
57
|
+
##
|
58
|
+
# Tombstones a specific producer of an existing topic
|
59
|
+
#
|
60
|
+
# @see http://nsq.io/components/nsqlookupd.html#deletion_tombstones
|
61
|
+
#
|
62
|
+
# @param topic [String] the existing topic
|
63
|
+
# @param node [String] the producer (nsqd) to tombstone (identified by <broadcast_address>:<http_port>)
|
64
|
+
def self.tombstone_topic_producer(topic:, node:, **args)
|
65
|
+
new(request_uri: '/tombstone_topic_producer', **args).get(topic: topic, node: node)
|
66
|
+
end
|
67
|
+
|
68
|
+
##
|
69
|
+
# Monitoring endpoint, should return +OK+
|
70
|
+
def self.ping(**args)
|
71
|
+
new(request_uri: '/ping', **args).get
|
72
|
+
end
|
73
|
+
|
74
|
+
##
|
75
|
+
# Returns nsqlookupd version information
|
76
|
+
def self.info(**args)
|
77
|
+
new(request_uri: '/info', **args).get
|
78
|
+
end
|
79
|
+
|
80
|
+
##
|
81
|
+
# Nsqlookupd http wrapper. Provides a simple interface to all NSQlookupd http api's
|
82
|
+
# @see http://nsq.io/components/nsqlookupd.html
|
83
|
+
#
|
84
|
+
# @attr [String] request_uri the request you would like to call ie: '/thing'
|
85
|
+
# @attr [String] base_uri the host, port, and protocol of your nsqd
|
86
|
+
# @attr [Object] adapter the http adapter you would like to use...
|
87
|
+
def initialize(request_uri:, base_uri: BASE_NSQLOOKUPD_URL, adapter: FastlyNsq::Http)
|
88
|
+
@adapter = adapter
|
89
|
+
@base_uri = base_uri
|
90
|
+
uri = URI.join(@base_uri, request_uri)
|
91
|
+
|
92
|
+
@client = @adapter.new(uri: uri)
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
attr_accessor :client
|
98
|
+
end
|
99
|
+
end
|
data/lib/fastly_nsq/version.rb
CHANGED
@@ -41,9 +41,16 @@ RSpec.describe FastlyNsq::FakeBackend::Producer do
|
|
41
41
|
let(:producer) { FastlyNsq::FakeBackend::Producer.new topic: topic }
|
42
42
|
|
43
43
|
it 'adds a new message to the queue' do
|
44
|
-
|
44
|
+
body = 'hello'
|
45
45
|
|
46
|
-
expect
|
46
|
+
expect do
|
47
|
+
producer.write(body)
|
48
|
+
end.to change { FastlyNsq::FakeBackend.queue.size }.by(1)
|
49
|
+
|
50
|
+
message = FastlyNsq::FakeBackend.queue.shift
|
51
|
+
|
52
|
+
expect(message.topic).to eq(topic)
|
53
|
+
expect(message.body).to eq(body)
|
47
54
|
end
|
48
55
|
|
49
56
|
it 'has a `terminate` method which is a noop' do
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'fastly_nsq/http/nsqd'
|
5
|
+
|
6
|
+
RSpec.describe FastlyNsq::Http::Nsqd do
|
7
|
+
let(:base_uri) { 'http://example.com' }
|
8
|
+
|
9
|
+
it 'makes simple get requests' do
|
10
|
+
%w(ping info config/nsqlookupd_tcp_addresses).each do |api|
|
11
|
+
url = "#{base_uri}/#{api}"
|
12
|
+
stub_request(:get, url)
|
13
|
+
FastlyNsq::Http::Nsqd.send(api.tr('/', '_').to_sym, base_uri: base_uri)
|
14
|
+
|
15
|
+
expect(a_request(:get, url)).to have_been_requested
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe 'stats' do
|
20
|
+
it 'can fetch stats' do
|
21
|
+
url = "#{base_uri}/stats?topic=lol&channel=foo&format=json"
|
22
|
+
stub_request(:get, url)
|
23
|
+
data = { topic: 'lol', channel: 'foo', format: 'json' }
|
24
|
+
|
25
|
+
FastlyNsq::Http::Nsqd.stats(topic: 'lol', channel: 'foo', base_uri: base_uri)
|
26
|
+
|
27
|
+
expect(a_request(:get, url).with(query: data)).to have_been_requested
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'raises InvaildFormatError if provided format is not in list' do
|
31
|
+
expect do
|
32
|
+
FastlyNsq::Http::Nsqd.stats(format: 'foo')
|
33
|
+
end.to raise_error(FastlyNsq::Http::Nsqd::InvalidFormatError)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'can publish messages' do
|
38
|
+
url = "#{base_uri}/pub?topic=lol&defer=999"
|
39
|
+
stub_request(:post, url)
|
40
|
+
data = { topic: 'lol', defer: 999 }
|
41
|
+
|
42
|
+
FastlyNsq::Http::Nsqd.pub(topic: 'lol', defer: 999, message: 'SOMETHING', base_uri: base_uri)
|
43
|
+
|
44
|
+
expect(a_request(:post, url).with(query: data, body: 'SOMETHING')).to have_been_requested
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'can publish multiple messages' do
|
48
|
+
url = "#{base_uri}/mpub?topic=lol&binary=false"
|
49
|
+
stub_request(:post, url)
|
50
|
+
data = { topic: 'lol' }
|
51
|
+
body = "ONE MESSAGE\nTWO MESSAGE\nRED MESSAGE\nBLUE MESSAGE"
|
52
|
+
|
53
|
+
FastlyNsq::Http::Nsqd.mpub(topic: 'lol', message: body, base_uri: base_uri)
|
54
|
+
|
55
|
+
expect(a_request(:post, url).with(query: data, body: body)).to have_been_requested
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'can create, delete, empty, pause and unpause topics and channels' do
|
59
|
+
verbs = %w(create delete empty pause unpause)
|
60
|
+
|
61
|
+
verbs.each do |verb|
|
62
|
+
url = "#{base_uri}/topic/#{verb}?topic=lol"
|
63
|
+
stub_request(:post, url)
|
64
|
+
data = { topic: 'lol' }
|
65
|
+
|
66
|
+
FastlyNsq::Http::Nsqd.send("topic_#{verb}".to_sym, topic: 'lol', base_uri: base_uri)
|
67
|
+
|
68
|
+
expect(a_request(:post, url).with(query: data)).to have_been_requested
|
69
|
+
|
70
|
+
url = "#{base_uri}/channel/#{verb}?topic=lol&channel=foo"
|
71
|
+
stub_request(:post, url)
|
72
|
+
data = { topic: 'lol', channel: 'foo' }
|
73
|
+
|
74
|
+
FastlyNsq::Http::Nsqd.send("channel_#{verb}".to_sym, topic: 'lol', channel: 'foo', base_uri: base_uri)
|
75
|
+
|
76
|
+
expect(a_request(:post, url).with(query: data)).to have_been_requested
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'fastly_nsq/http/nsqlookupd'
|
5
|
+
|
6
|
+
RSpec.describe FastlyNsq::Http::Nsqlookupd do
|
7
|
+
let(:base_uri) { 'http://example.com' }
|
8
|
+
|
9
|
+
it 'makes simple get requests' do
|
10
|
+
%w(topics nodes ping info).each do |api|
|
11
|
+
url = "#{base_uri}/#{api}"
|
12
|
+
stub_request(:get, url)
|
13
|
+
FastlyNsq::Http::Nsqlookupd.send(api.to_sym, base_uri: base_uri)
|
14
|
+
|
15
|
+
expect(a_request(:get, url)).to have_been_requested
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'can lookup producers for a topic' do
|
20
|
+
url = "#{base_uri}/lookup?topic=lol"
|
21
|
+
stub_request(:get, url)
|
22
|
+
data = { topic: 'lol' }
|
23
|
+
|
24
|
+
FastlyNsq::Http::Nsqlookupd.lookup(topic: 'lol', base_uri: base_uri)
|
25
|
+
|
26
|
+
expect(a_request(:get, url).with(query: data)).to have_been_requested
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'can lookup channels for a topic' do
|
30
|
+
url = "#{base_uri}/channels?topic=lol"
|
31
|
+
stub_request(:get, url)
|
32
|
+
data = { topic: 'lol' }
|
33
|
+
|
34
|
+
FastlyNsq::Http::Nsqlookupd.channels(topic: 'lol', base_uri: base_uri)
|
35
|
+
|
36
|
+
expect(a_request(:get, url).with(query: data)).to have_been_requested
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'can delete a topic' do
|
40
|
+
url = "#{base_uri}/delete_topic?topic=lol"
|
41
|
+
stub_request(:get, url)
|
42
|
+
data = { topic: 'lol' }
|
43
|
+
|
44
|
+
FastlyNsq::Http::Nsqlookupd.delete_topic(topic: 'lol', base_uri: base_uri)
|
45
|
+
|
46
|
+
expect(a_request(:get, url).with(query: data)).to have_been_requested
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'can delete a channel' do
|
50
|
+
url = "#{base_uri}/delete_channel?topic=lol&channel=foo"
|
51
|
+
stub_request(:get, url)
|
52
|
+
data = { topic: 'lol', channel: 'foo' }
|
53
|
+
|
54
|
+
FastlyNsq::Http::Nsqlookupd.delete_channel(topic: 'lol', channel: 'foo', base_uri: base_uri)
|
55
|
+
|
56
|
+
expect(a_request(:get, url).with(query: data)).to have_been_requested
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'can tombstone a producer' do
|
60
|
+
url = "#{base_uri}/tombstone_topic_producer?topic=lol&node=localhost:8989"
|
61
|
+
stub_request(:get, url)
|
62
|
+
data = { topic: 'lol', node: 'localhost:8989' }
|
63
|
+
|
64
|
+
FastlyNsq::Http::Nsqlookupd.tombstone_topic_producer(topic: 'lol', node: 'localhost:8989', base_uri: base_uri)
|
65
|
+
|
66
|
+
expect(a_request(:get, url).with(query: data)).to have_been_requested
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fastly_nsq/http'
|
3
|
+
|
4
|
+
RSpec.describe FastlyNsq::Http do
|
5
|
+
let(:base_url) { 'http://example.com' }
|
6
|
+
describe 'get' do
|
7
|
+
it 'can make simple requests' do
|
8
|
+
url = "#{base_url}/boop"
|
9
|
+
stub_request(:get, url)
|
10
|
+
|
11
|
+
FastlyNsq::Http.new(uri: URI.parse(url)).get
|
12
|
+
FastlyNsq::Http.new(uri: url).get
|
13
|
+
|
14
|
+
expect(a_request(:get, url)).to have_been_requested.twice
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'can make requests with params' do
|
18
|
+
url = "#{base_url}/boop?sloop=noop"
|
19
|
+
data = { sloop: 'noop' }
|
20
|
+
stub_request(:get, url)
|
21
|
+
|
22
|
+
FastlyNsq::Http.new(uri: url).get(data)
|
23
|
+
|
24
|
+
expect(a_request(:get, url).with(query: data)).to have_been_made
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe 'post' do
|
29
|
+
it 'can make simple post requests' do
|
30
|
+
url = "#{base_url}/boop?sloop=noop"
|
31
|
+
stub_request(:post, url)
|
32
|
+
data = { sloop: 'noop' }
|
33
|
+
|
34
|
+
FastlyNsq::Http.new(uri: URI.parse(url)).post(data)
|
35
|
+
FastlyNsq::Http.new(uri: url).post(data)
|
36
|
+
|
37
|
+
expect(a_request(:post, url)).to have_been_requested.twice
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'can make post requests with bodies' do
|
41
|
+
url = "#{base_url}/boop?sloop=noop"
|
42
|
+
stub_request(:post, url)
|
43
|
+
data = { sloop: 'noop' }
|
44
|
+
body = 'SOME MESSAGE'
|
45
|
+
|
46
|
+
FastlyNsq::Http.new(uri: url).post(data, body)
|
47
|
+
|
48
|
+
expect(a_request(:post, url).with(body: body)).to have_been_requested
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe 'SSL' do
|
53
|
+
it 'can be asked to use SSL' do
|
54
|
+
ssl_url = 'https://example.com:80/boop'
|
55
|
+
stub_request(:get, ssl_url)
|
56
|
+
|
57
|
+
cert_file = '/tmp/thing.cert'
|
58
|
+
key_file = '/tmp/thing.key'
|
59
|
+
|
60
|
+
allow(File).to receive(:read).with(cert_file).and_return('something')
|
61
|
+
allow(File).to receive(:read).with(key_file).and_return('something')
|
62
|
+
allow(OpenSSL::X509::Certificate).to receive(:new).with('something').and_return(true)
|
63
|
+
allow(OpenSSL::PKey::RSA).to receive(:new).with('something').and_return(true)
|
64
|
+
|
65
|
+
url = "#{base_url}/boop"
|
66
|
+
http = FastlyNsq::Http.new(uri: url, cert_filename: cert_file, key_filename: key_file)
|
67
|
+
http.use_ssl
|
68
|
+
http.get
|
69
|
+
|
70
|
+
expect(a_request(:get, ssl_url)).to have_been_requested
|
71
|
+
expect(File).to have_received(:read).twice
|
72
|
+
expect(OpenSSL::X509::Certificate).to have_received(:new)
|
73
|
+
expect(OpenSSL::PKey::RSA).to have_received(:new)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'fastly_nsq'
|
2
2
|
require 'awesome_print'
|
3
3
|
require 'pry-byebug'
|
4
|
+
require 'webmock/rspec'
|
4
5
|
|
5
6
|
require_relative 'support/env_helpers'
|
6
7
|
|
@@ -29,6 +30,7 @@ RSpec.configure do |config|
|
|
29
30
|
config.before(:each) do
|
30
31
|
load_sample_environment_variables
|
31
32
|
FastlyNsq::FakeBackend.reset!
|
33
|
+
WebMock.reset!
|
32
34
|
end
|
33
35
|
|
34
36
|
config.around(:each, fake_queue: true) do |example|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fastly_nsq
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.13.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tommy O'Neil
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2017-11-
|
14
|
+
date: 2017-11-29 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: awesome_print
|
@@ -167,6 +167,20 @@ dependencies:
|
|
167
167
|
- - "~>"
|
168
168
|
- !ruby/object:Gem::Version
|
169
169
|
version: '0.2'
|
170
|
+
- !ruby/object:Gem::Dependency
|
171
|
+
name: webmock
|
172
|
+
requirement: !ruby/object:Gem::Requirement
|
173
|
+
requirements:
|
174
|
+
- - ">="
|
175
|
+
- !ruby/object:Gem::Version
|
176
|
+
version: '0'
|
177
|
+
type: :development
|
178
|
+
prerelease: false
|
179
|
+
version_requirements: !ruby/object:Gem::Requirement
|
180
|
+
requirements:
|
181
|
+
- - ">="
|
182
|
+
- !ruby/object:Gem::Version
|
183
|
+
version: '0'
|
170
184
|
- !ruby/object:Gem::Dependency
|
171
185
|
name: nsq-ruby
|
172
186
|
requirement: !ruby/object:Gem::Requirement
|
@@ -217,6 +231,9 @@ files:
|
|
217
231
|
- lib/fastly_nsq/cli.rb
|
218
232
|
- lib/fastly_nsq/consumer.rb
|
219
233
|
- lib/fastly_nsq/fake_backend.rb
|
234
|
+
- lib/fastly_nsq/http.rb
|
235
|
+
- lib/fastly_nsq/http/nsqd.rb
|
236
|
+
- lib/fastly_nsq/http/nsqlookupd.rb
|
220
237
|
- lib/fastly_nsq/launcher.rb
|
221
238
|
- lib/fastly_nsq/listener.rb
|
222
239
|
- lib/fastly_nsq/listener/config.rb
|
@@ -233,6 +250,9 @@ files:
|
|
233
250
|
- spec/lib/fastly_nsq/consumer_spec.rb
|
234
251
|
- spec/lib/fastly_nsq/fake_backend_spec.rb
|
235
252
|
- spec/lib/fastly_nsq/fastly_nsq_spec.rb
|
253
|
+
- spec/lib/fastly_nsq/http/nsqd_spec.rb
|
254
|
+
- spec/lib/fastly_nsq/http/nsqlookupd_spec.rb
|
255
|
+
- spec/lib/fastly_nsq/http_spec.rb
|
236
256
|
- spec/lib/fastly_nsq/launcher_spec.rb
|
237
257
|
- spec/lib/fastly_nsq/listener_spec.rb
|
238
258
|
- spec/lib/fastly_nsq/manager_spec.rb
|