asterism 0.3.0 → 0.4.0
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 +4 -4
- data/CHANGELOG.md +110 -0
- data/README.md +245 -63
- data/lib/asterism/cruby/objects.rb +25 -10
- data/lib/asterism/cruby/ros.rb +6 -4
- data/lib/asterism/cruby/zenoh.rb +190 -60
- data/lib/asterism/version.rb +1 -1
- data/lib/asterism.rb +2 -2
- data/mrblib/asterism.rb +112 -19
- data/mrblib/cdr.rb +5 -1
- data/mrblib/future.rb +11 -2
- data/mrblib/proxy.rb +13 -3
- data/mrblib/ros.rb +118 -38
- metadata +5 -4
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# The object layer (Asterism.connect / expose / []) with blocks and a
|
|
2
2
|
# receiving thread (CRuby only). Asterism.connect without a block,
|
|
3
|
-
# Asterism.poll and the rest of the
|
|
3
|
+
# Asterism.poll and the rest of the portable API work as on the boards.
|
|
4
4
|
#
|
|
5
5
|
# Asterism.connect("tcp/192.0.2.2:7447", node: "mypc", app: "demo") do |net|
|
|
6
6
|
# net.expose("screen", Screen.new, methods: [:say])
|
|
@@ -23,10 +23,10 @@ module Asterism
|
|
|
23
23
|
# Held by every entry into the object layer (reentrant).
|
|
24
24
|
LOCK = Monitor.new
|
|
25
25
|
|
|
26
|
-
# The
|
|
26
|
+
# The portable API, entered under LOCK. Prepended to the Asterism module's
|
|
27
27
|
# singleton class, so the shared methods themselves are not changed.
|
|
28
28
|
module Locked
|
|
29
|
-
%i[expose unexpose poll nodes [] call_async meta connected? exposed on_join on_leave].each do |m|
|
|
29
|
+
%i[expose unexpose poll nodes [] call_async meta connected? exposed on_join on_leave off_join off_leave].each do |m|
|
|
30
30
|
define_method(m) do |*args, **kw, &blk|
|
|
31
31
|
::Asterism::LOCK.synchronize { super(*args, **kw, &blk) }
|
|
32
32
|
end
|
|
@@ -35,9 +35,11 @@ module Asterism
|
|
|
35
35
|
# With a block: yields an Asterism::Net and closes when the block ends
|
|
36
36
|
# (also on an exception); returns the block's value. Without a block,
|
|
37
37
|
# as before (returns Asterism).
|
|
38
|
-
def connect(locator, node:, app:, mode: nil, listen: nil,
|
|
38
|
+
def connect(locator, node:, app:, mode: nil, listen: nil, config: nil, connect_timeout: nil, check_timeout: nil,
|
|
39
|
+
&blk)
|
|
39
40
|
::Asterism::LOCK.synchronize do
|
|
40
|
-
super(locator, node: node, app: app, mode: mode, listen: listen
|
|
41
|
+
super(locator, node: node, app: app, mode: mode, listen: listen, config: config,
|
|
42
|
+
connect_timeout: connect_timeout, check_timeout: check_timeout)
|
|
41
43
|
# The Net of a connection that was lost (not closed) belongs to the
|
|
42
44
|
# old session.
|
|
43
45
|
old = @net
|
|
@@ -145,15 +147,17 @@ module Asterism
|
|
|
145
147
|
::Asterism.unexpose(name)
|
|
146
148
|
end
|
|
147
149
|
|
|
148
|
-
# A proxy for <node>/<app>/<object>; timeout in seconds
|
|
149
|
-
|
|
150
|
-
|
|
150
|
+
# A proxy for <node>/<app>/<object>; timeout: in seconds (or
|
|
151
|
+
# timeout_ms:).
|
|
152
|
+
def [](path, timeout: nil, timeout_ms: nil)
|
|
153
|
+
::Asterism[path, timeout: timeout, timeout_ms: timeout_ms]
|
|
151
154
|
end
|
|
152
155
|
alias proxy []
|
|
153
156
|
|
|
154
157
|
# The exposed objects alive now matching the pattern, as proxies. With
|
|
155
|
-
# a block, yields each and returns their number
|
|
156
|
-
#
|
|
158
|
+
# a block, yields each and returns their number (1.0: returns self, as
|
|
159
|
+
# Ruby's each does; net.count is the number); without, an Enumerator
|
|
160
|
+
# (net.each("*/demo/info").map(&:status)).
|
|
157
161
|
def each(pattern = "**", &blk)
|
|
158
162
|
return enum_for(:each, pattern) unless blk
|
|
159
163
|
::Asterism.each(pattern, &blk)
|
|
@@ -173,6 +177,17 @@ module Asterism
|
|
|
173
177
|
self
|
|
174
178
|
end
|
|
175
179
|
|
|
180
|
+
# Removes a block given to on_join / on_leave (keep the Proc).
|
|
181
|
+
def off_join(blk)
|
|
182
|
+
::Asterism.off_join(blk)
|
|
183
|
+
self
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def off_leave(blk)
|
|
187
|
+
::Asterism.off_leave(blk)
|
|
188
|
+
self
|
|
189
|
+
end
|
|
190
|
+
|
|
176
191
|
# on_error { |error, where| }: what on_join / on_leave blocks raise.
|
|
177
192
|
# (An exposed method that raises is answered to its caller as a
|
|
178
193
|
# RemoteError, as before; it does not come here.)
|
data/lib/asterism/cruby/ros.rb
CHANGED
|
@@ -197,9 +197,11 @@ module Asterism
|
|
|
197
197
|
Topic.new(self, topic, type, qos, depth)
|
|
198
198
|
end
|
|
199
199
|
|
|
200
|
-
# Node#call
|
|
201
|
-
|
|
202
|
-
|
|
200
|
+
# Node#call; here timeout: is always the time limit, also for a
|
|
201
|
+
# request type with a field named timeout (give such a request as
|
|
202
|
+
# request: { ... }).
|
|
203
|
+
def call(service, type, req = nil, request: nil, timeout: nil, timeout_ms: nil, **fields)
|
|
204
|
+
ms = ::Asterism.time_ms("Node#call", timeout, timeout_ms, nil, nil)
|
|
203
205
|
c = @asterism_runner.lock.synchronize do
|
|
204
206
|
@clients ||= {}
|
|
205
207
|
cl = @clients[service]
|
|
@@ -209,7 +211,7 @@ module Asterism
|
|
|
209
211
|
end
|
|
210
212
|
cl
|
|
211
213
|
end
|
|
212
|
-
c.call(request, timeout_ms: ms, **fields)
|
|
214
|
+
c.call(req, request: request, timeout_ms: ms, **fields)
|
|
213
215
|
end
|
|
214
216
|
end
|
|
215
217
|
|
data/lib/asterism/cruby/zenoh.rb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# Asterism::Zenoh with blocks, threads and Enumerators (CRuby only). The
|
|
2
|
-
#
|
|
2
|
+
# portable API of asterism-zenoh (Session, each_pending, each_reply) is the
|
|
3
3
|
# same on the boards and stays as it is; this is a layer on top of it.
|
|
4
4
|
#
|
|
5
5
|
# Asterism::Zenoh.open("tcp/192.0.2.2:7447") do |s|
|
|
@@ -80,10 +80,63 @@ module Asterism
|
|
|
80
80
|
end
|
|
81
81
|
end
|
|
82
82
|
|
|
83
|
-
# Seconds (Float) or nil -> milliseconds for the
|
|
83
|
+
# Seconds (Float) or nil -> milliseconds for the portable API.
|
|
84
|
+
# @api private
|
|
84
85
|
def self.ms(seconds, default_ms)
|
|
85
|
-
|
|
86
|
-
|
|
86
|
+
::Asterism.time_ms("timeout:", seconds, nil, nil, default_ms)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Warns once for owner (a wrapper, or a Get) when raw (what it wraps)
|
|
90
|
+
# dropped something. Only for queues whose depth the application left
|
|
91
|
+
# at the default: one that chose depth: reads dropped itself.
|
|
92
|
+
# @api private
|
|
93
|
+
def self.note_dropped(owner, raw, what, unit)
|
|
94
|
+
d = raw.dropped
|
|
95
|
+
return false if d == 0
|
|
96
|
+
::Asterism.warn_once(owner, "asterism: #{what}: #{d} #{unit} dropped, the queue was full " \
|
|
97
|
+
"(pass a larger depth:, or read dropped)")
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# The keys liveliness_get returns: an Array, with the counts of the get
|
|
101
|
+
# behind it.
|
|
102
|
+
class KeyList < Array
|
|
103
|
+
# Replies that did not fit the get's queue (oldest first), and all
|
|
104
|
+
# that came.
|
|
105
|
+
attr_reader :dropped, :received
|
|
106
|
+
|
|
107
|
+
# @api private
|
|
108
|
+
def finish(get)
|
|
109
|
+
@dropped = get.dropped
|
|
110
|
+
@received = get.received
|
|
111
|
+
self
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# What Connection#get and Querier#get return without a block: an
|
|
116
|
+
# Enumerator (each iteration sends the get again) that also has the
|
|
117
|
+
# counts of the last get it sent: dropped, received, errors (nil before
|
|
118
|
+
# the first).
|
|
119
|
+
class GetEnumerator < Enumerator
|
|
120
|
+
attr_reader :dropped, :received, :errors
|
|
121
|
+
|
|
122
|
+
# @api private
|
|
123
|
+
def finish(get)
|
|
124
|
+
@dropped = get.dropped
|
|
125
|
+
@received = get.received
|
|
126
|
+
@errors = get.errors
|
|
127
|
+
self
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Yields obj and closes it after the block (the block's value), or
|
|
132
|
+
# returns obj without a block. @api private
|
|
133
|
+
def self.scoped(obj)
|
|
134
|
+
return obj unless block_given?
|
|
135
|
+
begin
|
|
136
|
+
yield obj
|
|
137
|
+
ensure
|
|
138
|
+
obj.close
|
|
139
|
+
end
|
|
87
140
|
end
|
|
88
141
|
|
|
89
142
|
# Waits on the calling thread until a sample comes into sub (an
|
|
@@ -130,30 +183,34 @@ module Asterism
|
|
|
130
183
|
|
|
131
184
|
# A declared publisher (Connection::Publisher): put / delete,
|
|
132
185
|
# matching?, on_matching { |listening| }. opts: those of
|
|
133
|
-
# Session#publisher (encoding:, priority:, ...).
|
|
134
|
-
|
|
135
|
-
|
|
186
|
+
# Session#publisher (encoding:, priority:, ...). With a block: yields
|
|
187
|
+
# it and closes it after the block (returns the block's value).
|
|
188
|
+
def publisher(key, **opts, &blk)
|
|
189
|
+
Zenoh.scoped(Publisher.new(self, @session.publisher(key, **opts), key), &blk)
|
|
136
190
|
end
|
|
137
191
|
|
|
138
192
|
# An advanced publisher (cache:, sample_miss_detection:,
|
|
139
193
|
# publisher_detection: and the publisher options): late subscribers
|
|
140
|
-
# with history get what it kept. Same object as publisher
|
|
141
|
-
|
|
142
|
-
|
|
194
|
+
# with history get what it kept. Same object as publisher (and the
|
|
195
|
+
# same block form).
|
|
196
|
+
def advanced_publisher(key, **opts, &blk)
|
|
197
|
+
Zenoh.scoped(Publisher.new(self, @session.advanced_publisher(key, **opts), key), &blk)
|
|
143
198
|
end
|
|
144
199
|
|
|
145
200
|
# An advanced subscriber (history:, recovery:, subscriber_detection:,
|
|
146
|
-
# query_timeout_ms:): like subscribe,
|
|
201
|
+
# query_timeout: in seconds or query_timeout_ms:): like subscribe,
|
|
202
|
+
# plus on_publisher and on_miss.
|
|
147
203
|
def advanced_subscriber(key, depth: 16, **opts, &blk)
|
|
148
|
-
sub = AdvancedSubscription.new(self, @session.advanced_subscriber(key, depth, **opts), key)
|
|
204
|
+
sub = AdvancedSubscription.new(self, @session.advanced_subscriber(key, depth: depth, **opts), key)
|
|
149
205
|
sub.handle(&blk) if blk
|
|
150
206
|
sub
|
|
151
207
|
end
|
|
152
208
|
|
|
153
209
|
# A declared get (Connection::Querier): get { |reply| }, matching?,
|
|
154
|
-
# on_matching. timeout in seconds
|
|
155
|
-
|
|
156
|
-
|
|
210
|
+
# on_matching. timeout: in seconds (2.0) or timeout_ms:; the rest as
|
|
211
|
+
# Session#querier.
|
|
212
|
+
def querier(key, timeout: nil, **opts)
|
|
213
|
+
Querier.new(self, @session.querier(key, timeout: timeout, **opts), key)
|
|
157
214
|
end
|
|
158
215
|
|
|
159
216
|
# on_transport(history: false) { |event| }: a TransportEvent (kind
|
|
@@ -161,21 +218,22 @@ module Asterism
|
|
|
161
218
|
# peer or router connects or goes. Returns an Events (close it).
|
|
162
219
|
def on_transport(history: false, depth: 16, &blk)
|
|
163
220
|
raise ArgumentError, "a block is needed" unless blk
|
|
164
|
-
Events.new(self, @session.transport_events(depth, history: history), "on_transport", blk)
|
|
221
|
+
Events.new(self, @session.transport_events(depth: depth, history: history), "on_transport", blk)
|
|
165
222
|
end
|
|
166
223
|
|
|
167
224
|
# on_link(history: false) { |event| }: a LinkEvent each time a link
|
|
168
225
|
# opens or closes.
|
|
169
226
|
def on_link(history: false, depth: 16, &blk)
|
|
170
227
|
raise ArgumentError, "a block is needed" unless blk
|
|
171
|
-
Events.new(self, @session.link_events(depth, history: history), "on_link", blk)
|
|
228
|
+
Events.new(self, @session.link_events(depth: depth, history: history), "on_link", blk)
|
|
172
229
|
end
|
|
173
230
|
|
|
174
231
|
# With a block: every sample is given to it (as a Sample) on the
|
|
175
232
|
# receiving thread; returns the Subscription (close it to stop).
|
|
176
|
-
# Without: a Subscription to take from (each,
|
|
177
|
-
def subscribe(key, depth:
|
|
178
|
-
|
|
233
|
+
# Without: a Subscription to take from (each, each_sample).
|
|
234
|
+
def subscribe(key, depth: nil, &blk)
|
|
235
|
+
d = depth.nil? ? DEFAULT_DEPTH : depth
|
|
236
|
+
sub = Subscription.new(self, @session.subscribe(key, depth: d), key, warn: depth.nil?)
|
|
179
237
|
sub.handle(&blk) if blk
|
|
180
238
|
sub
|
|
181
239
|
end
|
|
@@ -184,53 +242,65 @@ module Asterism
|
|
|
184
242
|
# finished when it returns (reply in the block with q.reply). Without:
|
|
185
243
|
# a Queryable whose each yields the queries (finished after each).
|
|
186
244
|
def queryable(key, depth: 16, complete: false, &blk)
|
|
187
|
-
qa = Queryable.new(self, @session.queryable(key, depth, complete: complete), key)
|
|
245
|
+
qa = Queryable.new(self, @session.queryable(key, depth: depth, complete: complete), key)
|
|
188
246
|
qa.handle(&blk) if blk
|
|
189
247
|
qa
|
|
190
248
|
end
|
|
191
249
|
|
|
192
250
|
# The replies to a get: yields each Reply until every answer came or
|
|
193
|
-
# timeout (seconds) ran out, and returns their number
|
|
194
|
-
#
|
|
195
|
-
#
|
|
196
|
-
#
|
|
197
|
-
#
|
|
198
|
-
|
|
199
|
-
|
|
251
|
+
# timeout (seconds; or timeout_ms:) ran out, and returns their number
|
|
252
|
+
# (not named each, so the count stays). Without a block, a
|
|
253
|
+
# GetEnumerator (each iteration sends the get again; dropped /
|
|
254
|
+
# received / errors of the last one). errors: true also yields the
|
|
255
|
+
# error replies (Reply#error?). depth: the replies kept until taken
|
|
256
|
+
# (DEFAULT_GET_DEPTH, 1024); replies past it are dropped, which warns
|
|
257
|
+
# once unless depth: was given. opts: encoding:, priority:,
|
|
258
|
+
# congestion_control:, express:, accept_replies: (Session#get).
|
|
259
|
+
def get(key, timeout: nil, timeout_ms: nil, params: nil, payload: nil, attachment: nil, target: :all,
|
|
260
|
+
consolidation: :none, errors: false, depth: nil, **opts, &blk)
|
|
261
|
+
ms = ::Asterism.time_ms("Connection#get", timeout, timeout_ms, nil, 2000)
|
|
262
|
+
opts[:depth] = depth unless depth.nil?
|
|
200
263
|
start = lambda do
|
|
201
|
-
@session.get(key,
|
|
264
|
+
@session.get(key, timeout_ms: ms, params: params, payload: payload,
|
|
202
265
|
attachment: attachment, target: target, consolidation: consolidation, **opts)
|
|
203
266
|
end
|
|
204
|
-
|
|
205
|
-
get_each(start, errors, &blk)
|
|
267
|
+
get_run(start, errors, "get #{key}", depth.nil?, &blk)
|
|
206
268
|
end
|
|
207
269
|
|
|
208
|
-
# A liveliness token (close it to withdraw).
|
|
209
|
-
|
|
210
|
-
|
|
270
|
+
# A liveliness token (close it to withdraw). With a block: the token
|
|
271
|
+
# is withdrawn after the block (returns the block's value).
|
|
272
|
+
def liveliness(key, &blk)
|
|
273
|
+
Zenoh.scoped(@session.liveliness(key), &blk)
|
|
211
274
|
end
|
|
212
275
|
|
|
213
276
|
# With a block: yields key and alive (true when the token appeared) on
|
|
214
277
|
# the receiving thread for each change; the tokens alive now come
|
|
215
|
-
# first. Without: a Watch whose each yields Liveliness
|
|
216
|
-
|
|
217
|
-
|
|
278
|
+
# first, in one burst. Without: a Watch whose each yields Liveliness
|
|
279
|
+
# values. depth: DEFAULT_WATCH_DEPTH (1024); changes past it are
|
|
280
|
+
# dropped (Watch#dropped), which warns once unless depth: was given.
|
|
281
|
+
def liveliness_watch(key, depth: nil, &blk)
|
|
282
|
+
d = depth.nil? ? DEFAULT_WATCH_DEPTH : depth
|
|
283
|
+
w = Watch.new(self, @session.liveliness_watch(key, depth: d), key, warn: depth.nil?)
|
|
218
284
|
w.handle(&blk) if blk
|
|
219
285
|
w
|
|
220
286
|
end
|
|
221
287
|
|
|
222
|
-
# The keys of the liveliness tokens alive now (an Array
|
|
223
|
-
# the answers, at most timeout
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
288
|
+
# The keys of the liveliness tokens alive now (a KeyList, an Array
|
|
289
|
+
# with dropped and received; waits for the answers, at most timeout
|
|
290
|
+
# seconds, or timeout_ms:). depth: DEFAULT_GET_DEPTH (1024); keys
|
|
291
|
+
# past it are dropped, which warns once unless depth: was given.
|
|
292
|
+
def liveliness_get(key, timeout: nil, timeout_ms: nil, depth: nil)
|
|
293
|
+
ms = ::Asterism.time_ms("Connection#liveliness_get", timeout, timeout_ms, nil, 2000)
|
|
294
|
+
g = @session.liveliness_get(key, timeout_ms: ms, depth: depth)
|
|
295
|
+
keys = KeyList.new
|
|
227
296
|
loop do
|
|
297
|
+
ended = g.done? # before taking the replies (see get_each)
|
|
228
298
|
g.each_reply.each { |r| keys << r[0] }
|
|
229
|
-
break if g.
|
|
299
|
+
break if ended && g.pending == 0
|
|
230
300
|
sleep(ENUM_STEP)
|
|
231
301
|
end
|
|
232
|
-
g
|
|
233
|
-
keys
|
|
302
|
+
Zenoh.note_dropped(g, g, "liveliness_get #{key}", "keys") if depth.nil?
|
|
303
|
+
keys.finish(g)
|
|
234
304
|
end
|
|
235
305
|
|
|
236
306
|
# Receives on a thread of its own (blocks run there). Returns self.
|
|
@@ -274,8 +344,15 @@ module Asterism
|
|
|
274
344
|
@session.zid
|
|
275
345
|
end
|
|
276
346
|
|
|
347
|
+
# The routers (client) or peers (peer mode) connected now.
|
|
348
|
+
def connection_count
|
|
349
|
+
@session.connection_count
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
# Deprecated: connection_count.
|
|
277
353
|
def peers
|
|
278
|
-
|
|
354
|
+
::Asterism.deprecated("Connection#peers", "Connection#connection_count")
|
|
355
|
+
@session.connection_count
|
|
279
356
|
end
|
|
280
357
|
|
|
281
358
|
# The Zenoh IDs of the peers / routers connected now.
|
|
@@ -306,10 +383,19 @@ module Asterism
|
|
|
306
383
|
|
|
307
384
|
private
|
|
308
385
|
|
|
386
|
+
# The block form (get_each, the count) or a GetEnumerator over it.
|
|
387
|
+
def get_run(start, errors, what, warn, &blk)
|
|
388
|
+
return get_each(start, errors, what, warn, nil, &blk) if blk
|
|
389
|
+
e = nil
|
|
390
|
+
e = GetEnumerator.new { |y| get_each(start, errors, what, warn, e) { |r| y << r } }
|
|
391
|
+
end
|
|
392
|
+
|
|
309
393
|
# Sends the get (start) and yields each Reply; error replies only
|
|
310
394
|
# with errors. The done? before taking the replies: once the get is
|
|
311
|
-
# done, every reply it had is already in the queue.
|
|
312
|
-
|
|
395
|
+
# done, every reply it had is already in the queue. Warns once when
|
|
396
|
+
# replies were dropped (warn: depth left at the default); stats (a
|
|
397
|
+
# GetEnumerator or nil) gets the counts.
|
|
398
|
+
def get_each(start, errors, what = "get", warn = true, stats = nil)
|
|
313
399
|
g = start.call
|
|
314
400
|
n = 0
|
|
315
401
|
loop do
|
|
@@ -323,23 +409,28 @@ module Asterism
|
|
|
323
409
|
break if done && g.pending == 0
|
|
324
410
|
sleep(ENUM_STEP) if got.empty?
|
|
325
411
|
end
|
|
412
|
+
Zenoh.note_dropped(g, g, what, "replies") if warn
|
|
413
|
+
stats&.finish(g)
|
|
326
414
|
n
|
|
327
415
|
end
|
|
328
416
|
|
|
329
417
|
# A subscription of a Connection. Either its block gets the samples
|
|
330
418
|
# (on the receiving thread), or the application takes them: each (an
|
|
331
419
|
# Enumerator that waits for samples) or each_pending (what is there
|
|
332
|
-
# now, as the
|
|
420
|
+
# now, as the portable API).
|
|
333
421
|
class Subscription
|
|
334
422
|
include Enumerable
|
|
335
423
|
|
|
336
424
|
attr_reader :key, :subscriber
|
|
337
425
|
|
|
338
|
-
|
|
426
|
+
# warn: say once when samples were dropped (the depth was left at
|
|
427
|
+
# the default).
|
|
428
|
+
def initialize(conn, subscriber, key, warn: false)
|
|
339
429
|
@conn = conn
|
|
340
430
|
@subscriber = subscriber
|
|
341
431
|
@key = key
|
|
342
432
|
@task = nil
|
|
433
|
+
@warn = warn
|
|
343
434
|
end
|
|
344
435
|
|
|
345
436
|
def handle(&blk)
|
|
@@ -349,29 +440,48 @@ module Asterism
|
|
|
349
440
|
@task = r.add do
|
|
350
441
|
got = @subscriber.each_sample
|
|
351
442
|
got.each { |s| r.guard(where) { blk.call(s) } }
|
|
443
|
+
note_dropped unless got.empty?
|
|
352
444
|
got.size
|
|
353
445
|
end
|
|
354
446
|
self
|
|
355
447
|
end
|
|
356
448
|
|
|
449
|
+
# @api private
|
|
450
|
+
def note_dropped
|
|
451
|
+
@warn && Zenoh.note_dropped(self, @subscriber, "subscribe #{@key}", "samples")
|
|
452
|
+
end
|
|
453
|
+
|
|
357
454
|
# Yields each Sample as it comes, waiting for the next; ends when the
|
|
358
455
|
# subscription or the session closes, or after timeout seconds.
|
|
359
456
|
# Without a block, an Enumerator (each.lazy.map { ... }.first(3)).
|
|
360
457
|
def each(timeout: nil, &blk)
|
|
361
458
|
return enum_for(:each, timeout: timeout) unless blk
|
|
362
459
|
raise ::Asterism::Error, "this subscription has a block; its samples go there" if @task
|
|
363
|
-
Zenoh.drain(@subscriber, @conn.session, timeout, take: :each_sample)
|
|
460
|
+
Zenoh.drain(@subscriber, @conn.session, timeout, take: :each_sample) do |s|
|
|
461
|
+
note_dropped
|
|
462
|
+
blk.call(s)
|
|
463
|
+
end
|
|
364
464
|
self
|
|
365
465
|
end
|
|
366
466
|
|
|
367
|
-
# The samples there now as Samples (an Array), or yields them
|
|
368
|
-
|
|
467
|
+
# The samples there now as Samples (an Array), or yields them and
|
|
468
|
+
# returns their number. (The portable API's each_sample.)
|
|
469
|
+
def each_sample
|
|
369
470
|
got = @subscriber.each_sample
|
|
471
|
+
note_dropped unless got.empty?
|
|
370
472
|
return got unless block_given?
|
|
371
473
|
got.each { |s| yield s }
|
|
372
474
|
got.size
|
|
373
475
|
end
|
|
374
476
|
|
|
477
|
+
# Deprecated: each_sample. In the portable API each_pending gives
|
|
478
|
+
# [key, payload, attachment] Arrays; here it gave Samples, so one
|
|
479
|
+
# name had two shapes.
|
|
480
|
+
def each_pending(&blk)
|
|
481
|
+
::Asterism.deprecated("Connection::Subscription#each_pending", "each_sample")
|
|
482
|
+
each_sample(&blk)
|
|
483
|
+
end
|
|
484
|
+
|
|
375
485
|
def pending = @subscriber.pending
|
|
376
486
|
def received = @subscriber.received
|
|
377
487
|
def dropped = @subscriber.dropped
|
|
@@ -455,11 +565,14 @@ module Asterism
|
|
|
455
565
|
|
|
456
566
|
attr_reader :key, :watch
|
|
457
567
|
|
|
458
|
-
|
|
568
|
+
# warn: say once when changes were dropped (the depth was left at
|
|
569
|
+
# the default).
|
|
570
|
+
def initialize(conn, watch, key, warn: false)
|
|
459
571
|
@conn = conn
|
|
460
572
|
@watch = watch
|
|
461
573
|
@key = key
|
|
462
574
|
@task = nil
|
|
575
|
+
@warn = warn
|
|
463
576
|
end
|
|
464
577
|
|
|
465
578
|
def handle(&blk)
|
|
@@ -469,6 +582,7 @@ module Asterism
|
|
|
469
582
|
@task = r.add do
|
|
470
583
|
got = @watch.each_pending
|
|
471
584
|
got.each { |e| r.guard(where) { blk.call(e[0], e[1]) } }
|
|
585
|
+
note_dropped unless got.empty?
|
|
472
586
|
got.size
|
|
473
587
|
end
|
|
474
588
|
self
|
|
@@ -479,10 +593,24 @@ module Asterism
|
|
|
479
593
|
def each(timeout: nil, &blk)
|
|
480
594
|
return enum_for(:each, timeout: timeout) unless blk
|
|
481
595
|
raise ::Asterism::Error, "this watch has a block; its changes go there" if @task
|
|
482
|
-
Zenoh.drain(@watch, @conn.session, timeout)
|
|
596
|
+
Zenoh.drain(@watch, @conn.session, timeout) do |e|
|
|
597
|
+
note_dropped
|
|
598
|
+
blk.call(Liveliness.new(e[0], e[1]))
|
|
599
|
+
end
|
|
483
600
|
self
|
|
484
601
|
end
|
|
485
602
|
|
|
603
|
+
# @api private
|
|
604
|
+
def note_dropped
|
|
605
|
+
@warn && Zenoh.note_dropped(self, @watch, "liveliness_watch #{@key}", "changes")
|
|
606
|
+
end
|
|
607
|
+
|
|
608
|
+
# Changes waiting / received so far / dropped because the queue was
|
|
609
|
+
# full (the oldest go; the watch no longer knows which tokens are
|
|
610
|
+
# alive, so declare it again).
|
|
611
|
+
def pending = @watch.pending
|
|
612
|
+
def received = @watch.received
|
|
613
|
+
def dropped = @watch.dropped
|
|
486
614
|
def closed? = @watch.closed?
|
|
487
615
|
|
|
488
616
|
def close
|
|
@@ -554,11 +682,13 @@ module Asterism
|
|
|
554
682
|
|
|
555
683
|
# Yields each Reply until every answer came or the querier's time
|
|
556
684
|
# ran out; returns their number. errors: true also yields the error
|
|
557
|
-
# replies. Without a block,
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
685
|
+
# replies. depth: as Connection#get. Without a block, a
|
|
686
|
+
# GetEnumerator.
|
|
687
|
+
def get(params: nil, payload: nil, attachment: nil, encoding: nil, errors: false, depth: nil, &blk)
|
|
688
|
+
opts = { attachment: attachment, encoding: encoding }
|
|
689
|
+
opts[:depth] = depth unless depth.nil?
|
|
690
|
+
start = -> { @querier.get(params, payload, **opts) }
|
|
691
|
+
@conn.send(:get_run, start, errors, "querier get #{@key}", depth.nil?, &blk)
|
|
562
692
|
end
|
|
563
693
|
|
|
564
694
|
def matching? = @querier.matching?
|
data/lib/asterism/version.rb
CHANGED
data/lib/asterism.rb
CHANGED
|
@@ -16,8 +16,8 @@ require_relative "asterism/version"
|
|
|
16
16
|
require_relative "../mrblib/#{f}"
|
|
17
17
|
end
|
|
18
18
|
require_relative "asterism/cruby"
|
|
19
|
-
# The
|
|
20
|
-
# pattern matching): CRuby only, see README "The
|
|
19
|
+
# The CRuby API on top (blocks, a receiving thread, Enumerators,
|
|
20
|
+
# pattern matching): CRuby only, see README "The CRuby API".
|
|
21
21
|
%w[runner zenoh objects ros].each do |f|
|
|
22
22
|
require_relative "asterism/cruby/#{f}"
|
|
23
23
|
end
|