ruby_nest_nats 0.2.1 → 0.2.2
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 +9 -9
- data/lib/ruby_nest_nats.rb +5 -3
- data/lib/ruby_nest_nats/client.rb +54 -59
- data/lib/ruby_nest_nats/controller.rb +64 -67
- data/lib/ruby_nest_nats/utils.rb +2 -1
- data/lib/ruby_nest_nats/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 115d647c8fddd551ecd29db19c99ecc6ee958b80406322141d9773219dd24345
|
4
|
+
data.tar.gz: b000384383eef9cf1f484195115aba6ef9bb4727b5baa852a818006a8bbbf876
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dbe204fb29c5acc514ff48c026ce34f93e297bcaebceb5e6fade77512e373e2a722b733dc92ac8e5b1228cf9e551f138659ad7511e6ff8a7d9d23740a0e91e74
|
7
|
+
data.tar.gz: 3f2b68a7473b4facddbc954aae0fd38b5d0a1e9b2a72adfd69415a1e7ec712a4d2723a04935d9a30aa25aa83aa681262149aab3047da3d26333d2e98125834fe
|
data/README.md
CHANGED
@@ -62,7 +62,7 @@ docker run -p 4222:4222 -p 8222:8222 -p 6222:6222 -ti nats:latest
|
|
62
62
|
|
63
63
|
Attach a logger to have `ruby_nest_nats` write out logs for messages received, responses sent, errors raised, lifecycle events, etc.
|
64
64
|
|
65
|
-
```
|
65
|
+
```ruby
|
66
66
|
require 'ruby_nest_nats'
|
67
67
|
require 'logger'
|
68
68
|
|
@@ -74,7 +74,7 @@ RubyNestNats::Client.logger = nats_logger
|
|
74
74
|
|
75
75
|
In a Rails application, you might do this instead:
|
76
76
|
|
77
|
-
```
|
77
|
+
```ruby
|
78
78
|
RubyNestNats::Client.logger = Rails.logger
|
79
79
|
```
|
80
80
|
|
@@ -93,13 +93,13 @@ The following will be logged at the specified log levels
|
|
93
93
|
|
94
94
|
Set a default queue for subscriptions.
|
95
95
|
|
96
|
-
```
|
96
|
+
```ruby
|
97
97
|
RubyNestNats::Client.default_queue = "foobar"
|
98
98
|
```
|
99
99
|
|
100
100
|
Leave the `::default_queue` blank (or assign `nil`) to use no default queue.
|
101
101
|
|
102
|
-
```
|
102
|
+
```ruby
|
103
103
|
RubyNestNats::Client.default_queue = nil
|
104
104
|
```
|
105
105
|
|
@@ -111,7 +111,7 @@ Register a message handler with the `RubyNestNats::Client::reply_to` method. Pas
|
|
111
111
|
|
112
112
|
The result of the given block will be published in reply to the message. The block is passed two arguments when a message matching the subject is received: `data` and `subject`. The `data` argument is the payload of the message (JSON objects/arrays will be parsed into string-keyed `Hash` objects/`Array` objects, respectively). The `subject` argument is the subject of the message received (mostly only useful if a _pattern_ was specified instead of a static subject string).
|
113
113
|
|
114
|
-
```
|
114
|
+
```ruby
|
115
115
|
RubyNestNats::Client.reply_to("some.subject", queue: "foobar") { |data| "Got it! #{data.inspect}" }
|
116
116
|
|
117
117
|
RubyNestNats::Client.reply_to("some.*.pattern") { |data, subject| "Got #{data} on #{subject}" }
|
@@ -133,7 +133,7 @@ end
|
|
133
133
|
|
134
134
|
Start listening for messages with the `RubyNestNats::Client::start!` method. This will spin up a non-blocking thread that subscribes to subjects (as specified by invocation(s) of `::reply_to`) and waits for messages to come in. When a message is received, the appropriate `::reply_to` block will be used to compute a response, and that response will be published.
|
135
135
|
|
136
|
-
```
|
136
|
+
```ruby
|
137
137
|
RubyNestNats::Client.start!
|
138
138
|
```
|
139
139
|
|
@@ -149,7 +149,7 @@ The following should be enough to start a `ruby_nest_nats` setup in your Ruby ap
|
|
149
149
|
|
150
150
|
> **NOTE:** For a more organized structure and implementation in a larger app (like a Rails project), see the ["controller" section below](#controller-section).
|
151
151
|
|
152
|
-
```
|
152
|
+
```ruby
|
153
153
|
require 'ruby_nest_nats'
|
154
154
|
require 'logger'
|
155
155
|
|
@@ -178,7 +178,7 @@ Use the `::subject` macro to create a block for listening to that subject segmen
|
|
178
178
|
|
179
179
|
You can register a response for the built-up subject/pattern string using the `::response` macro. Pass a block to `::response` which optionally takes two arguments ([the same arguments supplied to the block of `RubyNestNats::Client::reply_to`](#reply-to-section)). The result of that block will be sent as a response to the message received.
|
180
180
|
|
181
|
-
```
|
181
|
+
```ruby
|
182
182
|
class HelloController < RubyNestNats::Controller
|
183
183
|
default_queue "foobar"
|
184
184
|
|
@@ -228,7 +228,7 @@ end
|
|
228
228
|
>
|
229
229
|
> For example: in a Rails project (assuming you have your NATS controllers in a directory called `app/nats/`), you may want to put something like the following in an initializer (such as `config/initializers/nats.rb`):
|
230
230
|
>
|
231
|
-
> ```
|
231
|
+
> ```ruby
|
232
232
|
> RubyNestNats::Client.logger = Rails.logger
|
233
233
|
> RubyNestNats::Client.default_queue = "foobar"
|
234
234
|
>
|
data/lib/ruby_nest_nats.rb
CHANGED
@@ -6,10 +6,12 @@ require_relative "ruby_nest_nats/utils"
|
|
6
6
|
require_relative "ruby_nest_nats/client"
|
7
7
|
require_relative "ruby_nest_nats/controller"
|
8
8
|
|
9
|
-
# The
|
9
|
+
# The +RubyNestNats+ module provides the top-level namespace for the NATS client
|
10
10
|
# and controller machinery.
|
11
11
|
module RubyNestNats
|
12
|
-
|
12
|
+
# :nodoc:
|
13
|
+
class Error < StandardError; end
|
13
14
|
|
14
|
-
|
15
|
+
# :nodoc:
|
16
|
+
class NewSubscriptionsError < RubyNestNats::Error; end
|
15
17
|
end
|
@@ -5,31 +5,30 @@ require "nats/client"
|
|
5
5
|
require_relative "./utils"
|
6
6
|
|
7
7
|
module RubyNestNats
|
8
|
-
# The
|
8
|
+
# The +RubyNestNats::Client+ class provides a basic interface for subscribing
|
9
9
|
# to messages by subject & queue, and replying to those messages. It also logs
|
10
10
|
# most functionality if desired.
|
11
11
|
class Client
|
12
12
|
class << self
|
13
|
-
|
13
|
+
# :nodoc:
|
14
|
+
attr_reader :logger, :default_queue
|
14
15
|
|
15
|
-
# Attach a logger to have
|
16
|
+
# Attach a logger to have +ruby_nest_nats+ write out logs for messages
|
16
17
|
# received, responses sent, errors raised, lifecycle events, etc.
|
17
18
|
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
19
|
+
# @example
|
20
|
+
# require 'ruby_nest_nats'
|
21
|
+
# require 'logger'
|
21
22
|
#
|
22
|
-
#
|
23
|
-
#
|
23
|
+
# nats_logger = Logger.new(STDOUT)
|
24
|
+
# nats_logger.level = Logger::INFO
|
24
25
|
#
|
25
|
-
#
|
26
|
-
# ```
|
26
|
+
# RubyNestNats::Client.logger = nats_logger
|
27
27
|
#
|
28
28
|
# In a Rails application, you might do this instead:
|
29
29
|
#
|
30
|
-
#
|
31
|
-
#
|
32
|
-
# ```
|
30
|
+
# @example
|
31
|
+
# RubyNestNats::Client.logger = Rails.logger
|
33
32
|
#
|
34
33
|
def logger=(some_logger)
|
35
34
|
log("Setting the logger to #{some_logger.inspect}")
|
@@ -38,16 +37,14 @@ module RubyNestNats
|
|
38
37
|
|
39
38
|
# Set a default queue for subscriptions.
|
40
39
|
#
|
41
|
-
#
|
42
|
-
#
|
43
|
-
# ```
|
40
|
+
# @example
|
41
|
+
# RubyNestNats::Client.default_queue = "foobar"
|
44
42
|
#
|
45
|
-
# Leave the
|
43
|
+
# Leave the +::default_queue+ blank (or assign +nil+) to use no default
|
46
44
|
# queue.
|
47
45
|
#
|
48
|
-
#
|
49
|
-
#
|
50
|
-
# ```
|
46
|
+
# @example
|
47
|
+
# RubyNestNats::Client.default_queue = nil
|
51
48
|
#
|
52
49
|
def default_queue=(some_queue)
|
53
50
|
queue = Utils.presence(some_queue.to_s)
|
@@ -55,52 +52,51 @@ module RubyNestNats
|
|
55
52
|
@default_queue = queue
|
56
53
|
end
|
57
54
|
|
58
|
-
# Returns
|
59
|
-
# is listening to NATS messages). Returns
|
55
|
+
# Returns +true+ if +::start!+ has already been called (meaning the client
|
56
|
+
# is listening to NATS messages). Returns +false+ if it has not yet been
|
60
57
|
# called, or if it has been stopped.
|
61
58
|
def started?
|
62
59
|
@started ||= false
|
63
60
|
end
|
64
61
|
|
65
|
-
# Opposite of
|
62
|
+
# Opposite of +::started?+: returns +false+ if +::start!+ has already been
|
66
63
|
# called (meaning the client is listening to NATS messages). Returns
|
67
|
-
#
|
64
|
+
# +true+ if it has not yet been called, or if it has been stopped.
|
68
65
|
def stopped?
|
69
66
|
!started?
|
70
67
|
end
|
71
68
|
|
72
|
-
# Register a message handler with the
|
69
|
+
# Register a message handler with the +RubyNestNats::Client::reply_to+
|
73
70
|
# method. Pass a subject string as the first argument (either a static
|
74
71
|
# subject string or a pattern to match more than one subject). Specify a
|
75
|
-
# queue (or don't) with the
|
76
|
-
#
|
77
|
-
#
|
72
|
+
# queue (or don't) with the +queue:+ option. If you don't provide the
|
73
|
+
# +queue:+ option, it will be set to the value of +default_queue+, or to
|
74
|
+
# +nil+ (no queue) if a default queue hasn't been set.
|
78
75
|
#
|
79
76
|
# The result of the given block will be published in reply to the message.
|
80
77
|
# The block is passed two arguments when a message matching the subject is
|
81
|
-
# received:
|
82
|
-
# the message (JSON objects/arrays will be parsed into string-keyed
|
83
|
-
# objects
|
78
|
+
# received: +data+ and +subject+. The +data+ argument is the payload of
|
79
|
+
# the message (JSON objects/arrays will be parsed into string-keyed +Hash+
|
80
|
+
# objects/+Array+ objects, respectively). The +subject+ argument is the
|
84
81
|
# subject of the message received (mostly only useful if a _pattern_ was
|
85
82
|
# specified instead of a static subject string).
|
86
83
|
#
|
87
|
-
#
|
88
|
-
#
|
84
|
+
# @example
|
85
|
+
# RubyNestNats::Client.reply_to("some.subject", queue: "foobar") { |data| "Got it! #{data.inspect}" }
|
89
86
|
#
|
90
|
-
#
|
87
|
+
# RubyNestNats::Client.reply_to("some.*.pattern") { |data, subject| "Got #{data} on #{subject}" }
|
91
88
|
#
|
92
|
-
#
|
93
|
-
#
|
94
|
-
#
|
95
|
-
#
|
96
|
-
#
|
89
|
+
# RubyNestNats::Client.reply_to("other.subject") do |data|
|
90
|
+
# if data["foo"] == "bar"
|
91
|
+
# { is_bar: "Yep!" }
|
92
|
+
# else
|
93
|
+
# { is_bar: "No way!" }
|
94
|
+
# end
|
97
95
|
# end
|
98
|
-
# end
|
99
96
|
#
|
100
|
-
#
|
101
|
-
#
|
102
|
-
#
|
103
|
-
# ```
|
97
|
+
# RubyNestNats::Client.reply_to("subject.in.queue", queue: "barbaz") do
|
98
|
+
# "My turn!"
|
99
|
+
# end
|
104
100
|
#
|
105
101
|
def reply_to(subject, queue: nil, &block)
|
106
102
|
queue = Utils.presence(queue) || default_queue
|
@@ -109,34 +105,33 @@ module RubyNestNats
|
|
109
105
|
register_reply!(subject: subject.to_s, handler: block, queue: queue.to_s)
|
110
106
|
end
|
111
107
|
|
112
|
-
# Start listening for messages with the
|
108
|
+
# Start listening for messages with the +RubyNestNats::Client::start!+
|
113
109
|
# method. This will spin up a non-blocking thread that subscribes to
|
114
|
-
# subjects (as specified by invocation(s) of
|
110
|
+
# subjects (as specified by invocation(s) of +::reply_to+) and waits for
|
115
111
|
# messages to come in. When a message is received, the appropriate
|
116
|
-
#
|
112
|
+
# +::reply_to+ block will be used to compute a response, and that response
|
117
113
|
# will be published.
|
118
114
|
#
|
119
|
-
#
|
120
|
-
#
|
121
|
-
# ```
|
115
|
+
# @example
|
116
|
+
# RubyNestNats::Client.start!
|
122
117
|
#
|
123
118
|
# **NOTE:** If an error is raised in one of the handlers,
|
124
|
-
#
|
119
|
+
# +RubyNestNats::Client+ will restart automatically.
|
125
120
|
#
|
126
|
-
# **NOTE:** You _can_ invoke
|
127
|
-
# subscriptions after
|
121
|
+
# **NOTE:** You _can_ invoke +::reply_to+ to create additional message
|
122
|
+
# subscriptions after +RubyNestNats::Client.start!+, but be aware that
|
128
123
|
# this forces the client to restart. You may see (benign, already-handled)
|
129
124
|
# errors in the logs generated when this restart happens. It will force
|
130
125
|
# the client to restart and re-subscribe after _each additional
|
131
|
-
#
|
132
|
-
# additional
|
133
|
-
# refactoring so that your call to
|
126
|
+
# +::reply_to+ invoked after +::start!+._ So, if you have a lot of
|
127
|
+
# additional +::reply_to+ invocations, you may want to consider
|
128
|
+
# refactoring so that your call to +RubyNestNats::Client.start!+ occurs
|
134
129
|
# _after_ those additions.
|
135
130
|
#
|
136
|
-
# **NOTE:** The
|
137
|
-
# only the first will be honored, and any subsequent calls to
|
131
|
+
# **NOTE:** The +::start!+ method can be safely called multiple times;
|
132
|
+
# only the first will be honored, and any subsequent calls to +::start!+
|
138
133
|
# after the client is already started will do nothing (except write a
|
139
|
-
# _"NATS is already running"_ log to the logger at the
|
134
|
+
# _"NATS is already running"_ log to the logger at the +DEBUG+ level).
|
140
135
|
#
|
141
136
|
def start!
|
142
137
|
log("Starting NATS", level: :debug)
|
@@ -3,38 +3,38 @@
|
|
3
3
|
require_relative "./utils"
|
4
4
|
|
5
5
|
module RubyNestNats
|
6
|
-
# Create controller classes which inherit from
|
6
|
+
# Create controller classes which inherit from +RubyNestNats::Controller+ in
|
7
7
|
# order to give your message listeners some structure.
|
8
8
|
class Controller
|
9
|
+
# :nodoc:
|
9
10
|
NO_QUEUE_GIVEN = :ruby_nest_nats_super_special_no_op_queue_symbol_qwertyuiop1234567890
|
10
11
|
|
11
12
|
class << self
|
12
13
|
# Default queue for the controller. Falls back to the client's default
|
13
|
-
# queue if the controller's default queue is
|
14
|
+
# queue if the controller's default queue is +nil+.
|
14
15
|
#
|
15
|
-
# - Call with no argument (
|
16
|
-
# - Call as a macro with an argument (
|
16
|
+
# - Call with no argument (+::default_queue+) to get the default queue.
|
17
|
+
# - Call as a macro with an argument (+default_queue "something"+) to set
|
17
18
|
# the default queue.
|
18
19
|
#
|
19
|
-
#
|
20
|
+
# @example
|
21
|
+
# class FoobarNatsController < RubyNatsController
|
22
|
+
# default_queue "foobar"
|
20
23
|
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
# # ...
|
25
|
-
# end
|
24
|
+
# # ...
|
25
|
+
# end
|
26
26
|
#
|
27
27
|
# If omitted, the controller will fall back on the global default queue
|
28
|
-
# assigned with
|
28
|
+
# assigned with +RubyNestNats::Client::default_queue=+. If no default
|
29
29
|
# queue is set in either the controller or globally, then the default
|
30
|
-
# queue will be blank. Set the default queue to
|
30
|
+
# queue will be blank. Set the default queue to +nil+ in a controller to
|
31
31
|
# override the global default queue and explicitly make the default queue
|
32
32
|
# blank for that controller.
|
33
33
|
#
|
34
34
|
def default_queue(some_queue = NO_QUEUE_GIVEN)
|
35
|
-
#
|
36
|
-
# default queue can be "unset" to
|
37
|
-
# default set with
|
35
|
+
# +NO_QUEUE_GIVEN+ is a special symbol (rather than +nil+) so that the
|
36
|
+
# default queue can be "unset" to +nil+ (given a non-+nil+ global
|
37
|
+
# default set with +RubyNestNats::Client::default_queue=+).
|
38
38
|
if some_queue == NO_QUEUE_GIVEN
|
39
39
|
@default_queue || Client.default_queue
|
40
40
|
else
|
@@ -42,54 +42,52 @@ module RubyNestNats
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
-
# Use the
|
46
|
-
# subject segment. Nested calls to
|
45
|
+
# Use the +::subject+ macro to create a block for listening to that
|
46
|
+
# subject segment. Nested calls to +::subject+ will append each subsequent
|
47
47
|
# subject/pattern string to the last (joined by a periods). There is no
|
48
48
|
# limit to the level of nesting.
|
49
49
|
#
|
50
50
|
# **NOTE:** The following two examples do exactly the same thing.
|
51
51
|
#
|
52
|
-
#
|
52
|
+
# @example
|
53
|
+
# class FoobarNatsController < RubyNatsController
|
54
|
+
# # ...
|
55
|
+
#
|
56
|
+
# subject "hello.wassup" do
|
57
|
+
# response do |data, subject|
|
58
|
+
# # The subject at this point is "hello.wassup"
|
59
|
+
# # ...
|
60
|
+
# end
|
61
|
+
# end
|
62
|
+
#
|
63
|
+
# subject "hello.howdy" do
|
64
|
+
# response do |data, subject|
|
65
|
+
# # The subject at this point is "hello.howdy"
|
66
|
+
# # ...
|
67
|
+
# end
|
68
|
+
# end
|
69
|
+
# end
|
53
70
|
#
|
54
|
-
#
|
55
|
-
#
|
71
|
+
# @example
|
72
|
+
# class FoobarNatsController < RubyNatsController
|
73
|
+
# # ...
|
56
74
|
#
|
57
|
-
#
|
75
|
+
# subject "hello" do
|
76
|
+
# subject "wassup" do
|
58
77
|
# response do |data, subject|
|
59
78
|
# # The subject at this point is "hello.wassup"
|
60
79
|
# # ...
|
61
80
|
# end
|
62
81
|
# end
|
63
82
|
#
|
64
|
-
# subject "
|
83
|
+
# subject "howdy" do
|
65
84
|
# response do |data, subject|
|
66
85
|
# # The subject at this point is "hello.howdy"
|
67
86
|
# # ...
|
68
87
|
# end
|
69
88
|
# end
|
70
89
|
# end
|
71
|
-
#
|
72
|
-
# Example:
|
73
|
-
#
|
74
|
-
# class FoobarNatsController < RubyNatsController
|
75
|
-
# # ...
|
76
|
-
#
|
77
|
-
# subject "hello" do
|
78
|
-
# subject "wassup" do
|
79
|
-
# response do |data, subject|
|
80
|
-
# # The subject at this point is "hello.wassup"
|
81
|
-
# # ...
|
82
|
-
# end
|
83
|
-
# end
|
84
|
-
#
|
85
|
-
# subject "howdy" do
|
86
|
-
# response do |data, subject|
|
87
|
-
# # The subject at this point is "hello.howdy"
|
88
|
-
# # ...
|
89
|
-
# end
|
90
|
-
# end
|
91
|
-
# end
|
92
|
-
# end
|
90
|
+
# end
|
93
91
|
#
|
94
92
|
def subject(subject_segment, queue: nil)
|
95
93
|
subject_chain.push(subject_segment)
|
@@ -101,38 +99,37 @@ module RubyNestNats
|
|
101
99
|
end
|
102
100
|
|
103
101
|
# You can register a response for the built-up subject/pattern string
|
104
|
-
# using the
|
102
|
+
# using the +::response+ macro. Pass a block to +::response+ which
|
105
103
|
# optionally takes two arguments (the same arguments supplied to the block
|
106
|
-
# of
|
104
|
+
# of +RubyNestNats::Client::reply_to+). The result of that block will be
|
107
105
|
# sent as a response to the message received.
|
108
106
|
#
|
109
|
-
#
|
110
|
-
#
|
111
|
-
#
|
112
|
-
# # ...
|
107
|
+
# @example
|
108
|
+
# class FoobarNatsController < RubyNatsController
|
109
|
+
# # ...
|
113
110
|
#
|
114
|
-
#
|
115
|
-
#
|
116
|
-
#
|
117
|
-
#
|
118
|
-
#
|
119
|
-
#
|
120
|
-
#
|
121
|
-
#
|
122
|
-
# end
|
111
|
+
# subject "hello" do
|
112
|
+
# subject "wassup" do
|
113
|
+
# response do |data, subject|
|
114
|
+
# # The subject at this point is "hello.wassup".
|
115
|
+
# # Assume the message sent a JSON payload of {"name":"Bob"}
|
116
|
+
# # in this example.
|
117
|
+
# # We'll reply with a string response:
|
118
|
+
# "I'm all right, #{data['name']}"
|
123
119
|
# end
|
120
|
+
# end
|
124
121
|
#
|
125
|
-
#
|
126
|
-
#
|
127
|
-
#
|
128
|
-
#
|
129
|
-
#
|
130
|
-
#
|
131
|
-
#
|
132
|
-
# end
|
122
|
+
# subject "howdy" do
|
123
|
+
# response do |data, subject|
|
124
|
+
# # The subject at this point is "hello.howdy".
|
125
|
+
# # Assume the message sent a JSON payload of {"name":"Bob"}
|
126
|
+
# # in this example.
|
127
|
+
# # We'll reply with a JSON response (a Ruby +Hash+):
|
128
|
+
# { message: "I'm okay, #{data['name']}. Thanks for asking!" }
|
133
129
|
# end
|
134
130
|
# end
|
135
131
|
# end
|
132
|
+
# end
|
136
133
|
#
|
137
134
|
def response(queue: nil, &block)
|
138
135
|
response_queue = Utils.presence(queue.to_s) || current_queue || default_queue
|
data/lib/ruby_nest_nats/utils.rb
CHANGED