rsmp 0.4.4 → 0.5.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b82a88e9cd80aeb3bf0bc89b774727155dc8c6418520493c34a852809eb29e94
4
- data.tar.gz: 16cb2331281e470233ff28fcf6ac1e89124a88628d920f8f3d7e486b0a076b2f
3
+ metadata.gz: a60faacf7dbd02175c26ff74a0576bcba1eae29d7ac53973ed4991a8952d94d3
4
+ data.tar.gz: dffbf77a1385be65a90e1b6ebd8edd8a109bd27ee54eeee5d9d3651c64f10abc
5
5
  SHA512:
6
- metadata.gz: 47d08d2fab1e0dd76dc5e988b3ee4e56a3110258402ffc9d1d8213ca7cbd889e94d08119100b785dfc5803dfd5f0618ac25c2597e1499cebd7fbd2db500614d5
7
- data.tar.gz: 321f695677507a66fa03a81fc2bdc87350df51278e53e95bb6f75e5eeea180ea3e1503f0ee072aea425970d32e7a814a8a683cd33abdf7d832cd8c83e216ff97
6
+ metadata.gz: a117f1ddeb790ff61d550359bfa28445b13322b66155c6f213035c7a4f01c27cecb0ea1229c2891125e26e06a54314b9fd8f1002b36bd2c8925daa5f630225e7
7
+ data.tar.gz: 6e6f9a2e1da0296d9f635b5e07fb74efecaa84b819a7ac16fea84c144a1d48804a3582e4e39de367c5d7fc0ba23da83e30e6650af907848fbc81b309d123dd90
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rsmp (0.4.3)
4
+ rsmp (0.5.1)
5
5
  async (~> 1.29.1)
6
6
  async-io (~> 1.32.1)
7
7
  colorize (~> 0.8.1)
@@ -19,6 +19,7 @@ log:
19
19
  text: true
20
20
  direction: true
21
21
  level: false
22
+ debug: true
22
23
  json: true
23
24
  acknowledgements: false
24
25
  watchdogs: false
data/config/tlc.yaml CHANGED
@@ -38,6 +38,7 @@ log:
38
38
  ip: false
39
39
  site_id: true
40
40
  level: false
41
+ debug: true
41
42
  text: true
42
43
  direction: true
43
44
  json: true
@@ -7,7 +7,12 @@ module RSMP
7
7
 
8
8
  def initialize proxy, options={}
9
9
  super proxy, options
10
- @options = options.clone
10
+ @options = {
11
+ cancel: {
12
+ schema_error: true,
13
+ disconnect: false,
14
+ }
15
+ }.deep_merge options
11
16
  @ingoing = options[:ingoing] == nil ? true : options[:ingoing]
12
17
  @outgoing = options[:outgoing] == nil ? false : options[:outgoing]
13
18
  @condition = Async::Notification.new
@@ -82,7 +87,7 @@ module RSMP
82
87
  if message.is_a?(MessageNotAck)
83
88
  if message.attribute('oMId') == @options[:m_id]
84
89
  m_id_short = RSMP::Message.shorten_m_id @options[:m_id], 8
85
- @error = RSMP::MessageRejected.new("#{@title} #{m_id_short} was rejected: #{message.attribute('rea')}")
90
+ @error = RSMP::MessageRejected.new("#{@title} #{m_id_short} was rejected with '#{message.attribute('rea')}'")
86
91
  complete
87
92
  end
88
93
  false
@@ -123,6 +128,43 @@ module RSMP
123
128
  @condition.signal
124
129
  end
125
130
 
131
+ # The proxy experienced some error.
132
+ # Check if this should cause us to cancel.
133
+ def notify_error error, options={}
134
+ case error
135
+ when RSMP::SchemaError
136
+ notify_schema_error error, options
137
+ when RSMP::ConnectionError
138
+ notify_disconnect error, options
139
+ end
140
+ end
141
+
142
+ # Cancel if we received e schema error for a message type we're collecting
143
+ def notify_schema_error error, options
144
+ return unless @options.dig(:cancel,:schema_error)
145
+ message = options[:message]
146
+ return unless message
147
+ klass = message.class.name.split('::').last
148
+ return unless [@options[:type]].flatten.include? klass
149
+ @proxy.log "Collect cancelled due to schema error in #{klass} #{message.m_id_short}", level: :debug
150
+ cancel error
151
+ end
152
+
153
+ # Cancel if we received e notificaiton about a disconnect
154
+ def notify_disconnect error, options
155
+ return unless @options.dig(:cancel,:disconnect)
156
+ @proxy.log "Collect cancelled due to a connection error: #{error.to_s}", level: :debug
157
+ cancel error
158
+ end
159
+
160
+ # Abort collection
161
+ def cancel error
162
+ @error = error if error
163
+ @done = false
164
+ @proxy.remove_listener self
165
+ @condition.signal
166
+ end
167
+
126
168
  # Store a message in the result array
127
169
  def keep message
128
170
  @messages << message
@@ -12,6 +12,9 @@ module RSMP
12
12
  def notify message
13
13
  end
14
14
 
15
+ def notify_error error, options={}
16
+ end
17
+
15
18
  def listen &block
16
19
  @proxy.add_listener self
17
20
  yield
@@ -102,6 +102,5 @@ module RSMP
102
102
  end
103
103
  @proxy.log "#{@title.capitalize} collect reached #{summary}", level: :debug
104
104
  end
105
-
106
105
  end
107
106
  end
@@ -2,6 +2,8 @@
2
2
 
3
3
  module RSMP
4
4
  module Notifier
5
+ attr_reader :listeners
6
+
5
7
  include Inspect
6
8
 
7
9
  def inspect
@@ -10,6 +12,22 @@ module RSMP
10
12
 
11
13
  def initialize_distributor
12
14
  @listeners = []
15
+ @defer_notify = false
16
+ @notify_queue = []
17
+ end
18
+
19
+ def deferred_notify &block
20
+ was, @defer_notify = @defer_notify, true
21
+ yield
22
+ dequeue_notify
23
+ ensure
24
+ @defer_notify = was
25
+ end
26
+
27
+ def dequeue_notify
28
+ @notify_queue.each { |message| notify_without_defer message }
29
+ ensure
30
+ @notify_queue = []
13
31
  end
14
32
 
15
33
  def add_listener listener
@@ -23,7 +41,20 @@ module RSMP
23
41
  end
24
42
 
25
43
  def notify message
44
+ raise ArgumentError unless message
45
+ if @defer_notify
46
+ @notify_queue << message
47
+ else
48
+ notify_without_defer message
49
+ end
50
+ end
51
+
52
+ def notify_without_defer message
26
53
  @listeners.each { |listener| listener.notify message }
27
54
  end
55
+
56
+ def distribute_error error, options={}
57
+ @listeners.each { |listener| listener.notify_error error, options }
58
+ end
28
59
  end
29
60
  end
data/lib/rsmp/error.rb CHANGED
@@ -32,6 +32,9 @@ module RSMP
32
32
  class FatalError < Error
33
33
  end
34
34
 
35
+ class HandshakeError < FatalError
36
+ end
37
+
35
38
  class NotReady < Error
36
39
  end
37
40
 
data/lib/rsmp/logger.rb CHANGED
@@ -5,6 +5,7 @@ module RSMP
5
5
 
6
6
  def initialize settings={}
7
7
  defaults = {
8
+ 'prefix'=>nil,
8
9
  'active'=>false,
9
10
  'path'=>nil,
10
11
  'stream'=>nil,
@@ -20,7 +21,8 @@ module RSMP
20
21
  'json'=>false,
21
22
  'debug'=>false,
22
23
  'statistics'=>false,
23
- 'hide_ip_and_port' => false
24
+ 'hide_ip_and_port' => false,
25
+ 'acknowledgements' => false
24
26
  }
25
27
  if settings
26
28
  @settings = defaults.merge settings
@@ -139,6 +141,7 @@ module RSMP
139
141
 
140
142
  def build_output item
141
143
  parts = []
144
+ parts << "#{@settings['prefix']} " if @settings['prefix']
142
145
  parts << item[:index].to_s.ljust(7) if @settings["index"] == true
143
146
  parts << item[:author].to_s.ljust(13) if @settings["author"] == true
144
147
  parts << Clock.to_s(item[:timestamp]).ljust(24) unless @settings["timestamp"] == false
data/lib/rsmp/message.rb CHANGED
@@ -142,7 +142,7 @@ module RSMP
142
142
  def validate schemas
143
143
  errors = RSMP::Schemer.validate attributes, schemas
144
144
  if errors
145
- error_string = errors.compact.join(', ').strip
145
+ error_string = errors.map {|item| item.reject {|e| e=='' } }.compact.join(', ').strip
146
146
  raise SchemaError.new error_string
147
147
  end
148
148
  end
data/lib/rsmp/proxy.rb CHANGED
@@ -86,6 +86,7 @@ module RSMP
86
86
  return if @state == :stopped
87
87
  set_state :stopping
88
88
  stop_tasks
89
+ notify_error ConnectionError.new("Connection was closed")
89
90
  ensure
90
91
  close_socket
91
92
  clear
@@ -237,6 +238,7 @@ module RSMP
237
238
  if now > latest
238
239
  log "No acknowledgements for #{message.type} #{message.m_id_short} within #{timeout} seconds", level: :error
239
240
  stop
241
+ notify_error MissingAcknowledgment.new('No ack')
240
242
  end
241
243
  end
242
244
  end
@@ -266,7 +268,7 @@ module RSMP
266
268
  # TODO
267
269
  # what schema should we use to validate the intial Version and MessageAck messages?
268
270
  schemas = { core: '3.1.5' }
269
- schemas[sxl] = RSMP::Schemer.sanitize_version(sxl_version) if sxl
271
+ schemas[sxl] = RSMP::Schemer.sanitize_version(sxl_version) if sxl && sxl_version
270
272
  schemas
271
273
  end
272
274
 
@@ -315,13 +317,23 @@ module RSMP
315
317
  !skip.include?(klass)
316
318
  end
317
319
 
320
+ def process_deferred
321
+ node.process_deferred
322
+ end
323
+
324
+ def verify_sequence message
325
+ expect_version_message(message) unless @version_determined
326
+ end
327
+
318
328
  def process_packet json
319
329
  attributes = Message.parse_attributes json
320
330
  message = Message.build attributes, json
321
331
  message.validate(get_schemas) if should_validate_ingoing_message?(message)
322
- notify message
323
- expect_version_message(message) unless @version_determined
324
- process_message message
332
+ verify_sequence message
333
+ deferred_notify do
334
+ notify message
335
+ process_message message
336
+ end
325
337
  process_deferred
326
338
  message
327
339
  rescue InvalidPacket => e
@@ -338,17 +350,17 @@ module RSMP
338
350
  rescue SchemaError, RSMP::Schemer::Error => e
339
351
  str = "Received invalid #{message.type}, schema errors: #{e.message}"
340
352
  log str, message: message, level: :warning
341
- notify_error e.exception("#{str} #{message.json}")
353
+ notify_error e.exception("#{str} #{message.json}"), message: message
342
354
  dont_acknowledge message, str
343
355
  message
344
356
  rescue InvalidMessage => e
345
357
  str = "Received", "invalid #{message.type}, #{e.message}"
346
- notify_error e.exception("#{str} #{message.json}")
358
+ notify_error e.exception("#{str} #{message.json}"), message: message
347
359
  dont_acknowledge message, str
348
360
  message
349
361
  rescue FatalError => e
350
362
  str = "Rejected #{message.type},"
351
- notify_error e.exception("#{str} #{message.json}")
363
+ notify_error e.exception("#{str} #{message.json}"), message: message
352
364
  dont_acknowledge message, str, "#{e.message}"
353
365
  stop
354
366
  message
@@ -402,7 +414,7 @@ module RSMP
402
414
  if candidates.any?
403
415
  @rsmp_version = candidates.sort_by { |v| Gem::Version.new(v) }.last # pick latest version
404
416
  else
405
- raise FatalError.new "RSMP versions [#{message.versions.join(',')}] requested, but only [#{versions.join(',')}] supported."
417
+ raise HandshakeError.new "RSMP versions [#{message.versions.join(',')}] requested, but only [#{versions.join(',')}] supported."
406
418
  end
407
419
  end
408
420
 
@@ -546,7 +558,7 @@ module RSMP
546
558
 
547
559
  def expect_version_message message
548
560
  unless message.is_a?(Version) || message.is_a?(MessageAck) || message.is_a?(MessageNotAck)
549
- raise FatalError.new "Version must be received first"
561
+ raise HandshakeError.new "Version must be received first"
550
562
  end
551
563
  end
552
564
 
@@ -578,7 +590,7 @@ module RSMP
578
590
  # will be raised in the parent task, and caught by rspec.
579
591
  # rspec will then show the error and record the test as failed
580
592
  m_id_short = RSMP::Message.shorten_m_id m_id, 8
581
- result = RSMP::MessageRejected.new "Aggregated status request #{m_id_short} was rejected: #{message.attribute('rea')}"
593
+ result = RSMP::MessageRejected.new "Aggregated status request #{m_id_short} was rejected with '#{message.attribute('rea')}'"
582
594
  next true # done, no more messages wanted
583
595
  end
584
596
  elsif message.is_a?(MessageAck)
@@ -587,6 +599,5 @@ module RSMP
587
599
  false
588
600
  end
589
601
  end
590
-
591
602
  end
592
603
  end
@@ -75,10 +75,6 @@ module RSMP
75
75
  acknowledge message
76
76
  end
77
77
 
78
- def process_deferred
79
- supervisor.process_deferred
80
- end
81
-
82
78
  def version_accepted message
83
79
  log "Received Version message for site #{@site_id}", message: message, level: :log
84
80
  start_timer
@@ -333,6 +329,7 @@ module RSMP
333
329
 
334
330
  def notify_error e, options={}
335
331
  @supervisor.notify_error e, options if @supervisor
332
+ distribute_error e, options
336
333
  end
337
334
 
338
335
  def collect_alarms parent_task, options={}
@@ -7,7 +7,7 @@ module RSMP
7
7
  attr_reader :rsmp_versions, :site_id, :supervisor_settings, :proxies, :logger
8
8
 
9
9
  def initialize options={}
10
- handle_supervisor_settings options
10
+ handle_supervisor_settings( options[:supervisor_settings] || {} )
11
11
  super options
12
12
  @proxies = []
13
13
  @site_id_condition = Async::Notification.new
@@ -17,7 +17,7 @@ module RSMP
17
17
  @supervisor_settings['site_id']
18
18
  end
19
19
 
20
- def handle_supervisor_settings options={}
20
+ def handle_supervisor_settings supervisor_settings
21
21
  defaults = {
22
22
  'port' => 12111,
23
23
  'ips' => 'all',
@@ -36,8 +36,8 @@ module RSMP
36
36
  }
37
37
 
38
38
  # merge options into defaults
39
- @supervisor_settings = defaults.deep_merge(options[:supervisor_settings] || {})
40
- @rsmp_versions = @supervisor_settings["rsmp_versions"]
39
+ @supervisor_settings = defaults.deep_merge(supervisor_settings)
40
+ @rsmp_versions = @supervisor_settings["guest"]["rsmp_versions"]
41
41
  check_site_sxl_types
42
42
  end
43
43
 
@@ -172,7 +172,12 @@ module RSMP
172
172
  id = peek_version_message protocol
173
173
  proxy = find_site id
174
174
  if proxy
175
- proxy.revive settings
175
+ if proxy.connected?
176
+ raise ConnectionError.new("Site #{id} alredy connected from port #{proxy.port}")
177
+ else
178
+ p proxy.state
179
+ proxy.revive settings
180
+ end
176
181
  else
177
182
  check_max_sites
178
183
  proxy = build_proxy settings.merge(site_id:id) # keep the id learned by peeking above
@@ -246,7 +251,7 @@ module RSMP
246
251
 
247
252
  def check_site_already_connected site_id
248
253
  site = find_site(site_id)
249
- raise FatalError.new "Site '#{site_id}' already connected" if site != nil && site != self
254
+ raise HandshakeError.new "Site '#{site_id}' already connected" if site != nil && site != self
250
255
  end
251
256
 
252
257
  def site_id_to_site_setting site_id
@@ -256,7 +261,7 @@ module RSMP
256
261
  return settings
257
262
  end
258
263
  end
259
- raise FatalError.new "site id #{site_id} unknown"
264
+ raise HandshakeError.new "site id #{site_id} unknown"
260
265
  end
261
266
 
262
267
  def ip_to_site_settings ip
@@ -86,10 +86,6 @@ module RSMP
86
86
  dont_acknowledge message, '', e.to_s
87
87
  end
88
88
 
89
- def process_deferred
90
- site.process_deferred
91
- end
92
-
93
89
  def acknowledged_first_ingoing message
94
90
  # TODO
95
91
  # aggregateds status should only be send for later version of rsmp
data/lib/rsmp/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module RSMP
2
- VERSION = "0.4.4"
2
+ VERSION = "0.5.1"
3
3
  end
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.4
4
+ version: 0.5.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: 2021-10-29 00:00:00.000000000 Z
11
+ date: 2021-11-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async