rsmp 0.8.0 → 0.8.4

Sign up to get free protection for your applications and to get access to all the features.
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