rsmp 0.7.3 → 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ruby-version +1 -0
- data/Gemfile.lock +5 -4
- data/documentation/classes_and_modules.md +1 -4
- data/documentation/collecting_message.md +196 -0
- data/lib/rsmp/cli.rb +4 -0
- data/lib/rsmp/collect/aggregated_status_collector.rb +9 -0
- data/lib/rsmp/collect/collector.rb +132 -86
- data/lib/rsmp/collect/command_query.rb +16 -0
- data/lib/rsmp/collect/command_response_collector.rb +20 -0
- data/lib/rsmp/collect/listener.rb +9 -4
- data/lib/rsmp/collect/message_matchers.rb +0 -64
- data/lib/rsmp/collect/query.rb +2 -2
- data/lib/rsmp/collect/{matcher.rb → state_collector.rb} +13 -15
- data/lib/rsmp/collect/{message_queries.rb → status_query.rb} +1 -16
- data/lib/rsmp/collect/status_response_collector.rb +11 -0
- data/lib/rsmp/collect/status_update_collector.rb +11 -0
- data/lib/rsmp/collect/status_update_or_response_collector.rb +17 -0
- data/lib/rsmp/error.rb +1 -1
- data/lib/rsmp/node.rb +3 -1
- data/lib/rsmp/proxy.rb +9 -13
- data/lib/rsmp/site_proxy.rb +26 -21
- data/lib/rsmp/supervisor.rb +1 -2
- data/lib/rsmp/supervisor_proxy.rb +6 -5
- data/lib/rsmp/tlc/signal_group.rb +1 -1
- data/lib/rsmp/version.rb +1 -1
- data/lib/rsmp.rb +8 -3
- metadata +13 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5316c50ad6cd09d30e7d1baab78e717fac4656c06178272ef4adc1c6647fb544
|
4
|
+
data.tar.gz: 6ef4d635b42f3eac19b94b68bbcb05c59ce94de96e0e27f1f5c7a6deefd4e470
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1947906505e532d0d47d93f1d9fe2c8c3199ff58d378b9be3df18865339e966a6ad5f74512aa168ee4a5d641624cf7b0f170436d2c11e4f495bd7d6b88be502f
|
7
|
+
data.tar.gz: ee0ecbb229637276d6cec21ccacc6414199ad7f0392324633231cb4a8632a8b64b1aa2ba5abd979a7699ed6721a5a40b9d9c531f45dc0f59345149662e608b12
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
3.0.3
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rsmp (0.
|
4
|
+
rsmp (0.8.1)
|
5
5
|
async (~> 1.29.1)
|
6
6
|
async-io (~> 1.32.1)
|
7
7
|
colorize (~> 0.8.1)
|
@@ -34,7 +34,7 @@ GEM
|
|
34
34
|
childprocess (4.1.0)
|
35
35
|
colorize (0.8.1)
|
36
36
|
concurrent-ruby (1.1.9)
|
37
|
-
console (1.
|
37
|
+
console (1.14.0)
|
38
38
|
fiber-local
|
39
39
|
contracts (0.17)
|
40
40
|
cucumber (6.1.0)
|
@@ -95,7 +95,7 @@ GEM
|
|
95
95
|
thor
|
96
96
|
thread_safe
|
97
97
|
rake (13.0.3)
|
98
|
-
regexp_parser (2.
|
98
|
+
regexp_parser (2.2.0)
|
99
99
|
rsmp_schemer (0.3.2)
|
100
100
|
json_schemer (~> 0.2.18)
|
101
101
|
rspec (3.10.0)
|
@@ -124,6 +124,7 @@ GEM
|
|
124
124
|
|
125
125
|
PLATFORMS
|
126
126
|
x86_64-darwin-20
|
127
|
+
x86_64-darwin-21
|
127
128
|
|
128
129
|
DEPENDENCIES
|
129
130
|
aruba (~> 1.1.2)
|
@@ -136,4 +137,4 @@ DEPENDENCIES
|
|
136
137
|
timecop (~> 0.9.4)
|
137
138
|
|
138
139
|
BUNDLED WITH
|
139
|
-
2.2.
|
140
|
+
2.2.32
|
@@ -19,9 +19,6 @@ Handle logging.
|
|
19
19
|
### Wait
|
20
20
|
Handles waiting for an async condition and block.
|
21
21
|
|
22
|
-
### SiteProxyWait
|
23
|
-
Handles waiting for different types of messages and responses from a remote site.
|
24
|
-
|
25
22
|
### Components
|
26
23
|
Component handling.
|
27
24
|
|
@@ -38,7 +35,7 @@ A Site has one or more SupervisorProxies (connections to supervisor).
|
|
38
35
|
|
39
36
|
A site has one of more components.
|
40
37
|
|
41
|
-
### Supervisor
|
38
|
+
### Supervisor
|
42
39
|
A Supervisor represents an RSMP supervisor, typically a central supervisor system. An RSMP supervisor can handle connections one or more sites.
|
43
40
|
|
44
41
|
A Supervisor has one or more SiteProxies (connections to sites).
|
@@ -0,0 +1,196 @@
|
|
1
|
+
# Collection
|
2
|
+
You often need to collect messages or responses. The collector classes are used to collect message asyncronously. Other tasks continue until the collection completes, time outs or is cancelled.
|
3
|
+
|
4
|
+
A collector can collect ingoing and/or outgoing messages.
|
5
|
+
|
6
|
+
An object that includes the Notifier module (or implements the same functionality) must be provided when you construct a Collected. The collector will attach itself to this notifier when it starts collecting, to receive messages. The SiteProxy and SupervisorProxy classes both include the Notifier module, and can therefore be used as message sources.
|
7
|
+
|
8
|
+
Messages that match the relevant criteria are stored by the collector.
|
9
|
+
|
10
|
+
When the collection is done, the collector detaches from the notifier, and returns the status.
|
11
|
+
|
12
|
+
|
13
|
+
## Collector
|
14
|
+
Class uses for collecting messages filtered by message type, direction and/or component id. A block can be used for custom filtering.
|
15
|
+
|
16
|
+
You can choose to collect a specific number of message and/or for a specific duration.
|
17
|
+
|
18
|
+
A collector has a status, which is `:ready` initialialy. When you start collecting, it changes to `:collecting`. It will be `:ok` once collection completes successfully, or `:cancel` if it was cancelled to to some error or by a filter block.
|
19
|
+
|
20
|
+
### Initialization
|
21
|
+
When you create a collector, you specify the messages types you want to collect.
|
22
|
+
You can also specify ingoing and/or outgoing direction and the RSMP component.
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
collector = MessageCollector.new notifier, num: 10, ingoing: true, outgoing: true
|
26
|
+
```
|
27
|
+
|
28
|
+
num: The number of messages to collect. If not provided, a timeout must be set instead.
|
29
|
+
timeout: The number of seconds to collect
|
30
|
+
ingoing: Whether to collect ingoing messages. Defaults to true
|
31
|
+
outgoing: Whether to collect outgoing messages. Defaults to true
|
32
|
+
component: An RSMP component id.
|
33
|
+
|
34
|
+
### Collecting
|
35
|
+
Use collect() to start collecting and wait for completion or timeout. The status will be returned.
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
result = collector.collect # => :ok, :timeout or :cancelled
|
39
|
+
collector.messages # => collected messages
|
40
|
+
```
|
41
|
+
|
42
|
+
If you want start collection, but not wait for the result, use `start()`. You can then later use `wait()` if you want:
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
result = collector.start # => nil
|
46
|
+
# do other stuff
|
47
|
+
result = collector.wait
|
48
|
+
```
|
49
|
+
|
50
|
+
### Custom filtering
|
51
|
+
You can use a block to do extra filtering. The block will be callled for each messages that fulfils the correct message type, direction and component id.
|
52
|
+
|
53
|
+
The block must return nil or a list of symbols to indicate whether the message should be kept, and whether collection should be cancelled.
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
result = collector.collect do |message|
|
57
|
+
:keep, :cancel # example of how to keep the message and cancel collection
|
58
|
+
end
|
59
|
+
```
|
60
|
+
|
61
|
+
`:keep` keeps (collect) this message
|
62
|
+
`:cancel` cancel collection
|
63
|
+
|
64
|
+
Note that you cannot use `return` in a block. You can either simply provide the values as the last expresssion in the block, or use next().
|
65
|
+
|
66
|
+
Exceptions in the block will cause the collector to abort. If the collect! or wait! variants are used, the exception is propagated to the caller.
|
67
|
+
|
68
|
+
### Bang version
|
69
|
+
The method collect!() will raise exceptions in case of errors, and will return the collect message directly.
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
message = collector.collect # => collected message.
|
73
|
+
```
|
74
|
+
|
75
|
+
Similar, `wait!()` will raise an exception in case of timeouts or errors:
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
message = collector.wait! # => collected message.
|
79
|
+
```
|
80
|
+
|
81
|
+
|
82
|
+
### Schema Errors and Disconnects
|
83
|
+
The collector can optionally cancel collection in special cases, controlled by the `:cancel` option provided when contructing the collector.
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
options = {
|
87
|
+
cancel: {
|
88
|
+
disconnect: true,
|
89
|
+
schema_error: true
|
90
|
+
}
|
91
|
+
}
|
92
|
+
result = collector.collect options
|
93
|
+
```
|
94
|
+
|
95
|
+
disconnect: If the proxy which provides messages experience a disconnect, the collector will cancel collection.
|
96
|
+
|
97
|
+
schema_error: If the proxy receives a message with a schema error, the collector will cancel collection, if the the invalid message has the correct message type.
|
98
|
+
|
99
|
+
### NotAck
|
100
|
+
A typical scenaria is that you send a command or status request, and want to collect the response. But if the original message is rejected by the site, you will received a NotAck instead of a reply. The collector classes can handle this, as long as you provide the message id of the original request in the `m_id` key of teh options when you construct the collector.
|
101
|
+
|
102
|
+
If a NotAck is received with a matching `oMId` (original message id), the collection is cancelled.
|
103
|
+
|
104
|
+
## StatusCollector
|
105
|
+
Waits for a set of status criteria to be met.
|
106
|
+
|
107
|
+
Note that a single RSMP status message can contain multiple status items. Unlike MessageCollector, a StatusCollector therefore operates on items, rather than messages, and you can't specify a number of messages to collect.
|
108
|
+
|
109
|
+
|
110
|
+
### Criteria
|
111
|
+
You construct a StatusCollector with set of criteria, specifying the status codes, names, and optionally values that must be met.
|
112
|
+
|
113
|
+
### Collecting
|
114
|
+
When you start collection, it will complete once all criteria are all fulfilled, the timeout is reached or a custom filtering block aborts the collection.
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
collector = StatusCollector.new(options)
|
118
|
+
result = matcher.collect(timeout: 5)
|
119
|
+
```
|
120
|
+
|
121
|
+
### Custom filtering
|
122
|
+
You can use a block to do extra filtering. The block will be called for each individual status item that fulfils all criteria, like status code and name, component, etc.
|
123
|
+
|
124
|
+
Like with MessageCollector, the block must return a hash specifing whether to keep the message and whether to continue collection.
|
125
|
+
|
126
|
+
```ruby
|
127
|
+
matcher = StatusCollector.new(options)
|
128
|
+
result = matcher.collect(options) do |message,item|
|
129
|
+
next(:keep) if good_item?(item) # keep item
|
130
|
+
end
|
131
|
+
```
|
132
|
+
|
133
|
+
## Subscribing to status updates
|
134
|
+
The method `subscribe_to_status` can be used to subscribe to one of more status messages.
|
135
|
+
|
136
|
+
### Without collection
|
137
|
+
The simple form sends an RSMP status subscription message to the site and then returns immediatly. To collect incoming status messages, you need to manually use e.g. a Collector.
|
138
|
+
|
139
|
+
A hash is returned, with `:sent` containing the send subscription messages.
|
140
|
+
|
141
|
+
```ruby
|
142
|
+
options = {
|
143
|
+
list: [{'sCI'=>'S0001','n'=>'signalgroupstatus'}],
|
144
|
+
}
|
145
|
+
result = subscribe_to_status(options)
|
146
|
+
result.keys => # [:sent]
|
147
|
+
```
|
148
|
+
|
149
|
+
Note: If you want to use this simple form and manually collect responses, it's best to start collection in an asyncronous task _before_ you subscribe, to make sure you don't miss early responses:
|
150
|
+
|
151
|
+
```ruby
|
152
|
+
task = async do
|
153
|
+
MessageCollector.new(options).collect(num: 5, timeout:10) # start listening for status messages
|
154
|
+
end
|
155
|
+
result = subscribe_to_status(options) # subscribe
|
156
|
+
task.wait # wait for collection task to complete (or time out)
|
157
|
+
```
|
158
|
+
|
159
|
+
### With collection
|
160
|
+
If you provide `:collect` options, it will be used to construct a StatusUpdateCollector for collecting the relevant status messages. When collection completes the collector is returned in the `:collector` key:
|
161
|
+
|
162
|
+
```ruby
|
163
|
+
options = {
|
164
|
+
list: [{'sCI'=>'S0001','n'=>'signalgroupstatus'}],
|
165
|
+
collect: {timeout: 5}
|
166
|
+
}
|
167
|
+
result = subscribe_to_status(options)
|
168
|
+
result.keys => # [:sent, :collector]
|
169
|
+
result[:collector].messages # => list of collected messages
|
170
|
+
```
|
171
|
+
|
172
|
+
You can pass you own collector which will give you more control of how to collect the incoming status messages:
|
173
|
+
|
174
|
+
```ruby
|
175
|
+
collector = Collector.new(options)
|
176
|
+
options = {collect: collector}
|
177
|
+
result = subscribe_to_status(options)
|
178
|
+
result.keys => # [:sent, :collector]
|
179
|
+
result[:collector].messages # => list of collected messages
|
180
|
+
```
|
181
|
+
|
182
|
+
### Processing responses
|
183
|
+
If you pass a block, the block will be used to construct a collector. The block will be called for each matching status item received.
|
184
|
+
Collection will continue until the block returns :cancel, or it times.
|
185
|
+
|
186
|
+
```ruby
|
187
|
+
options = {
|
188
|
+
list: [{'sCI'=>'S0001','n'=>'signalgroupstatus'}]
|
189
|
+
}
|
190
|
+
result = subscribe_to_status(options) do |message|
|
191
|
+
# do something with message
|
192
|
+
:keep # or not
|
193
|
+
end
|
194
|
+
result.keys => # [:sent, :collector]
|
195
|
+
```
|
196
|
+
|
data/lib/rsmp/cli.rb
CHANGED
@@ -0,0 +1,9 @@
|
|
1
|
+
module RSMP
|
2
|
+
# Class for waiting for an aggregated status response
|
3
|
+
class AggregatedStatusCollector < Collector
|
4
|
+
def initialize proxy, options={}
|
5
|
+
required = { type: ['AggregatedStatus','MessageNotAck'], title: 'aggregated status' }
|
6
|
+
super proxy, options.merge(required)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
@@ -1,9 +1,10 @@
|
|
1
1
|
module RSMP
|
2
2
|
|
3
|
-
# Collects
|
4
|
-
# Can filter by message type and
|
3
|
+
# Collects messages from a notifier.
|
4
|
+
# Can filter by message type, componet and direction.
|
5
|
+
# Wakes up the once the desired number of messages has been collected.
|
5
6
|
class Collector < Listener
|
6
|
-
attr_reader :condition, :messages, :
|
7
|
+
attr_reader :condition, :messages, :status, :error, :task
|
7
8
|
|
8
9
|
def initialize proxy, options={}
|
9
10
|
super proxy, options
|
@@ -17,16 +18,51 @@ module RSMP
|
|
17
18
|
@outgoing = options[:outgoing] == nil ? false : options[:outgoing]
|
18
19
|
@condition = Async::Notification.new
|
19
20
|
@title = options[:title] || [@options[:type]].flatten.join('/')
|
20
|
-
@options[:
|
21
|
-
@options[:num] ||= 1
|
21
|
+
@task = options[:task]
|
22
22
|
reset
|
23
23
|
end
|
24
24
|
|
25
|
+
def use_task task
|
26
|
+
@task = task
|
27
|
+
end
|
28
|
+
|
29
|
+
# Clear all query results
|
30
|
+
def reset
|
31
|
+
@messages = []
|
32
|
+
@error = nil
|
33
|
+
@status = :ready
|
34
|
+
end
|
35
|
+
|
25
36
|
# Inspect formatter that shows the message we have collected
|
26
37
|
def inspect
|
27
38
|
"#<#{self.class.name}:#{self.object_id}, #{inspector(:@messages)}>"
|
28
39
|
end
|
29
40
|
|
41
|
+
# Is collection active?
|
42
|
+
def collecting?
|
43
|
+
@status == :collecting
|
44
|
+
end
|
45
|
+
|
46
|
+
# Is collection active?
|
47
|
+
def ok?
|
48
|
+
@status == :ok
|
49
|
+
end
|
50
|
+
|
51
|
+
# Has collection time out?
|
52
|
+
def timeout?
|
53
|
+
@status == :timeout
|
54
|
+
end
|
55
|
+
|
56
|
+
# Is collection ready to start?
|
57
|
+
def ready?
|
58
|
+
@status == :ready
|
59
|
+
end
|
60
|
+
|
61
|
+
# Has collection been cancelled?
|
62
|
+
def cancelled?
|
63
|
+
@status == :cancelled
|
64
|
+
end
|
65
|
+
|
30
66
|
# Want ingoing messages?
|
31
67
|
def ingoing?
|
32
68
|
@ingoing == true
|
@@ -37,90 +73,105 @@ module RSMP
|
|
37
73
|
@outgoing == true
|
38
74
|
end
|
39
75
|
|
40
|
-
#
|
41
|
-
|
42
|
-
|
76
|
+
# Collect message
|
77
|
+
# Will return once all messages have been collected, or timeout is reached
|
78
|
+
def collect &block
|
79
|
+
start &block
|
80
|
+
wait
|
81
|
+
@status
|
82
|
+
ensure
|
83
|
+
@notifier.remove_listener self
|
43
84
|
end
|
44
85
|
|
45
86
|
# Collect message
|
46
|
-
#
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
@block = block
|
51
|
-
unless @done
|
52
|
-
listen do
|
53
|
-
task.with_timeout(@options[:timeout]) do
|
54
|
-
@condition.wait
|
55
|
-
end
|
56
|
-
end
|
87
|
+
# Returns the collected messages, or raise an exception in case of a time out.
|
88
|
+
def collect! &block
|
89
|
+
if collect(&block) == :timeout
|
90
|
+
raise RSMP::TimeoutError.new describe_progress
|
57
91
|
end
|
58
|
-
|
59
|
-
self
|
60
|
-
rescue Async::TimeoutError
|
61
|
-
str = "#{@title.capitalize} collection"
|
62
|
-
str << " in response to #{options[:m_id]}" if options[:m_id]
|
63
|
-
str << " didn't complete within #{@options[:timeout]}s"
|
64
|
-
reached = progress
|
65
|
-
str << ", reached #{progress[:reached]}/#{progress[:need]}"
|
66
|
-
raise RSMP::TimeoutError.new str
|
92
|
+
@messages
|
67
93
|
end
|
68
94
|
|
69
|
-
#
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
95
|
+
# If collection is not active, return status immeditatly. Otherwise wait until
|
96
|
+
# the desired messages have been collected, or timeout is reached.
|
97
|
+
def wait
|
98
|
+
if collecting?
|
99
|
+
if @options[:timeout]
|
100
|
+
@task.with_timeout(@options[:timeout]) { @condition.wait }
|
101
|
+
else
|
102
|
+
@condition.wait
|
103
|
+
end
|
104
|
+
end
|
105
|
+
@status
|
106
|
+
rescue Async::TimeoutError
|
107
|
+
@status = :timeout
|
74
108
|
end
|
75
109
|
|
76
|
-
#
|
77
|
-
|
78
|
-
|
110
|
+
# If collection is not active, raise an error. Otherwise wait until
|
111
|
+
# the desired messages have been collected.
|
112
|
+
# If timeout is reached, an exceptioin is raised.
|
113
|
+
def wait!
|
114
|
+
wait
|
115
|
+
raise RSMP::TimeoutError.new(describe_progress) if timeout?
|
116
|
+
@messages
|
79
117
|
end
|
80
118
|
|
81
|
-
#
|
82
|
-
|
83
|
-
|
119
|
+
# Start collection and return immediately
|
120
|
+
# You can later use wait() to wait for completion
|
121
|
+
def start &block
|
122
|
+
raise RuntimeError.new("Can't begin unless ready (currenty #{@status})") unless ready?
|
123
|
+
@block = block
|
124
|
+
raise ArgumentError.new("Num, timeout or block must be provided") unless @options[:num] || @options[:timeout] || @block
|
125
|
+
reset
|
126
|
+
@status = :collecting
|
127
|
+
@notifier.add_listener self if @notifier
|
84
128
|
end
|
85
129
|
|
86
|
-
#
|
87
|
-
def
|
88
|
-
|
89
|
-
@
|
90
|
-
@
|
130
|
+
# Build a string describing how how progress reached before timeout
|
131
|
+
def describe_progress
|
132
|
+
str = "#{@title.capitalize} collection "
|
133
|
+
str << "in response to #{@options[:m_id]} " if @options[:m_id]
|
134
|
+
str << "didn't complete within #{@options[:timeout]}s, "
|
135
|
+
str << "reached #{@messages.size}/#{@options[:num]}"
|
136
|
+
str
|
91
137
|
end
|
92
138
|
|
93
139
|
# Check if we receive a NotAck related to initiating request, identified by @m_id.
|
94
|
-
def
|
140
|
+
def reject_not_ack message
|
95
141
|
return unless @options[:m_id]
|
96
142
|
if message.is_a?(MessageNotAck)
|
97
143
|
if message.attribute('oMId') == @options[:m_id]
|
98
144
|
m_id_short = RSMP::Message.shorten_m_id @options[:m_id], 8
|
99
|
-
|
100
|
-
|
145
|
+
cancel RSMP::MessageRejected.new("#{@title} #{m_id_short} was rejected with '#{message.attribute('rea')}'")
|
146
|
+
true
|
101
147
|
end
|
102
|
-
false
|
103
148
|
end
|
104
149
|
end
|
105
150
|
|
106
151
|
# Handle message. and return true when we're done collecting
|
107
152
|
def notify message
|
108
153
|
raise ArgumentError unless message
|
109
|
-
raise RuntimeError.new("can't process message when
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
@done
|
154
|
+
raise RuntimeError.new("can't process message when done") unless ready? || collecting?
|
155
|
+
unless reject_not_ack(message)
|
156
|
+
perform_match message
|
157
|
+
end
|
158
|
+
@status
|
115
159
|
end
|
116
160
|
|
117
161
|
# Match message against our collection criteria
|
118
|
-
def
|
119
|
-
|
120
|
-
if
|
162
|
+
def perform_match message
|
163
|
+
return unless type_match?(message)
|
164
|
+
if @block
|
165
|
+
status = [@block.call(message)].flatten
|
166
|
+
keep message if status.include?(:keep)
|
167
|
+
if status.include?(:cancel)
|
168
|
+
cancel('Cancelled by block')
|
169
|
+
else
|
170
|
+
complete if done?
|
171
|
+
end
|
172
|
+
else
|
121
173
|
keep message
|
122
|
-
|
123
|
-
forget message
|
174
|
+
complete if done?
|
124
175
|
end
|
125
176
|
end
|
126
177
|
|
@@ -132,8 +183,14 @@ module RSMP
|
|
132
183
|
# Called when we're done collecting. Remove ourself as a listener,
|
133
184
|
# se we don't receive message notifications anymore
|
134
185
|
def complete
|
135
|
-
@
|
136
|
-
|
186
|
+
@status = :ok
|
187
|
+
do_stop
|
188
|
+
end
|
189
|
+
|
190
|
+
# Remove ourself as a listener, so we don't receive message notifications anymore,
|
191
|
+
# and wake up the async condition
|
192
|
+
def do_stop
|
193
|
+
@notifier.remove_listener self
|
137
194
|
@condition.signal
|
138
195
|
end
|
139
196
|
|
@@ -143,7 +200,7 @@ module RSMP
|
|
143
200
|
case error
|
144
201
|
when RSMP::SchemaError
|
145
202
|
notify_schema_error error, options
|
146
|
-
when RSMP::
|
203
|
+
when RSMP::DisconnectError
|
147
204
|
notify_disconnect error, options
|
148
205
|
end
|
149
206
|
end
|
@@ -154,24 +211,23 @@ module RSMP
|
|
154
211
|
message = options[:message]
|
155
212
|
return unless message
|
156
213
|
klass = message.class.name.split('::').last
|
157
|
-
return unless [@options[:type]].flatten.include?
|
158
|
-
@
|
214
|
+
return unless @options[:type] == nil || [@options[:type]].flatten.include?(klass)
|
215
|
+
@notifier.log "Collection cancelled due to schema error in #{klass} #{message.m_id_short}", level: :debug
|
159
216
|
cancel error
|
160
217
|
end
|
161
218
|
|
162
219
|
# Cancel if we received e notificaiton about a disconnect
|
163
220
|
def notify_disconnect error, options
|
164
221
|
return unless @options.dig(:cancel,:disconnect)
|
165
|
-
@
|
222
|
+
@notifier.log "Collection cancelled due to a connection error: #{error.to_s}", level: :debug
|
166
223
|
cancel error
|
167
224
|
end
|
168
225
|
|
169
226
|
# Abort collection
|
170
227
|
def cancel error
|
171
|
-
@error = error
|
172
|
-
@
|
173
|
-
|
174
|
-
@condition.signal
|
228
|
+
@error = error
|
229
|
+
@status = :cancelled
|
230
|
+
do_stop
|
175
231
|
end
|
176
232
|
|
177
233
|
# Store a message in the result array
|
@@ -179,30 +235,20 @@ module RSMP
|
|
179
235
|
@messages << message
|
180
236
|
end
|
181
237
|
|
182
|
-
# Remove a message from the result array
|
183
|
-
def forget message
|
184
|
-
@messages.delete message
|
185
|
-
end
|
186
|
-
|
187
238
|
# Check a message against our match criteria
|
188
|
-
# Return true if there's a match
|
189
|
-
def
|
190
|
-
|
191
|
-
return if message.direction == :
|
192
|
-
return if message.direction == :out && @outgoing == false
|
239
|
+
# Return true if there's a match, false if not
|
240
|
+
def type_match? message
|
241
|
+
return false if message.direction == :in && @ingoing == false
|
242
|
+
return false if message.direction == :out && @outgoing == false
|
193
243
|
if @options[:type]
|
194
|
-
return if message == nil
|
195
244
|
if @options[:type].is_a? Array
|
196
|
-
return unless @options[:type].include? message.type
|
245
|
+
return false unless @options[:type].include? message.type
|
197
246
|
else
|
198
|
-
return unless message.type == @options[:type]
|
247
|
+
return false unless message.type == @options[:type]
|
199
248
|
end
|
200
249
|
end
|
201
250
|
if @options[:component]
|
202
|
-
return if message.attributes['cId'] && message.attributes['cId'] != @options[:component]
|
203
|
-
end
|
204
|
-
if @block
|
205
|
-
return if @block.call(message) == false
|
251
|
+
return false if message.attributes['cId'] && message.attributes['cId'] != @options[:component]
|
206
252
|
end
|
207
253
|
true
|
208
254
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module RSMP
|
2
|
+
# Match a specific command responses
|
3
|
+
class CommandQuery < Query
|
4
|
+
# Match a return value item against a query
|
5
|
+
def match? item
|
6
|
+
return nil if @want['cCI'] && @want['cCI'] != item['cCI']
|
7
|
+
return nil if @want['n'] && @want['n'] != item['n']
|
8
|
+
if @want['v'].is_a? Regexp
|
9
|
+
return false if @want['v'] && item['v'] !~ @want['v']
|
10
|
+
else
|
11
|
+
return false if @want['v'] && item['v'] != @want['v']
|
12
|
+
end
|
13
|
+
true
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module RSMP
|
2
|
+
# Class for waiting for specific command responses
|
3
|
+
class CommandResponseCollector < StateCollector
|
4
|
+
def initialize proxy, want, options={}
|
5
|
+
super proxy, want, options.merge(
|
6
|
+
type: ['CommandResponse','MessageNotAck'],
|
7
|
+
title:'command response'
|
8
|
+
)
|
9
|
+
end
|
10
|
+
|
11
|
+
def build_query want
|
12
|
+
CommandQuery.new want
|
13
|
+
end
|
14
|
+
|
15
|
+
# Get items, in our case the return values
|
16
|
+
def get_items message
|
17
|
+
message.attributes['rvs']
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -5,8 +5,13 @@ module RSMP
|
|
5
5
|
class Listener
|
6
6
|
include Inspect
|
7
7
|
|
8
|
-
def initialize
|
9
|
-
@
|
8
|
+
def initialize notifier, options={}
|
9
|
+
@notifier = notifier
|
10
|
+
end
|
11
|
+
|
12
|
+
def change_notifier notifier
|
13
|
+
@notifier.remove_listener self if @notifier
|
14
|
+
@notifier = notifier
|
10
15
|
end
|
11
16
|
|
12
17
|
def notify message
|
@@ -16,10 +21,10 @@ module RSMP
|
|
16
21
|
end
|
17
22
|
|
18
23
|
def listen &block
|
19
|
-
@
|
24
|
+
@notifier.add_listener self
|
20
25
|
yield
|
21
26
|
ensure
|
22
|
-
@
|
27
|
+
@notifier.remove_listener self
|
23
28
|
end
|
24
29
|
|
25
30
|
end
|
@@ -1,64 +0,0 @@
|
|
1
|
-
module RSMP
|
2
|
-
# Class for waiting for specific command responses
|
3
|
-
class CommandResponseMatcher < Matcher
|
4
|
-
def initialize proxy, want, options={}
|
5
|
-
super proxy, want, options.merge(
|
6
|
-
type: ['CommandResponse','MessageNotAck'],
|
7
|
-
title:'command response'
|
8
|
-
)
|
9
|
-
end
|
10
|
-
|
11
|
-
def build_query want
|
12
|
-
CommandQuery.new want
|
13
|
-
end
|
14
|
-
|
15
|
-
# Get items, in our case the return values
|
16
|
-
def get_items message
|
17
|
-
message.attributes['rvs']
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
# Base class for waiting for status updates or responses
|
22
|
-
class StatusUpdateOrResponseMatcher < Matcher
|
23
|
-
def initialize proxy, want, options={}
|
24
|
-
super proxy, want, options.merge
|
25
|
-
end
|
26
|
-
|
27
|
-
def build_query want
|
28
|
-
StatusQuery.new want
|
29
|
-
end
|
30
|
-
|
31
|
-
# Get items, in our case status values
|
32
|
-
def get_items message
|
33
|
-
message.attributes['sS']
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
# Class for waiting for specific status responses
|
38
|
-
class StatusResponseMatcher < StatusUpdateOrResponseMatcher
|
39
|
-
def initialize proxy, want, options={}
|
40
|
-
super proxy, want, options.merge(
|
41
|
-
type: ['StatusResponse','MessageNotAck'],
|
42
|
-
title: 'status response'
|
43
|
-
)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
# Class for waiting for specific status responses
|
48
|
-
class StatusUpdateMatcher < StatusUpdateOrResponseMatcher
|
49
|
-
def initialize proxy, want, options={}
|
50
|
-
super proxy, want, options.merge(
|
51
|
-
type: ['StatusUpdate','MessageNotAck'],
|
52
|
-
title:'status update'
|
53
|
-
)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
# Class for waiting for an aggregated status response
|
58
|
-
class AggregatedStatusMatcher < Collector
|
59
|
-
def initialize proxy, options={}
|
60
|
-
required = { type: ['AggregatedStatus','MessageNotAck'], title: 'aggregated status' }
|
61
|
-
super proxy, options.merge(required)
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
data/lib/rsmp/collect/query.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module RSMP
|
2
|
-
|
2
|
+
|
3
3
|
# Class that matches a single status or command item
|
4
4
|
class Query
|
5
5
|
attr_reader :want, :got, :message
|
@@ -18,7 +18,7 @@ module RSMP
|
|
18
18
|
|
19
19
|
# Check an item and set @done to true if it matches
|
20
20
|
# Store the item and corresponding message if there's a positive or negative match
|
21
|
-
def
|
21
|
+
def perform_match item, message
|
22
22
|
matched = match? item
|
23
23
|
if matched != nil
|
24
24
|
@message = message
|
@@ -31,15 +31,14 @@ module RSMP
|
|
31
31
|
# {"cCI"=>"M0104", "cO"=>"setDate", "n"=>"month", "v"=>/\d+/} =>
|
32
32
|
# { <StatusResponse message>, {"cCI"=>"M0104", "cO"=>"setDate", "n"=>"month", "v"=>"9"} }
|
33
33
|
# }
|
34
|
-
|
35
|
-
class Matcher < Collector
|
34
|
+
class StateCollector < Collector
|
36
35
|
attr_reader :queries
|
37
36
|
|
38
37
|
# Initialize with a list of wanted statuses
|
39
38
|
def initialize proxy, want, options={}
|
39
|
+
raise ArgumentError.new("num option cannot be used") if options[:num]
|
40
40
|
super proxy, options.merge( ingoing: true, outgoing: false)
|
41
41
|
@queries = want.map { |item| build_query item }
|
42
|
-
@want = want
|
43
42
|
end
|
44
43
|
|
45
44
|
# Build a query object.
|
@@ -60,11 +59,6 @@ module RSMP
|
|
60
59
|
@queries.map { |query| query.got }.compact
|
61
60
|
end
|
62
61
|
|
63
|
-
# get the first message. Useful when you only collect one mesage
|
64
|
-
def message
|
65
|
-
@queries.first.message
|
66
|
-
end
|
67
|
-
|
68
62
|
# Get messages from results
|
69
63
|
def messages
|
70
64
|
@queries.map { |query| query.message }.uniq
|
@@ -77,14 +71,14 @@ module RSMP
|
|
77
71
|
{ need: need, reached: reached }
|
78
72
|
end
|
79
73
|
|
80
|
-
# Are there queries left to
|
74
|
+
# Are there queries left to type_match?
|
81
75
|
def done?
|
82
76
|
@queries.all? { |query| query.done? }
|
83
77
|
end
|
84
78
|
|
85
79
|
# Get a simplified hash of queries, with values set to either true or false,
|
86
80
|
# indicating which queries have been matched.
|
87
|
-
def
|
81
|
+
def query_status
|
88
82
|
@queries.map { |query| [query.want, query.done?] }.to_h
|
89
83
|
end
|
90
84
|
|
@@ -95,19 +89,23 @@ module RSMP
|
|
95
89
|
|
96
90
|
# Check if a messages matches our criteria.
|
97
91
|
# Match each query against each item in the message
|
98
|
-
def
|
99
|
-
return unless
|
92
|
+
def perform_match message
|
93
|
+
return unless type_match?(message)
|
100
94
|
@queries.each do |query| # look through queries
|
101
95
|
get_items(message).each do |item| # look through items in message
|
102
|
-
matched = query.
|
96
|
+
matched = query.perform_match(item,message)
|
97
|
+
if matched == true
|
98
|
+
matched = @block.call(message,item) if @block
|
99
|
+
end
|
103
100
|
if matched != nil
|
104
101
|
type = {true=>'match',false=>'mismatch'}[matched]
|
105
|
-
@
|
102
|
+
@notifier.log "#{@title.capitalize} #{message.m_id_short} collect #{type} #{query.want}, item #{item}", level: :debug
|
106
103
|
break
|
107
104
|
end
|
108
105
|
end
|
109
106
|
end
|
110
|
-
|
107
|
+
complete if done?
|
108
|
+
@notifier.log "#{@title.capitalize} collect reached #{summary}", level: :debug
|
111
109
|
end
|
112
110
|
end
|
113
111
|
end
|
@@ -1,20 +1,5 @@
|
|
1
1
|
module RSMP
|
2
|
-
# Match a specific
|
3
|
-
class CommandQuery < Query
|
4
|
-
# Match a return value item against a query
|
5
|
-
def match? item
|
6
|
-
return nil if @want['cCI'] && @want['cCI'] != item['cCI']
|
7
|
-
return nil if @want['n'] && @want['n'] != item['n']
|
8
|
-
if @want['v'].is_a? Regexp
|
9
|
-
return false if @want['v'] && item['v'] !~ @want['v']
|
10
|
-
else
|
11
|
-
return false if @want['v'] && item['v'] != @want['v']
|
12
|
-
end
|
13
|
-
true
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
# Match a specific status response or update
|
2
|
+
# Match a specific status response or update
|
18
3
|
class StatusQuery < Query
|
19
4
|
# Match a status value against a query
|
20
5
|
def match? item
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module RSMP
|
2
|
+
# Class for waiting for specific status responses
|
3
|
+
class StatusResponseCollector < StatusUpdateOrResponseCollector
|
4
|
+
def initialize proxy, want, options={}
|
5
|
+
super proxy, want, options.merge(
|
6
|
+
type: ['StatusResponse','MessageNotAck'],
|
7
|
+
title: 'status response'
|
8
|
+
)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module RSMP
|
2
|
+
# Class for waiting for specific status responses
|
3
|
+
class StatusUpdateCollector < StatusUpdateOrResponseCollector
|
4
|
+
def initialize proxy, want, options={}
|
5
|
+
super proxy, want, options.merge(
|
6
|
+
type: ['StatusUpdate','MessageNotAck'],
|
7
|
+
title:'status update'
|
8
|
+
)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module RSMP
|
2
|
+
# Base class for waiting for status updates or responses
|
3
|
+
class StatusUpdateOrResponseCollector < StateCollector
|
4
|
+
def initialize proxy, want, options={}
|
5
|
+
super proxy, want, options.merge
|
6
|
+
end
|
7
|
+
|
8
|
+
def build_query want
|
9
|
+
RSMP::StatusQuery.new want
|
10
|
+
end
|
11
|
+
|
12
|
+
# Get items, in our case status values
|
13
|
+
def get_items message
|
14
|
+
message.attributes['sS']
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/rsmp/error.rb
CHANGED
data/lib/rsmp/node.rb
CHANGED
@@ -6,7 +6,7 @@ module RSMP
|
|
6
6
|
include Wait
|
7
7
|
include Inspect
|
8
8
|
|
9
|
-
attr_reader :archive, :logger, :task, :deferred, :error_queue, :clock
|
9
|
+
attr_reader :archive, :logger, :task, :deferred, :error_queue, :clock, :collector
|
10
10
|
|
11
11
|
def initialize options
|
12
12
|
initialize_logging options
|
@@ -15,6 +15,8 @@ module RSMP
|
|
15
15
|
@clock = Clock.new
|
16
16
|
@error_queue = Async::Queue.new
|
17
17
|
@ignore_errors = []
|
18
|
+
options[:collector]
|
19
|
+
@collect = options[:collect]
|
18
20
|
end
|
19
21
|
|
20
22
|
def ignore_errors classes, &block
|
data/lib/rsmp/proxy.rb
CHANGED
@@ -15,9 +15,8 @@ module RSMP
|
|
15
15
|
|
16
16
|
def initialize options
|
17
17
|
initialize_logging options
|
18
|
-
setup options
|
19
18
|
initialize_distributor
|
20
|
-
|
19
|
+
setup options
|
21
20
|
clear
|
22
21
|
end
|
23
22
|
|
@@ -37,6 +36,10 @@ module RSMP
|
|
37
36
|
@sxl = nil
|
38
37
|
@site_settings = nil # can't pick until we know the site id
|
39
38
|
@state = :stopped
|
39
|
+
if options[:collect]
|
40
|
+
@collector = RSMP::Collector.new self, options[:collect]
|
41
|
+
@collector.start
|
42
|
+
end
|
40
43
|
end
|
41
44
|
|
42
45
|
def inspect
|
@@ -49,16 +52,9 @@ module RSMP
|
|
49
52
|
node.clock
|
50
53
|
end
|
51
54
|
|
52
|
-
def
|
53
|
-
|
54
|
-
|
55
|
-
add_listener @collector
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def collect task, options, &block
|
60
|
-
collector = RSMP::Collector.new self, options
|
61
|
-
collector.collect task, &block
|
55
|
+
def collect options, &block
|
56
|
+
collector = RSMP::Collector.new self, options.merge(task: @task)
|
57
|
+
collector.collect &block
|
62
58
|
collector
|
63
59
|
end
|
64
60
|
|
@@ -86,7 +82,7 @@ module RSMP
|
|
86
82
|
return if @state == :stopped
|
87
83
|
set_state :stopping
|
88
84
|
stop_tasks
|
89
|
-
notify_error
|
85
|
+
notify_error DisconnectError.new("Connection was closed")
|
90
86
|
ensure
|
91
87
|
close_socket
|
92
88
|
clear
|
data/lib/rsmp/site_proxy.rb
CHANGED
@@ -101,15 +101,8 @@ module RSMP
|
|
101
101
|
"cId" => component,
|
102
102
|
"mId" => m_id
|
103
103
|
})
|
104
|
-
|
105
|
-
task
|
106
|
-
collect_aggregated_status task, options[:collect].merge(m_id: m_id)
|
107
|
-
end
|
108
|
-
send_message message, validate: options[:validate]
|
109
|
-
return message, task.wait
|
110
|
-
else
|
111
|
-
send_message message, validate: options[:validate]
|
112
|
-
message
|
104
|
+
send_and_collect_if_needed message, options do |task|
|
105
|
+
collect_aggregated_status task, options[:collect].merge(m_id: m_id, num:1)
|
113
106
|
end
|
114
107
|
end
|
115
108
|
|
@@ -181,7 +174,7 @@ module RSMP
|
|
181
174
|
"sS" => request_list,
|
182
175
|
"mId" => m_id
|
183
176
|
})
|
184
|
-
|
177
|
+
send_and_collect_if_needed message, options do |task|
|
185
178
|
collect_status_responses task, status_list, options[:collect].merge(m_id: m_id)
|
186
179
|
end
|
187
180
|
end
|
@@ -193,11 +186,15 @@ module RSMP
|
|
193
186
|
acknowledge message
|
194
187
|
end
|
195
188
|
|
196
|
-
def
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
189
|
+
def send_and_collect_if_needed message, options, &block
|
190
|
+
if options[:collect]
|
191
|
+
task = @task.async { |task| yield task }
|
192
|
+
send_message message, validate: options[:validate]
|
193
|
+
{ sent: message, collector: task.wait }
|
194
|
+
else
|
195
|
+
send_message message, validate: options[:validate]
|
196
|
+
return { sent: message }
|
197
|
+
end
|
201
198
|
end
|
202
199
|
|
203
200
|
def subscribe_to_status component_id, status_list, options={}
|
@@ -218,7 +215,7 @@ module RSMP
|
|
218
215
|
"sS" => subscribe_list,
|
219
216
|
'mId' => m_id
|
220
217
|
})
|
221
|
-
|
218
|
+
send_and_collect_if_needed message, options do |task|
|
222
219
|
collect_status_updates task, status_list, options[:collect].merge(m_id: m_id)
|
223
220
|
end
|
224
221
|
end
|
@@ -264,7 +261,7 @@ module RSMP
|
|
264
261
|
"arg" => command_list,
|
265
262
|
"mId" => m_id
|
266
263
|
})
|
267
|
-
|
264
|
+
send_and_collect_if_needed message, options do |task|
|
268
265
|
collect_command_responses task, command_list, options[:collect].merge(m_id: m_id)
|
269
266
|
end
|
270
267
|
end
|
@@ -352,19 +349,27 @@ module RSMP
|
|
352
349
|
end
|
353
350
|
|
354
351
|
def collect_status_updates task, status_list, options
|
355
|
-
|
352
|
+
collector = StatusUpdateCollector.new(self, status_list, options.merge(task:task))
|
353
|
+
collector.collect
|
354
|
+
collector
|
356
355
|
end
|
357
356
|
|
358
357
|
def collect_status_responses task, status_list, options
|
359
|
-
|
358
|
+
collector = StatusResponseCollector.new(self, status_list, options.merge(task:task))
|
359
|
+
collector.collect
|
360
|
+
collector
|
360
361
|
end
|
361
362
|
|
362
363
|
def collect_command_responses task, command_list, options
|
363
|
-
|
364
|
+
collector = CommandResponseCollector.new(self, command_list, options.merge(task:task))
|
365
|
+
collector.collect
|
366
|
+
collector
|
364
367
|
end
|
365
368
|
|
366
369
|
def collect_aggregated_status task, options
|
367
|
-
|
370
|
+
collector = AggregatedStatusCollector.new(self, options.merge(task:task))
|
371
|
+
collector.collect
|
372
|
+
collector
|
368
373
|
end
|
369
374
|
end
|
370
375
|
end
|
data/lib/rsmp/supervisor.rb
CHANGED
@@ -7,7 +7,6 @@ module RSMP
|
|
7
7
|
attr_reader :rsmp_versions, :site_id, :supervisor_settings, :proxies, :logger
|
8
8
|
|
9
9
|
def initialize options={}
|
10
|
-
|
11
10
|
handle_supervisor_settings( options[:supervisor_settings] || {} )
|
12
11
|
super options
|
13
12
|
@proxies = []
|
@@ -161,7 +160,7 @@ module RSMP
|
|
161
160
|
ip: info[:ip],
|
162
161
|
port: info[:port],
|
163
162
|
task: @task,
|
164
|
-
|
163
|
+
collect: @collect,
|
165
164
|
socket: socket,
|
166
165
|
stream: stream,
|
167
166
|
protocol: protocol,
|
@@ -244,10 +244,13 @@ module RSMP
|
|
244
244
|
@status_subscriptions[component] ||= {}
|
245
245
|
update_list[component] ||= {}
|
246
246
|
now = Time.now # internal timestamp
|
247
|
+
subs = @status_subscriptions[component]
|
247
248
|
|
248
249
|
message.attributes["sS"].each do |arg|
|
249
250
|
sCI = arg["sCI"]
|
250
251
|
subcription = {interval: arg["uRt"].to_i, last_sent_at: now}
|
252
|
+
subs[sCI] ||= {}
|
253
|
+
subs[sCI][arg["n"]] = subcription
|
251
254
|
update_list[component][sCI] ||= []
|
252
255
|
update_list[component][sCI] << arg["n"]
|
253
256
|
end
|
@@ -279,11 +282,7 @@ module RSMP
|
|
279
282
|
end
|
280
283
|
|
281
284
|
def fetch_last_sent_status component, code, name
|
282
|
-
|
283
|
-
@last_status_sent[component][code][name]
|
284
|
-
else
|
285
|
-
nil
|
286
|
-
end
|
285
|
+
@last_status_sent.dig component, code, name
|
287
286
|
end
|
288
287
|
|
289
288
|
def store_last_sent_status message
|
@@ -307,10 +306,12 @@ module RSMP
|
|
307
306
|
by_code.each_pair do |code,by_name|
|
308
307
|
by_name.each_pair do |name,subscription|
|
309
308
|
current = nil
|
309
|
+
should_send = false
|
310
310
|
if subscription[:interval] == 0
|
311
311
|
# send as soon as the data changes
|
312
312
|
if component_object
|
313
313
|
current, age = *(component_object.get_status code, name)
|
314
|
+
current = current.to_s
|
314
315
|
end
|
315
316
|
last_sent = fetch_last_sent_status component, code, name
|
316
317
|
if current != last_sent
|
data/lib/rsmp/version.rb
CHANGED
data/lib/rsmp.rb
CHANGED
@@ -20,10 +20,15 @@ require 'rsmp/components'
|
|
20
20
|
require 'rsmp/collect/notifier'
|
21
21
|
require 'rsmp/collect/listener'
|
22
22
|
require 'rsmp/collect/collector'
|
23
|
+
require 'rsmp/collect/state_collector'
|
23
24
|
require 'rsmp/collect/query'
|
24
|
-
require 'rsmp/collect/
|
25
|
-
require 'rsmp/collect/
|
26
|
-
require 'rsmp/collect/
|
25
|
+
require 'rsmp/collect/status_query'
|
26
|
+
require 'rsmp/collect/command_query'
|
27
|
+
require 'rsmp/collect/status_update_or_response_collector'
|
28
|
+
require 'rsmp/collect/status_response_collector'
|
29
|
+
require 'rsmp/collect/status_update_collector'
|
30
|
+
require 'rsmp/collect/command_response_collector'
|
31
|
+
require 'rsmp/collect/aggregated_status_collector'
|
27
32
|
require 'rsmp/component'
|
28
33
|
require 'rsmp/site'
|
29
34
|
require 'rsmp/proxy'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rsmp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Emil Tin
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-01-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: async
|
@@ -189,6 +189,7 @@ files:
|
|
189
189
|
- ".gitignore"
|
190
190
|
- ".gitmodules"
|
191
191
|
- ".rspec"
|
192
|
+
- ".ruby-version"
|
192
193
|
- CHANGELOG.md
|
193
194
|
- Gemfile
|
194
195
|
- Gemfile.lock
|
@@ -200,18 +201,25 @@ files:
|
|
200
201
|
- config/supervisor.yaml
|
201
202
|
- config/tlc.yaml
|
202
203
|
- documentation/classes_and_modules.md
|
204
|
+
- documentation/collecting_message.md
|
203
205
|
- documentation/message_distribution.md
|
204
206
|
- exe/rsmp
|
205
207
|
- lib/rsmp.rb
|
206
208
|
- lib/rsmp/archive.rb
|
207
209
|
- lib/rsmp/cli.rb
|
210
|
+
- lib/rsmp/collect/aggregated_status_collector.rb
|
208
211
|
- lib/rsmp/collect/collector.rb
|
212
|
+
- lib/rsmp/collect/command_query.rb
|
213
|
+
- lib/rsmp/collect/command_response_collector.rb
|
209
214
|
- lib/rsmp/collect/listener.rb
|
210
|
-
- lib/rsmp/collect/matcher.rb
|
211
215
|
- lib/rsmp/collect/message_matchers.rb
|
212
|
-
- lib/rsmp/collect/message_queries.rb
|
213
216
|
- lib/rsmp/collect/notifier.rb
|
214
217
|
- lib/rsmp/collect/query.rb
|
218
|
+
- lib/rsmp/collect/state_collector.rb
|
219
|
+
- lib/rsmp/collect/status_query.rb
|
220
|
+
- lib/rsmp/collect/status_response_collector.rb
|
221
|
+
- lib/rsmp/collect/status_update_collector.rb
|
222
|
+
- lib/rsmp/collect/status_update_or_response_collector.rb
|
215
223
|
- lib/rsmp/component.rb
|
216
224
|
- lib/rsmp/components.rb
|
217
225
|
- lib/rsmp/convert/export/json_schema.rb
|
@@ -262,7 +270,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
262
270
|
- !ruby/object:Gem::Version
|
263
271
|
version: '0'
|
264
272
|
requirements: []
|
265
|
-
rubygems_version: 3.2.
|
273
|
+
rubygems_version: 3.2.32
|
266
274
|
signing_key:
|
267
275
|
specification_version: 4
|
268
276
|
summary: RoadSide Message Protocol (RSMP) library.
|