rsmp 0.29.0 → 0.32.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +7 -7
- data/documentation/collecting_message.md +25 -10
- data/documentation/message_distribution.md +8 -8
- data/lib/rsmp/cli.rb +43 -19
- data/lib/rsmp/collect/ack_collector.rb +7 -5
- data/lib/rsmp/collect/aggregated_status_collector.rb +4 -2
- data/lib/rsmp/collect/alarm_collector.rb +10 -10
- data/lib/rsmp/collect/{alarm_query.rb → alarm_matcher.rb} +2 -2
- data/lib/rsmp/collect/collector.rb +69 -66
- data/lib/rsmp/collect/{command_query.rb → command_matcher.rb} +2 -2
- data/lib/rsmp/collect/command_response_collector.rb +3 -3
- data/lib/rsmp/collect/distributor.rb +65 -0
- data/lib/rsmp/collect/filter.rb +10 -5
- data/lib/rsmp/collect/{query.rb → matcher.rb} +1 -1
- data/lib/rsmp/collect/queue.rb +39 -0
- data/lib/rsmp/collect/receiver.rb +40 -0
- data/lib/rsmp/collect/state_collector.rb +57 -57
- data/lib/rsmp/collect/status_collector.rb +9 -6
- data/lib/rsmp/collect/{status_query.rb → status_matcher.rb} +2 -2
- data/lib/rsmp/component.rb +4 -0
- data/lib/rsmp/node.rb +1 -1
- data/lib/rsmp/proxy.rb +24 -22
- data/lib/rsmp/site.rb +43 -3
- data/lib/rsmp/site_proxy.rb +4 -4
- data/lib/rsmp/supervisor.rb +5 -5
- data/lib/rsmp/supervisor_proxy.rb +2 -1
- data/lib/rsmp/tlc/signal_priority.rb +19 -3
- data/lib/rsmp/tlc/traffic_controller.rb +29 -15
- data/lib/rsmp/tlc/traffic_controller_site.rb +4 -1
- data/lib/rsmp/version.rb +1 -1
- data/lib/rsmp.rb +7 -6
- metadata +9 -8
- data/lib/rsmp/collect/listener.rb +0 -23
- data/lib/rsmp/collect/notifier.rb +0 -65
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c4dc16f45d38459c4ab31445f39e74c8e0fe71ce906759a4f842ddcc8ca78471
|
4
|
+
data.tar.gz: 50d8ff8a27a2f16ddba8206236cc17997a582b5b5ec01348a55e9a7b3a8004b7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 735d346b07fb2ad71cead5a0d934bb415125429e2fa628e9c4aa93a73f7e1e40a8db5cce27b6329fbb520f13f9018fb2f221e4cf60051818043e58cbab2f0523
|
7
|
+
data.tar.gz: aad8d0d4b871916080c7c981a00fea551fb0c7b62599149b017b955d46e6c810fd246682206d89f2a6a99b5ec19cc0285fb6c68e2cde8b594cbe40402e542834
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
rsmp (0.
|
4
|
+
rsmp (0.32.0)
|
5
5
|
async (~> 2.12.0)
|
6
6
|
async-io (~> 1.43.0)
|
7
7
|
colorize (~> 1.1)
|
@@ -16,16 +16,16 @@ GEM
|
|
16
16
|
cucumber (>= 8.0, < 10.0)
|
17
17
|
rspec-expectations (~> 3.4)
|
18
18
|
thor (~> 1.0)
|
19
|
-
async (2.12.
|
19
|
+
async (2.12.1)
|
20
20
|
console (~> 1.25, >= 1.25.2)
|
21
21
|
fiber-annotation
|
22
|
-
io-event (~> 1.6)
|
22
|
+
io-event (~> 1.6, >= 1.6.5)
|
23
23
|
async-io (1.43.2)
|
24
24
|
async
|
25
25
|
bigdecimal (3.1.8)
|
26
26
|
builder (3.3.0)
|
27
27
|
colorize (1.1.0)
|
28
|
-
console (1.
|
28
|
+
console (1.27.0)
|
29
29
|
fiber-annotation
|
30
30
|
fiber-local (~> 1.1)
|
31
31
|
json
|
@@ -64,9 +64,9 @@ GEM
|
|
64
64
|
fiber-annotation (0.2.0)
|
65
65
|
fiber-local (1.1.0)
|
66
66
|
fiber-storage
|
67
|
-
fiber-storage (0.
|
67
|
+
fiber-storage (1.0.0)
|
68
68
|
hana (1.3.7)
|
69
|
-
io-event (1.6.
|
69
|
+
io-event (1.6.5)
|
70
70
|
json (2.7.2)
|
71
71
|
json_schemer (2.3.0)
|
72
72
|
bigdecimal
|
@@ -96,7 +96,7 @@ GEM
|
|
96
96
|
simpleidn (0.2.3)
|
97
97
|
sys-uname (1.3.0)
|
98
98
|
ffi (~> 1.1)
|
99
|
-
thor (1.3.
|
99
|
+
thor (1.3.2)
|
100
100
|
timecop (0.9.10)
|
101
101
|
|
102
102
|
PLATFORMS
|
@@ -3,30 +3,45 @@ You often need to collect messages or responses. The collector classes are used
|
|
3
3
|
|
4
4
|
A collector can collect ingoing and/or outgoing messages.
|
5
5
|
|
6
|
-
An object that includes the
|
6
|
+
An object that includes the Distributor module (or implements the same functionality) must be provided when you construct a Collected. The collector will attach itself to this distributor when it starts collecting, to receive messages. The SiteProxy and SupervisorProxy classes both include the Distributor module, and can therefore be used as message sources.
|
7
7
|
|
8
8
|
Messages that match the relevant criteria are stored by the collector.
|
9
9
|
|
10
|
-
When the collection is done, the collector detaches from the
|
10
|
+
When the collection is done, the collector detaches from the distributor, and returns the status.
|
11
11
|
|
12
12
|
|
13
13
|
## Collector
|
14
|
-
Class
|
14
|
+
Class used for collecting messages filtered by message type, direction and/or component id. A block can be used for custom filtering.
|
15
15
|
|
16
16
|
You can choose to collect a specific number of message and/or for a specific duration.
|
17
17
|
|
18
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
19
|
|
20
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.
|
21
|
+
When you create a collector, you provide a Filter to specify the messages types you want to collect. You can also specify ingoing and/or outgoing direction and the RSMP component.
|
23
22
|
|
24
23
|
```ruby
|
25
|
-
collector = MessageCollector.new
|
24
|
+
collector = MessageCollector.new(distributor,
|
25
|
+
num: 10,
|
26
|
+
filter: Filter.new(ingoing: true, outgoing: true)
|
26
27
|
```
|
27
28
|
|
28
29
|
num: The number of messages to collect. If not provided, a timeout must be set instead.
|
29
|
-
|
30
|
+
filter: filter to identify the types of messages to look for.
|
31
|
+
|
32
|
+
### Filter
|
33
|
+
The Filter class is used to filter messages according to message type, direction and component.
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
filter = Filter.new(
|
37
|
+
type: 'Alarm',
|
38
|
+
ingoing: true,
|
39
|
+
outgoing: false,
|
40
|
+
component: 'DL1'
|
41
|
+
)
|
42
|
+
```
|
43
|
+
|
44
|
+
type: a string, or an array of string, specifiying one or more RSMP message types.
|
30
45
|
ingoing: Whether to collect ingoing messages. Defaults to true
|
31
46
|
outgoing: Whether to collect outgoing messages. Defaults to true
|
32
47
|
component: An RSMP component id.
|
@@ -48,7 +63,7 @@ result = collector.wait
|
|
48
63
|
```
|
49
64
|
|
50
65
|
### Custom filtering
|
51
|
-
You can use a block to do extra filtering. The block will be callled for each messages that
|
66
|
+
You can use a block to do extra filtering. The block will be callled for each messages that passes the Filter provided when initializing the collector.
|
52
67
|
|
53
68
|
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
69
|
|
@@ -69,7 +84,7 @@ Exceptions in the block will cause the collector to abort. If the collect! or wa
|
|
69
84
|
The method collect!() will raise exceptions in case of errors, and will return the collect message directly.
|
70
85
|
|
71
86
|
```ruby
|
72
|
-
message = collector.collect # => collected message.
|
87
|
+
message = collector.collect! # => collected message.
|
73
88
|
```
|
74
89
|
|
75
90
|
Similar, `wait!()` will raise an exception in case of timeouts or errors:
|
@@ -181,7 +196,7 @@ result[:collector].messages # => list of collected messages
|
|
181
196
|
|
182
197
|
### Processing responses
|
183
198
|
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.
|
199
|
+
Collection will continue until the block returns :cancel, or it times out.
|
185
200
|
|
186
201
|
```ruby
|
187
202
|
options = {
|
@@ -1,23 +1,23 @@
|
|
1
1
|
# Message distribution
|
2
2
|
|
3
|
-
Proxy - -
|
3
|
+
Proxy - - Distributor --> Receivers
|
4
4
|
|
5
|
-
A proxy distributes messages to
|
5
|
+
A proxy distributes messages to receivers, when they are installed.
|
6
6
|
|
7
|
-
Collectors are special
|
7
|
+
Collectors are special receiverws that waits for specific message, and are used to implement methods for waiting for RMSP responses, statuses, alarms, etc.
|
8
8
|
|
9
|
-
Note that Archive is not a
|
9
|
+
Note that Archive is not a receiver, and does not receive messages via the Distributor. Instead the Archive gets and stores messages via the log() interface in the Logging module. The reason is that the items that the Archive and the Logger contain other data as well as the message, like error messages, warnings, text descriptions, colors codes, etc. The Distributor and Receiver handles only Message objects.
|
10
10
|
|
11
|
-
##
|
11
|
+
## Distributor
|
12
12
|
A module that handles distributing messages to receivers.
|
13
13
|
|
14
|
-
##
|
14
|
+
## Receiver
|
15
15
|
Receives messages as long as it's installed into a distributor.
|
16
16
|
|
17
17
|
## Collector
|
18
|
-
|
18
|
+
Includes the Receiver module to wait for specific messages. Once received
|
19
19
|
the client receives the collection.
|
20
20
|
|
21
21
|
## Proxy
|
22
|
-
A proxy includes the
|
22
|
+
A proxy includes the Distributor module and distributes each message to receivers after processing it.
|
23
23
|
|
data/lib/rsmp/cli.rb
CHANGED
@@ -12,9 +12,10 @@ module RSMP
|
|
12
12
|
method_option :config, :type => :string, :aliases => "-c", banner: 'Path to .yaml config file'
|
13
13
|
method_option :id, :type => :string, :aliases => "-i", banner: 'RSMP site id'
|
14
14
|
method_option :supervisors, :type => :string, :aliases => "-s", banner: 'ip:port,... list of supervisor to connect to'
|
15
|
+
method_option :core, :string => :string, banner: "Core version: [#{RSMP::Schema.core_versions.join(' ')}]", enum: RSMP::Schema.core_versions
|
16
|
+
method_option :type, :type => :string, :aliases => "-t", banner: 'Type of site: [tlc]', enum: ['tlc'], default: 'tlc'
|
15
17
|
method_option :log, :type => :string, :aliases => "-l", banner: 'Path to log file'
|
16
18
|
method_option :json, :type => :boolean, :aliases => "-j", banner: 'Show JSON messages in log'
|
17
|
-
method_option :type, :type => :string, :aliases => "-t", banner: 'Type of site: [tlc]'
|
18
19
|
def site
|
19
20
|
settings = {}
|
20
21
|
log_settings = { 'active' => true }
|
@@ -43,6 +44,20 @@ module RSMP
|
|
43
44
|
end
|
44
45
|
end
|
45
46
|
|
47
|
+
if options[:core]
|
48
|
+
settings['core_versions'] = [options[:core]]
|
49
|
+
end
|
50
|
+
|
51
|
+
site_class = RSMP::Site
|
52
|
+
site_type = options[:type] || settings['type']
|
53
|
+
case site_type
|
54
|
+
when 'tlc'
|
55
|
+
site_class = RSMP::TLC::TrafficControllerSite
|
56
|
+
else
|
57
|
+
puts "Error: Unknown site type #{site_type}"
|
58
|
+
exit
|
59
|
+
end
|
60
|
+
|
46
61
|
if options[:log]
|
47
62
|
log_settings['path'] = options[:log]
|
48
63
|
end
|
@@ -51,22 +66,25 @@ module RSMP
|
|
51
66
|
log_settings['json'] = options[:json]
|
52
67
|
end
|
53
68
|
|
54
|
-
site_class = RSMP::Site
|
55
|
-
if options[:type]
|
56
|
-
case options[:type]
|
57
|
-
when 'tlc'
|
58
|
-
site_class = RSMP::TLC::TrafficControllerSite
|
59
|
-
else
|
60
|
-
site_class = RSMP::Site
|
61
|
-
end
|
62
|
-
end
|
63
69
|
Async do |task|
|
64
70
|
task.annotate 'cli'
|
65
71
|
loop do
|
66
72
|
begin
|
67
|
-
site = site_class.new(site_settings:settings, log_settings: log_settings)
|
73
|
+
site = site_class.new(site_settings: settings, log_settings: log_settings)
|
68
74
|
site.start
|
69
75
|
site.wait
|
76
|
+
rescue Psych::SyntaxError => e
|
77
|
+
puts "Cannot read config file #{e}"
|
78
|
+
break
|
79
|
+
rescue RSMP::Schema::UnknownSchemaTypeError => e
|
80
|
+
puts "Cannot start site: #{e}"
|
81
|
+
break
|
82
|
+
rescue RSMP::Schema::UnknownSchemaVersionError => e
|
83
|
+
puts "Cannot start site: #{e}"
|
84
|
+
break
|
85
|
+
rescue RSMP::ConfigurationError => e
|
86
|
+
puts "Cannot start site: #{e}"
|
87
|
+
break
|
70
88
|
rescue RSMP::Restart
|
71
89
|
site.stop
|
72
90
|
end
|
@@ -74,12 +92,6 @@ module RSMP
|
|
74
92
|
end
|
75
93
|
rescue Interrupt
|
76
94
|
# cntr-c
|
77
|
-
rescue RSMP::Schema::UnknownSchemaTypeError => e
|
78
|
-
puts "Cannot start site: #{e}"
|
79
|
-
rescue RSMP::Schema::UnknownSchemaVersionError => e
|
80
|
-
puts "Cannot start site: #{e}"
|
81
|
-
rescue Psych::SyntaxError => e
|
82
|
-
puts "Cannot read config file #{e}"
|
83
95
|
rescue Exception => e
|
84
96
|
puts "Uncaught error: #{e}"
|
85
97
|
puts caller.join("\n")
|
@@ -90,6 +102,7 @@ module RSMP
|
|
90
102
|
method_option :id, :type => :string, :aliases => "-i", banner: 'RSMP site id'
|
91
103
|
method_option :ip, :type => :numeric, banner: 'IP address to listen on'
|
92
104
|
method_option :port, :type => :string, :aliases => "-p", banner: 'Port to listen on'
|
105
|
+
method_option :core, :string => :string, banner: "Core version: [#{RSMP::Schema.core_versions.join(' ')}]", enum: RSMP::Schema.core_versions
|
93
106
|
method_option :log, :type => :string, :aliases => "-l", banner: 'Path to log file'
|
94
107
|
method_option :json, :type => :boolean, :aliases => "-j", banner: 'Show JSON messages in log'
|
95
108
|
def supervisor
|
@@ -118,6 +131,11 @@ module RSMP
|
|
118
131
|
settings['port'] = options[:port]
|
119
132
|
end
|
120
133
|
|
134
|
+
if options[:core]
|
135
|
+
settings['guest'] = {}
|
136
|
+
settings['guest']['core_versions'] = [options[:core]]
|
137
|
+
end
|
138
|
+
|
121
139
|
if options[:log]
|
122
140
|
log_settings['path'] = options[:log]
|
123
141
|
end
|
@@ -131,11 +149,17 @@ module RSMP
|
|
131
149
|
supervisor = RSMP::Supervisor.new(supervisor_settings:settings,log_settings:log_settings)
|
132
150
|
supervisor.start
|
133
151
|
supervisor.wait
|
152
|
+
rescue Psych::SyntaxError => e
|
153
|
+
puts "Cannot read config file #{e}"
|
154
|
+
rescue RSMP::Schema::UnknownSchemaTypeError => e
|
155
|
+
puts "Cannot start supervisor: #{e}"
|
156
|
+
rescue RSMP::Schema::UnknownSchemaVersionError => e
|
157
|
+
puts "Cannot start supervisor: #{e}"
|
158
|
+
rescue RSMP::ConfigurationError => e
|
159
|
+
puts "Cannot start supervisor: #{e}"
|
134
160
|
end
|
135
161
|
rescue Interrupt
|
136
162
|
# ctrl-c
|
137
|
-
rescue RSMP::ConfigurationError => e
|
138
|
-
puts "Cannot start supervisor: #{e}"
|
139
163
|
end
|
140
164
|
|
141
165
|
desc "convert", "Convert SXL from YAML to JSON Schema"
|
@@ -3,14 +3,16 @@ module RSMP
|
|
3
3
|
class AckCollector < Collector
|
4
4
|
def initialize proxy, options={}
|
5
5
|
raise ArgumentError.new("m_id must be provided") unless options[:m_id]
|
6
|
-
|
7
|
-
|
6
|
+
super proxy, options.merge(
|
7
|
+
filter: RSMP::Filter.new(ingoing: true, outgoing: false, type: 'MessageAck'),
|
8
|
+
num: 1,
|
9
|
+
title: 'message acknowledgement'
|
10
|
+
)
|
8
11
|
end
|
9
12
|
|
10
13
|
# Check if we the MessageAck related to initiating request, identified by @m_id.
|
11
|
-
def
|
12
|
-
|
13
|
-
return message.attribute('oMId') == @options[:m_id]
|
14
|
+
def acceptable? message
|
15
|
+
super(message) && message.attribute('oMId') == @m_id
|
14
16
|
end
|
15
17
|
end
|
16
18
|
end
|
@@ -2,8 +2,10 @@ module RSMP
|
|
2
2
|
# Class for waiting for an aggregated status response
|
3
3
|
class AggregatedStatusCollector < Collector
|
4
4
|
def initialize proxy, options={}
|
5
|
-
|
6
|
-
|
5
|
+
super proxy, options.merge(
|
6
|
+
filter: RSMP::Filter.new(ingoing: true, outgoing: false, type: 'AggregatedStatus'),
|
7
|
+
title: 'aggregated status'
|
8
|
+
)
|
7
9
|
end
|
8
10
|
end
|
9
11
|
end
|
@@ -2,20 +2,20 @@ module RSMP
|
|
2
2
|
# Class for waiting for specific command responses
|
3
3
|
class AlarmCollector < Collector
|
4
4
|
def initialize proxy,options={}
|
5
|
-
@
|
5
|
+
@matcher = options[:matcher] || {}
|
6
6
|
super proxy, options.merge(
|
7
|
-
type: 'Alarm',
|
7
|
+
filter: RSMP::Filter.new(ingoing: true, outgoing: false, type: 'Alarm'),
|
8
8
|
title:'alarm'
|
9
9
|
)
|
10
10
|
end
|
11
11
|
|
12
12
|
# match alarm attributes
|
13
|
-
def
|
13
|
+
def acceptable? message
|
14
14
|
return false if super(message) == false
|
15
15
|
|
16
16
|
# match fixed attributes
|
17
17
|
%w{cId aCId aSp ack aS sS cat pri}.each do |key|
|
18
|
-
want = @
|
18
|
+
want = @matcher[key]
|
19
19
|
got = message.attribute(key)
|
20
20
|
case want
|
21
21
|
when Regexp
|
@@ -26,13 +26,13 @@ module RSMP
|
|
26
26
|
end
|
27
27
|
|
28
28
|
# match rvs items
|
29
|
-
if @
|
30
|
-
|
29
|
+
if @matcher['rvs']
|
30
|
+
matcher_rvs = @matcher['rvs']
|
31
31
|
message_rvs = message.attributes['rvs']
|
32
32
|
return false unless message_rvs
|
33
|
-
return false unless
|
33
|
+
return false unless matcher_rvs.all? do |matcher_item|
|
34
34
|
return false unless message_rvs.any? do |message_item|
|
35
|
-
next message_item['n'] ==
|
35
|
+
next message_item['n'] == matcher_item['n'] && message_item['v'] == matcher_item['v']
|
36
36
|
end
|
37
37
|
next true
|
38
38
|
end
|
@@ -41,8 +41,8 @@ module RSMP
|
|
41
41
|
end
|
42
42
|
|
43
43
|
# return a string that describes what we're collecting
|
44
|
-
def
|
45
|
-
"#{describe_num_and_type} #{ {component: @options[:component]}.merge(@
|
44
|
+
def describe_matcher
|
45
|
+
"#{describe_num_and_type} #{ {component: @options[:component]}.merge(@matcher).compact }"
|
46
46
|
end
|
47
47
|
|
48
48
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module RSMP
|
2
2
|
# Match a specific alarm
|
3
|
-
class
|
4
|
-
# Match an alarm value against a
|
3
|
+
class AlarmMatcher < Matcher
|
4
|
+
# Match an alarm value against a matcher
|
5
5
|
def match? item
|
6
6
|
return false if @want['n'] && @want['n'] != item['n']
|
7
7
|
if @want['v'].is_a? Regexp
|