rsmp 0.7.5 → 0.8.3

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.
@@ -5,22 +5,19 @@ module RSMP
5
5
  class Listener
6
6
  include Inspect
7
7
 
8
- def initialize proxy, options={}
9
- @proxy = proxy
8
+ def initialize notifier, options={}
9
+ @notifier = notifier
10
10
  end
11
11
 
12
- def notify message
12
+ def change_notifier notifier
13
+ @notifier.remove_listener self if @notifier
14
+ @notifier = notifier
13
15
  end
14
16
 
15
- def notify_error error, options={}
17
+ def notify message
16
18
  end
17
19
 
18
- def listen &block
19
- @proxy.add_listener self
20
- yield
21
- ensure
22
- @proxy.remove_listener self
20
+ def notify_error error, options={}
23
21
  end
24
-
25
22
  end
26
23
  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
@@ -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
@@ -8,26 +8,36 @@ module RSMP
8
8
  @want = want
9
9
  @got = nil
10
10
  @message = nil
11
- @done = false
12
11
  end
13
12
 
14
13
  # Are we done, i.e. did the last checked item match?
15
14
  def done?
16
- @done
15
+ @got != nil
17
16
  end
18
17
 
19
18
  # Check an item and set @done to true if it matches
20
19
  # Store the item and corresponding message if there's a positive or negative match
21
- def check_match item, message
20
+ def perform_match item, message, block
22
21
  matched = match? item
23
22
  if matched != nil
24
- @message = message
25
- @got = item
26
- @done = matched
23
+ if block
24
+ status = block.call(nil,item)
25
+ matched = status if status == true || status == false
26
+ end
27
27
  end
28
28
  matched
29
29
  end
30
30
 
31
+ def keep message, item
32
+ @message = message
33
+ @got = item
34
+ end
35
+
36
+ def forget
37
+ @message = nil
38
+ @got = nil
39
+ end
40
+
31
41
  def match? item
32
42
  end
33
43
  end
@@ -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,14 +59,9 @@ 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
- @queries.map { |query| query.message }.uniq
64
+ @queries.map { |query| query.message }.uniq.compact
71
65
  end
72
66
 
73
67
  # Return progress as completes queries vs. total number of queries
@@ -77,14 +71,14 @@ module RSMP
77
71
  { need: need, reached: reached }
78
72
  end
79
73
 
80
- # Are there queries left to match?
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 status
81
+ def query_status
88
82
  @queries.map { |query| [query.want, query.done?] }.to_h
89
83
  end
90
84
 
@@ -95,19 +89,34 @@ 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 check_match message
99
- return unless match?(message)
92
+ def perform_match message
93
+ return false if super(message) == false
94
+ return unless collecting?
100
95
  @queries.each do |query| # look through queries
101
96
  get_items(message).each do |item| # look through items in message
102
- matched = query.check_match(item,message)
97
+ matched = query.perform_match(item,message,@block)
98
+ return unless collecting?
103
99
  if matched != nil
104
100
  type = {true=>'match',false=>'mismatch'}[matched]
105
- @proxy.log "#{@title.capitalize} #{message.m_id_short} collect #{type} #{query.want}, item #{item}", level: :debug
106
- break
101
+ @notifier.log "#{@title.capitalize} #{message.m_id_short} collect #{type} #{query.want}, item #{item}", level: :debug
102
+ if matched == true
103
+ query.keep message, item
104
+ elsif matched == false
105
+ query.forget
106
+ end
107
107
  end
108
108
  end
109
109
  end
110
- @proxy.log "#{@title.capitalize} collect reached #{summary}", level: :debug
110
+ complete if done?
111
+ @notifier.log "#{@title.capitalize} collect reached #{summary}", level: :debug
112
+ end
113
+
114
+ # don't collect anything. Query will collect them instead
115
+ def keep message
116
+ end
117
+
118
+ def describe
119
+ @queries.map {|q| q.want.to_s }
111
120
  end
112
121
  end
113
122
  end
@@ -0,0 +1,20 @@
1
+ module RSMP
2
+ # Base class for waiting for status updates or responses
3
+ class StatusCollector < StateCollector
4
+ def initialize proxy, want, options={}
5
+ super proxy, want, options.merge(title: 'status response', type:['MessageNotAck'])
6
+
7
+ @options[:type] << 'StatusUpdate' unless options[:updates] == false
8
+ @options[:type] << 'StatusResponse' unless options[:reponses] == false
9
+ end
10
+
11
+ def build_query want
12
+ RSMP::StatusQuery.new want
13
+ end
14
+
15
+ # Get items, in our case status values
16
+ def get_items message
17
+ message.attributes['sS'] || []
18
+ end
19
+ end
20
+ end
@@ -1,20 +1,5 @@
1
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
-
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
data/lib/rsmp/error.rb CHANGED
@@ -41,7 +41,7 @@ module RSMP
41
41
  class TimeoutError < Error
42
42
  end
43
43
 
44
- class DisonnectError < Error
44
+ class DisconnectError < Error
45
45
  end
46
46
 
47
47
  class ConnectionError < Error
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,7 @@ module RSMP
15
15
  @clock = Clock.new
16
16
  @error_queue = Async::Queue.new
17
17
  @ignore_errors = []
18
+ @collect = options[:collect]
18
19
  end
19
20
 
20
21
  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
- prepare_collection @settings['collect']
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,19 +52,6 @@ module RSMP
49
52
  node.clock
50
53
  end
51
54
 
52
- def prepare_collection num
53
- if num
54
- @collector = RSMP::Collector.new self, num: num, ingoing: true, outgoing: true
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
62
- collector
63
- end
64
-
65
55
  def run
66
56
  start
67
57
  @reader.wait if @reader
@@ -86,7 +76,7 @@ module RSMP
86
76
  return if @state == :stopped
87
77
  set_state :stopping
88
78
  stop_tasks
89
- notify_error DisonnectError.new("Connection was closed")
79
+ notify_error DisconnectError.new("Connection was closed")
90
80
  ensure
91
81
  close_socket
92
82
  clear
@@ -583,25 +573,27 @@ module RSMP
583
573
  end
584
574
 
585
575
  def wait_for_acknowledgement parent_task, options={}, m_id
586
- collect(parent_task,options.merge({
587
- type: ['MessageAck','MessageNotAck'],
588
- num: 1
589
- })) do |message|
576
+ collector = Collector.new self, options.merge(task: parent_task, type: ['MessageAck','MessageNotAck'])
577
+ collector.collect do |message|
590
578
  if message.is_a?(MessageNotAck)
591
579
  if message.attribute('oMId') == m_id
592
- # set result to an exception, but don't raise it.
593
- # this will be returned by the task and stored as the task result
594
- # when the parent task call wait() on the task, the exception
595
- # will be raised in the parent task, and caught by rspec.
596
- # rspec will then show the error and record the test as failed
597
580
  m_id_short = RSMP::Message.shorten_m_id m_id, 8
598
- result = RSMP::MessageRejected.new "Aggregated status request #{m_id_short} was rejected with '#{message.attribute('rea')}'"
599
- next true # done, no more messages wanted
581
+ raise RSMP::MessageRejected.new "Aggregated status request #{m_id_short} was rejected with '#{message.attribute('rea')}'"
600
582
  end
601
583
  elsif message.is_a?(MessageAck)
602
- next true if message.attribute('oMId') == m_id
584
+ collector.complete if message.attribute('oMId') == m_id
603
585
  end
604
- false
586
+ end
587
+ end
588
+
589
+ def send_and_optionally_collect message, options, &block
590
+ if options[:collect]
591
+ task = @task.async { |task| yield task }
592
+ send_message message, validate: options[:validate]
593
+ { sent: message, collector: task.wait }
594
+ else
595
+ send_message message, validate: options[:validate]
596
+ return { sent: message }
605
597
  end
606
598
  end
607
599
  end
data/lib/rsmp/site.rb CHANGED
@@ -95,7 +95,8 @@ module RSMP
95
95
  ip: supervisor_settings['ip'],
96
96
  port: supervisor_settings['port'],
97
97
  logger: @logger,
98
- archive: @archive
98
+ archive: @archive,
99
+ collect: @collect
99
100
  })
100
101
  @proxies << proxy
101
102
  @proxies_condition.signal
@@ -101,15 +101,13 @@ module RSMP
101
101
  "cId" => component,
102
102
  "mId" => m_id
103
103
  })
104
- if options[:collect]
105
- task = @task.async do |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_optionally_collect message, options do |task|
105
+ collector = AggregatedStatusCollector.new(
106
+ self,
107
+ options[:collect].merge(task:@task,m_id: m_id, num:1)
108
+ )
109
+ collector.collect
110
+ collector
113
111
  end
114
112
  end
115
113
 
@@ -181,8 +179,14 @@ module RSMP
181
179
  "sS" => request_list,
182
180
  "mId" => m_id
183
181
  })
184
- send_while_collecting message, options do |task|
185
- collect_status_responses task, status_list, options[:collect].merge(m_id: m_id)
182
+ send_and_optionally_collect message, options do |task|
183
+ collector = StatusCollector.new(
184
+ self,
185
+ status_list,
186
+ options[:collect].merge(task:@task,m_id: m_id)
187
+ )
188
+ collector.collect
189
+ collector
186
190
  end
187
191
  end
188
192
 
@@ -193,13 +197,6 @@ module RSMP
193
197
  acknowledge message
194
198
  end
195
199
 
196
- def send_while_collecting message, options, &block
197
- task = @task.async { |task| yield task } if options[:collect]
198
- send_message message, validate: options[:validate]
199
- return message, task.wait if task
200
- message
201
- end
202
-
203
200
  def subscribe_to_status component_id, status_list, options={}
204
201
  validate_ready 'subscribe to status'
205
202
  m_id = options[:m_id] || RSMP::Message.make_m_id
@@ -218,8 +215,14 @@ module RSMP
218
215
  "sS" => subscribe_list,
219
216
  'mId' => m_id
220
217
  })
221
- send_while_collecting message, options do |task|
222
- collect_status_updates task, status_list, options[:collect].merge(m_id: m_id)
218
+ send_and_optionally_collect message, options do |task|
219
+ collector = StatusCollector.new(
220
+ self,
221
+ status_list,
222
+ options[:collect].merge(task:@task,m_id: m_id)
223
+ )
224
+ collector.collect
225
+ collector
223
226
  end
224
227
  end
225
228
 
@@ -264,8 +267,14 @@ module RSMP
264
267
  "arg" => command_list,
265
268
  "mId" => m_id
266
269
  })
267
- send_while_collecting message, options do |task|
268
- collect_command_responses task, command_list, options[:collect].merge(m_id: m_id)
270
+ send_and_optionally_collect message, options do |task|
271
+ collector = CommandResponseCollector.new(
272
+ self,
273
+ command_list,
274
+ options[:collect].merge(task:@task,m_id: m_id)
275
+ )
276
+ collector.collect
277
+ collector
269
278
  end
270
279
  end
271
280
 
@@ -342,29 +351,13 @@ module RSMP
342
351
  distribute_error e, options
343
352
  end
344
353
 
345
- def collect_alarms parent_task, options={}
346
- collect(parent_task,options.merge(type: "Alarm")) do |alarm|
354
+ def collect_alarms options={}
355
+ collect(@task,options.merge(type: "Alarm")) do |alarm|
347
356
  next if options[:aCId] && options[:aCId] != alarm.attribute("aCId")
348
357
  next if options[:aSp] && options[:aSp] != alarm.attribute("aSp")
349
358
  next if options[:aS] && options[:aS] != alarm.attribute("aS")
350
- true
359
+ :keep
351
360
  end
352
361
  end
353
-
354
- def collect_status_updates task, status_list, options
355
- StatusUpdateMatcher.new(self, status_list, options).collect task
356
- end
357
-
358
- def collect_status_responses task, status_list, options
359
- StatusResponseMatcher.new(self, status_list, options).collect task
360
- end
361
-
362
- def collect_command_responses task, command_list, options
363
- CommandResponseMatcher.new(self, command_list, options).collect task
364
- end
365
-
366
- def collect_aggregated_status task, options
367
- AggregatedStatusMatcher.new(self, options).collect task
368
- end
369
362
  end
370
363
  end
@@ -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
- settings: {'collect'=>@supervisor_settings['collect']},
163
+ collect: @collect,
165
164
  socket: socket,
166
165
  stream: stream,
167
166
  protocol: protocol,
@@ -138,16 +138,8 @@ module RSMP
138
138
  "mId" => m_id,
139
139
  })
140
140
 
141
- if options[:collect]
142
- result = nil
143
- task = @task.async do |task|
144
- wait_for_acknowledgement task, options[:collect], m_id
145
- end
146
- send_message message, validate: options[:validate]
147
- return message, task.wait
148
- else
149
- send_message message, validate: options[:validate]
150
- message
141
+ send_and_optionally_collect message, options do |task|
142
+ wait_for_acknowledgement task, options[:collect], m_id
151
143
  end
152
144
  end
153
145
 
@@ -282,7 +274,7 @@ module RSMP
282
274
  end
283
275
 
284
276
  def fetch_last_sent_status component, code, name
285
- @last_status_sent.dig component, code, name
277
+ @last_status_sent.dig component, code, name if @last_status_sent
286
278
  end
287
279
 
288
280
  def store_last_sent_status message
@@ -16,7 +16,7 @@ module RSMP
16
16
  return default unless plan.states
17
17
  states = plan.states[c_id]
18
18
  return default unless states
19
- state =states[pos]
19
+ state = states[pos]
20
20
  return default unless state =~ /[a-hA-G0-9N-P]/ # valid signal group states
21
21
  state
22
22
  end
data/lib/rsmp/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module RSMP
2
- VERSION = "0.7.5"
2
+ VERSION = "0.8.3"
3
3
  end
data/lib/rsmp.rb CHANGED
@@ -20,10 +20,14 @@ 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'
24
+ require 'rsmp/collect/filter'
23
25
  require 'rsmp/collect/query'
24
- require 'rsmp/collect/matcher'
25
- require 'rsmp/collect/message_queries'
26
- require 'rsmp/collect/message_matchers'
26
+ require 'rsmp/collect/status_query'
27
+ require 'rsmp/collect/command_query'
28
+ require 'rsmp/collect/status_collector'
29
+ require 'rsmp/collect/command_response_collector'
30
+ require 'rsmp/collect/aggregated_status_collector'
27
31
  require 'rsmp/component'
28
32
  require 'rsmp/site'
29
33
  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.7.5
4
+ version: 0.8.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Emil Tin
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-01-04 00:00:00.000000000 Z
11
+ date: 2022-01-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async
@@ -201,18 +201,24 @@ files:
201
201
  - config/supervisor.yaml
202
202
  - config/tlc.yaml
203
203
  - documentation/classes_and_modules.md
204
+ - documentation/collecting_message.md
204
205
  - documentation/message_distribution.md
205
206
  - exe/rsmp
206
207
  - lib/rsmp.rb
207
208
  - lib/rsmp/archive.rb
208
209
  - lib/rsmp/cli.rb
210
+ - lib/rsmp/collect/aggregated_status_collector.rb
209
211
  - lib/rsmp/collect/collector.rb
212
+ - lib/rsmp/collect/command_query.rb
213
+ - lib/rsmp/collect/command_response_collector.rb
214
+ - lib/rsmp/collect/filter.rb
210
215
  - lib/rsmp/collect/listener.rb
211
- - lib/rsmp/collect/matcher.rb
212
216
  - lib/rsmp/collect/message_matchers.rb
213
- - lib/rsmp/collect/message_queries.rb
214
217
  - lib/rsmp/collect/notifier.rb
215
218
  - lib/rsmp/collect/query.rb
219
+ - lib/rsmp/collect/state_collector.rb
220
+ - lib/rsmp/collect/status_collector.rb
221
+ - lib/rsmp/collect/status_query.rb
216
222
  - lib/rsmp/component.rb
217
223
  - lib/rsmp/components.rb
218
224
  - lib/rsmp/convert/export/json_schema.rb