rsmp 0.8.0 → 0.8.4

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.
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.8.0
4
+ version: 0.8.4
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-07 00:00:00.000000000 Z
11
+ date: 2022-01-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async
@@ -201,19 +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
- - lib/rsmp/collect/message_collector.rb
213
216
  - lib/rsmp/collect/message_matchers.rb
214
- - lib/rsmp/collect/message_queries.rb
215
217
  - lib/rsmp/collect/notifier.rb
216
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
217
222
  - lib/rsmp/component.rb
218
223
  - lib/rsmp/components.rb
219
224
  - lib/rsmp/convert/export/json_schema.rb
@@ -1,209 +0,0 @@
1
- module RSMP
2
-
3
- # Collects ingoing and/or outgoing messages from a notifier.
4
- # Can filter by message type and wakes up the client once the desired number of messages has been collected.
5
- class MessageCollector < Collector
6
- attr_reader :condition, :messages, :done
7
-
8
- def initialize proxy, options={}
9
- super proxy, options
10
- @options = {
11
- cancel: {
12
- schema_error: true,
13
- disconnect: false,
14
- }
15
- }.deep_merge options
16
- @ingoing = options[:ingoing] == nil ? true : options[:ingoing]
17
- @outgoing = options[:outgoing] == nil ? false : options[:outgoing]
18
- @condition = Async::Notification.new
19
- @title = options[:title] || [@options[:type]].flatten.join('/')
20
- @options[:timeout] ||= 1
21
- @options[:num] ||= 1
22
- reset
23
- end
24
-
25
- # Inspect formatter that shows the message we have collected
26
- def inspect
27
- "#<#{self.class.name}:#{self.object_id}, #{inspector(:@messages)}>"
28
- end
29
-
30
- # Want ingoing messages?
31
- def ingoing?
32
- @ingoing == true
33
- end
34
-
35
- # Want outgoing messages?
36
- def outgoing?
37
- @outgoing == true
38
- end
39
-
40
- # Block until all messages have been collected
41
- def wait
42
- @condition.wait
43
- end
44
-
45
- # Collect message
46
- # Will block until all messages have been collected,
47
- # or we time out
48
- def collect task, options={}, &block
49
- @options.merge! options
50
- @block = block
51
- unless @done
52
- listen do
53
- task.with_timeout(@options[:timeout]) do
54
- @condition.wait
55
- end
56
- end
57
- end
58
- return @error if @error
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
67
- end
68
-
69
- # Return progress as collected vs. number requested
70
- def progress
71
- need = @options[:num]
72
- reached = @messages.size
73
- { need: need, got: reached }
74
- end
75
-
76
- # Get the collected message.
77
- def message
78
- @messages.first
79
- end
80
-
81
- # Get the collected messages.
82
- def messages
83
- @messages
84
- end
85
-
86
- # Clear all query results
87
- def reset
88
- @messages = []
89
- @error = nil
90
- @done = false
91
- end
92
-
93
- # Check if we receive a NotAck related to initiating request, identified by @m_id.
94
- def check_not_ack message
95
- return unless @options[:m_id]
96
- if message.is_a?(MessageNotAck)
97
- if message.attribute('oMId') == @options[:m_id]
98
- m_id_short = RSMP::Message.shorten_m_id @options[:m_id], 8
99
- @error = RSMP::MessageRejected.new("#{@title} #{m_id_short} was rejected with '#{message.attribute('rea')}'")
100
- complete
101
- end
102
- false
103
- end
104
- end
105
-
106
- # Handle message. and return true when we're done collecting
107
- def notify message
108
- raise ArgumentError unless message
109
- raise RuntimeError.new("can't process message when already done") if @done
110
- check_not_ack(message)
111
- return true if @done
112
- perform_match message
113
- complete if done?
114
- @done
115
- end
116
-
117
- # Match message against our collection criteria
118
- def perform_match message
119
- matched = type_match?(message) && block_match?(message)
120
- if matched == true
121
- keep message
122
- elsif matched == false
123
- forget message
124
- end
125
- end
126
-
127
- # Have we collected the required number of messages?
128
- def done?
129
- @options[:num] && @messages.size >= @options[:num]
130
- end
131
-
132
- # Called when we're done collecting. Remove ourself as a listener,
133
- # se we don't receive message notifications anymore
134
- def complete
135
- @done = true
136
- @proxy.remove_listener self
137
- @condition.signal
138
- end
139
-
140
- # The proxy experienced some error.
141
- # Check if this should cause us to cancel.
142
- def notify_error error, options={}
143
- case error
144
- when RSMP::SchemaError
145
- notify_schema_error error, options
146
- when RSMP::ConnectionError
147
- notify_disconnect error, options
148
- end
149
- end
150
-
151
- # Cancel if we received e schema error for a message type we're collecting
152
- def notify_schema_error error, options
153
- return unless @options.dig(:cancel,:schema_error)
154
- message = options[:message]
155
- return unless message
156
- klass = message.class.name.split('::').last
157
- return unless [@options[:type]].flatten.include? klass
158
- @proxy.log "Collect cancelled due to schema error in #{klass} #{message.m_id_short}", level: :debug
159
- cancel error
160
- end
161
-
162
- # Cancel if we received e notificaiton about a disconnect
163
- def notify_disconnect error, options
164
- return unless @options.dig(:cancel,:disconnect)
165
- @proxy.log "Collect cancelled due to a connection error: #{error.to_s}", level: :debug
166
- cancel error
167
- end
168
-
169
- # Abort collection
170
- def cancel error
171
- @error = error if error
172
- @done = false
173
- @proxy.remove_listener self
174
- @condition.signal
175
- end
176
-
177
- # Store a message in the result array
178
- def keep message
179
- @messages << message
180
- end
181
-
182
- # Remove a message from the result array
183
- def forget message
184
- @messages.delete message
185
- end
186
-
187
- # Check a message against our match criteria
188
- # Return true if there's a match, false if not
189
- def type_match? message
190
- return false if message.direction == :in && @ingoing == false
191
- return false if message.direction == :out && @outgoing == false
192
- if @options[:type]
193
- if @options[:type].is_a? Array
194
- return false unless @options[:type].include? message.type
195
- else
196
- return false unless message.type == @options[:type]
197
- end
198
- end
199
- if @options[:component]
200
- return false if message.attributes['cId'] && message.attributes['cId'] != @options[:component]
201
- end
202
- true
203
- end
204
- end
205
-
206
- def block_match? message
207
- @block.call(message) == true
208
- end
209
- end