zillabyte-cli 0.1.37 → 0.1.38
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 +8 -8
- data/lib/zillabyte/cli/flows.rb +10 -1
- data/lib/zillabyte/runner/app_runner.rb +13 -6
- data/lib/zillabyte/runner/component_operation.rb +190 -152
- data/lib/zillabyte/runner/component_runner.rb +5 -3
- data/lib/zillabyte/runner/multilang_operation.rb +178 -77
- data/lib/zillabyte-cli/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
ODc2YjU3ZTY2MWI5YWUxZjQwNjc3YjljN2FjNGYwN2U1ZjQwNjkwZA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
NzhlMDhkODI1MzY4OTVjNzRhNzVlZWVjYWQ2NTM2OWYwNGNlNTQ3Nw==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
YzM4NWFkNzZmOTYwYjJmMGZmYTdiMTRkYmQ3NjlkYWVhMjFjMmZiYTU0MzUx
|
10
|
+
ZGM1ZjRkZGFhMWIxMWMxZThiOWNhNzUwMmFkMWY5NDhjZTYyMjBkMzgyMzBj
|
11
|
+
NmY4NmMzOWE0NDE5ZTMzZmEwYzViNzhkNjYzYmUyN2YzNzcxYzE=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
ODQ2ZDQ1N2M1ZTU4YjY3NjQyYzhlNmRiYjNkMTliMjMzOWFhYzhmYzA1ZWMx
|
14
|
+
MGFiOGE5ZGU1ODE3ZGQ5ODQwNGM1OWVkMDBkNzQzNTEwZWFmMjM2YTIzNTky
|
15
|
+
NjQwYjMzMTIyNjlkNjRjNDFkZWU4NDQ5YTBlZTVkOWNiNzdhYjU=
|
data/lib/zillabyte/cli/flows.rb
CHANGED
@@ -319,10 +319,20 @@ class Zillabyte::Command::Flows < Zillabyte::Command::Base
|
|
319
319
|
:body => options.to_json
|
320
320
|
)
|
321
321
|
|
322
|
+
return if res.body.nil? or res.body["state"].nil?
|
322
323
|
flow_state = res.body["state"]
|
324
|
+
if type.nil?
|
325
|
+
display "State: #{flow_state}"
|
326
|
+
elsif ["KILLED", "RETIRED"].member? flow_state
|
327
|
+
display res.body.to_json
|
328
|
+
return
|
329
|
+
end
|
330
|
+
|
331
|
+
return if res.body["instances"].nil?
|
323
332
|
instances = res.body["instances"].select do |instance|
|
324
333
|
!instance.nil?
|
325
334
|
end
|
335
|
+
return if instances.empty?
|
326
336
|
|
327
337
|
# a nested hash so can't map directly
|
328
338
|
# instead i'll map separately and then merge the arrays
|
@@ -420,7 +430,6 @@ class Zillabyte::Command::Flows < Zillabyte::Command::Base
|
|
420
430
|
# output on the CLI
|
421
431
|
if type.nil?
|
422
432
|
require("zillabyte/cli/helpers/table_output_builder")
|
423
|
-
display "State: #{flow_state}"
|
424
433
|
display TableOutputBuilder.build_terminal_table(headings, rows)
|
425
434
|
if from_dataset == true
|
426
435
|
display "percent complete: #{completion}%\n"
|
@@ -4,6 +4,8 @@ require "zillabyte/runner/multilang_operation"
|
|
4
4
|
class Zillabyte::Runner::AppRunner < Zillabyte::Command::Base
|
5
5
|
include Zillabyte::Helpers
|
6
6
|
|
7
|
+
END_CYCLE_MESSAGE = "{\"command\": \"end_cycle\"}\n"
|
8
|
+
|
7
9
|
def run (meta, dir = Dir.pwd, session = nil, options = {})
|
8
10
|
|
9
11
|
if meta.nil? or session.nil?
|
@@ -197,6 +199,7 @@ class Zillabyte::Runner::AppRunner < Zillabyte::Command::Base
|
|
197
199
|
display e.message
|
198
200
|
display e.backtrace
|
199
201
|
ensure
|
202
|
+
|
200
203
|
# Close the reading end of the child
|
201
204
|
pipes["rd_child_1"].close()
|
202
205
|
# Close the writing end of the child
|
@@ -214,7 +217,6 @@ class Zillabyte::Runner::AppRunner < Zillabyte::Command::Base
|
|
214
217
|
|
215
218
|
if interactive
|
216
219
|
display "To view results: Enter 'end' "
|
217
|
-
display "To exit the test: Enter 'Ctrl-C' "
|
218
220
|
display ""
|
219
221
|
|
220
222
|
|
@@ -222,11 +224,16 @@ class Zillabyte::Runner::AppRunner < Zillabyte::Command::Base
|
|
222
224
|
display "Enter an input tuple in JSON format i.e.{ \"url\" : \"foo.com\", \"html\" : \"bar.html\" }"
|
223
225
|
msg = ask
|
224
226
|
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
227
|
+
|
228
|
+
if msg == "end"
|
229
|
+
msg = END_CYCLE_MESSAGE
|
230
|
+
else
|
231
|
+
begin
|
232
|
+
JSON.parse(msg)
|
233
|
+
rescue JSON::ParserError
|
234
|
+
display "Received invalid JSON object"
|
235
|
+
next
|
236
|
+
end
|
230
237
|
end
|
231
238
|
# Send tuple to source
|
232
239
|
@operation_pipes["source_1"]["wr_parent_1"].puts msg
|
@@ -6,6 +6,7 @@ class Zillabyte::Runner::ComponentOperation
|
|
6
6
|
|
7
7
|
NEXT_MESSAGE = "{\"command\": \"next\"}\n"
|
8
8
|
DONE_MESSAGE = "{\"command\": \"done\"}\n"
|
9
|
+
KILL_CYCLE_MESSAGE = "{\"command\": \"kill_cycle\"}\n"
|
9
10
|
END_CYCLE_MESSAGE = "{\"command\": \"end_cycle\"}\n"
|
10
11
|
ENDMARKER = "\nend\n"
|
11
12
|
|
@@ -49,7 +50,6 @@ class Zillabyte::Runner::ComponentOperation
|
|
49
50
|
cdisplay e.message
|
50
51
|
cdisplay e.backtrace
|
51
52
|
end
|
52
|
-
|
53
53
|
end
|
54
54
|
|
55
55
|
|
@@ -104,22 +104,28 @@ class Zillabyte::Runner::ComponentOperation
|
|
104
104
|
consumer = consumer_hash[r][:consumer]
|
105
105
|
|
106
106
|
# Consumer is ready for next message
|
107
|
-
if msg["command"]
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
107
|
+
if msg["command"]
|
108
|
+
case msg["command"]
|
109
|
+
when "next"
|
110
|
+
|
111
|
+
@__emit_queues[stream][consumer][:ready] = true
|
112
|
+
tuple_json = get_consumer_tuple(stream, consumer)
|
113
|
+
|
114
|
+
# If all messages have been sent to consumer, end their cycle
|
115
|
+
if tuple_json.nil?
|
116
|
+
write_stream = get_write_stream(stream, consumer)
|
117
|
+
cdisplay "ending cycle for #{consumer}"
|
118
|
+
send_command_tuple(stream, consumer, END_CYCLE_MESSAGE)
|
119
|
+
send_command_tuple(stream, consumer, DONE_MESSAGE)
|
120
|
+
|
121
|
+
else
|
122
|
+
# Emit tuple to consumer
|
123
|
+
emit_consumer_tuple(stream, consumer, tuple_json)
|
124
|
+
emitted = true
|
125
|
+
end
|
118
126
|
|
119
|
-
|
120
|
-
|
121
|
-
emit_consumer_tuple(stream, consumer, tuple_json)
|
122
|
-
emitted = true
|
127
|
+
when "kill_cycle"
|
128
|
+
send_to_consumers(KILL_CYCLE_MESSAGE)
|
123
129
|
end
|
124
130
|
end
|
125
131
|
end
|
@@ -136,28 +142,23 @@ class Zillabyte::Runner::ComponentOperation
|
|
136
142
|
loop do
|
137
143
|
|
138
144
|
msg = stdin.gets
|
139
|
-
if msg ==
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
+
if msg == END_CYCLE_MESSAGE
|
146
|
+
send_to_consumers(END_CYCLE_MESSAGE)
|
147
|
+
send_to_consumers(DONE_MESSAGE)
|
148
|
+
return
|
149
|
+
else
|
150
|
+
# Build tuples
|
151
|
+
args = msg.scan(/(?:\w|"[^"]*")+/).map {|s| s.gsub(/[\'\"]/, '')}
|
152
|
+
component_args = []
|
153
|
+
|
154
|
+
while(true) do
|
155
|
+
break if args.empty?
|
156
|
+
tuple = {}
|
157
|
+
fields.each {|f| tuple[f] = args.shift}
|
158
|
+
tuple_json = build_tuple_json(tuple)
|
159
|
+
display_json = Hash[JSON.parse(tuple_json)["tuple"].map {|k,v| [Zillabyte::Runner::Operation.truncate_message(k), Zillabyte::Runner::Operation.truncate_message(v)]}].to_json
|
160
|
+
send_to_consumers(tuple_json)
|
145
161
|
end
|
146
|
-
|
147
|
-
break
|
148
|
-
end
|
149
|
-
|
150
|
-
# Build tuples
|
151
|
-
args = msg.scan(/(?:\w|"[^"]*")+/).map {|s| s.gsub(/[\'\"]/, '')}
|
152
|
-
component_args = []
|
153
|
-
|
154
|
-
while(true) do
|
155
|
-
break if args.empty?
|
156
|
-
tuple = {}
|
157
|
-
fields.each {|f| tuple[f] = args.shift}
|
158
|
-
tuple_json = build_tuple_json(tuple)
|
159
|
-
display_json = Hash[JSON.parse(tuple_json)["tuple"].map {|k,v| [Zillabyte::Runner::Operation.truncate_message(k), Zillabyte::Runner::Operation.truncate_message(v)]}].to_json
|
160
|
-
send_to_consumers(tuple_json)
|
161
162
|
end
|
162
163
|
end
|
163
164
|
end
|
@@ -173,11 +174,12 @@ class Zillabyte::Runner::ComponentOperation
|
|
173
174
|
# Keep track of how many consumers to handle before exiting
|
174
175
|
consumers_running = consumer_hash.keys.length
|
175
176
|
|
177
|
+
# Kill the cycle on error
|
178
|
+
cycle_killed = false
|
179
|
+
|
176
180
|
# Begin cycle
|
177
181
|
end_cycle_received = false
|
178
182
|
|
179
|
-
|
180
|
-
# TODO multiple inputs
|
181
183
|
# The input component(singular at the moment)
|
182
184
|
read_streams = consumer_hash.keys.concat [@__consumee_pipes["rd_child_1"]]
|
183
185
|
|
@@ -204,155 +206,172 @@ class Zillabyte::Runner::ComponentOperation
|
|
204
206
|
|
205
207
|
fields = source_nodes[0]["fields"]
|
206
208
|
|
207
|
-
|
208
|
-
loop do
|
209
|
-
|
210
|
-
# Read from a stream
|
211
|
-
rs = select_read_streams(read_streams)
|
212
|
-
rs.each do |r|
|
213
|
-
# Read a message
|
214
|
-
obj = read_message(r)
|
215
|
-
|
216
|
-
# Handle tuple through RPC
|
217
|
-
if obj['tuple']
|
218
|
-
cdisplay("error: The number of inputs to the component does not match the declared number for stream #{source_nodes[0]["name"]}.") if obj['tuple'].size != fields.size
|
219
|
-
rpc_inputs = []
|
220
|
-
fields.each do |field|
|
221
|
-
rpc_inputs << obj['tuple'][field.keys[0]]
|
222
|
-
end
|
223
|
-
|
224
|
-
display_json = Hash[obj['tuple'].map{|k, v| [Zillabyte::Runner::Operation.truncate_message(k), Zillabyte::Runner::Operation.truncate_message(v)]}].to_json
|
225
|
-
|
226
|
-
|
227
|
-
# Send RPC call
|
228
|
-
cdisplay "sending RPC call..."
|
229
|
-
call_options = {
|
230
|
-
:rpc_inputs => [rpc_inputs],
|
231
|
-
:output_format => output_format
|
232
|
-
}
|
209
|
+
begin
|
233
210
|
|
234
|
-
|
235
|
-
|
211
|
+
# Receive and handle messages
|
212
|
+
loop do
|
213
|
+
|
214
|
+
# Read from a stream
|
215
|
+
rs = select_read_streams(read_streams)
|
216
|
+
rs.each do |r|
|
217
|
+
# Read a message
|
218
|
+
obj = read_message(r)
|
219
|
+
|
220
|
+
# Handle tuple through RPC
|
221
|
+
if obj['tuple']
|
222
|
+
cdisplay("error: The number of inputs to the component does not match the declared number for stream #{source_nodes[0]["name"]}.") if obj['tuple'].size != fields.size
|
223
|
+
rpc_inputs = []
|
224
|
+
fields.each do |field|
|
225
|
+
rpc_inputs << obj['tuple'][field.keys[0]]
|
226
|
+
end
|
236
227
|
|
237
|
-
|
238
|
-
|
239
|
-
cdisplay("error: #{res['error']}")
|
240
|
-
next
|
241
|
-
end
|
242
|
-
run_ids = []
|
243
|
-
res['execute_ids'].each do |q, qid|
|
244
|
-
run_ids << qid
|
245
|
-
end
|
246
|
-
status = res['status']
|
228
|
+
display_json = Hash[obj['tuple'].map{|k, v| [Zillabyte::Runner::Operation.truncate_message(k), Zillabyte::Runner::Operation.truncate_message(v)]}].to_json
|
229
|
+
|
247
230
|
|
231
|
+
# Send RPC call
|
232
|
+
cdisplay "sending RPC call..."
|
233
|
+
call_options = {
|
234
|
+
:rpc_inputs => [rpc_inputs],
|
235
|
+
:output_format => output_format
|
236
|
+
}
|
248
237
|
|
249
|
-
|
250
|
-
|
238
|
+
res = caller.rpc(component_id, call_options)
|
239
|
+
cdisplay "received API response : #{res}"
|
251
240
|
|
252
|
-
#
|
253
|
-
ids_in_progress = []
|
254
|
-
res = caller.get_rpc_results(component_id, {:execute_ids => run_ids})
|
241
|
+
#TODO handle errors
|
255
242
|
if res['error']
|
256
243
|
cdisplay("error: #{res['error']}")
|
257
244
|
next
|
258
245
|
end
|
246
|
+
run_ids = []
|
247
|
+
res['execute_ids'].each do |q, qid|
|
248
|
+
run_ids << qid
|
249
|
+
end
|
250
|
+
status = res['status']
|
251
|
+
|
252
|
+
|
253
|
+
# Send result call
|
254
|
+
loop do
|
255
|
+
|
256
|
+
# If a call for results is not ready, save the execution ID for the next cycle
|
257
|
+
ids_in_progress = []
|
258
|
+
res = caller.get_rpc_results(component_id, {:execute_ids => run_ids})
|
259
|
+
if res['error']
|
260
|
+
cdisplay("error: #{res['error']}")
|
261
|
+
next
|
262
|
+
end
|
259
263
|
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
264
|
+
|
265
|
+
# check results
|
266
|
+
res['results'].each do |run_id, hash|
|
267
|
+
|
268
|
+
# We have results
|
269
|
+
if hash['status'] == "complete"
|
270
|
+
|
271
|
+
# Handle Tuple in here
|
272
|
+
data_streams = hash['data']
|
273
|
+
|
274
|
+
# if stream_hash.nil?
|
275
|
+
# cdisplay("error : no results!")
|
276
|
+
# next
|
277
|
+
# else
|
278
|
+
# stream_hash.each_pair
|
279
|
+
# end
|
280
|
+
|
281
|
+
# Handle each resulting tuple
|
282
|
+
data_streams.each_pair do |stream, data_tuples|
|
283
|
+
data_tuples.each do |data_tuple|
|
284
|
+
tuple_json = build_tuple_json(data_tuple)
|
285
|
+
|
286
|
+
#send or enqueue the tuple to all consumers of the stream
|
287
|
+
@__emit_queues.each_pair do |stream, consumers|
|
288
|
+
consumers.each_pair do |consumer, emitter|
|
289
|
+
if emitter[:ready]
|
290
|
+
emit_consumer_tuple(stream, consumer, tuple_json)
|
291
|
+
else
|
292
|
+
@__emit_queues[stream][consumer][:write_queue] << tuple_json
|
293
|
+
end
|
289
294
|
end
|
290
295
|
end
|
291
|
-
end
|
292
296
|
|
297
|
+
end
|
293
298
|
end
|
299
|
+
|
300
|
+
else
|
301
|
+
cdisplay "RPC #{run_id} has not completed... "
|
302
|
+
ids_in_progress << run_id
|
294
303
|
end
|
304
|
+
end
|
305
|
+
run_ids = ids_in_progress
|
295
306
|
|
296
|
-
|
297
|
-
|
298
|
-
|
307
|
+
# If no more IDs to run, we are done
|
308
|
+
if run_ids.empty?
|
309
|
+
break
|
299
310
|
end
|
300
|
-
end
|
301
|
-
run_ids = ids_in_progress
|
302
311
|
|
303
|
-
|
304
|
-
|
305
|
-
break
|
312
|
+
# Dont spam the API
|
313
|
+
sleep(2)
|
306
314
|
end
|
307
315
|
|
308
|
-
#
|
309
|
-
|
310
|
-
end
|
316
|
+
# Ask for next tuple
|
317
|
+
write_message(@__consumee_pipes["wr_child_1"], NEXT_MESSAGE)
|
311
318
|
|
312
|
-
# Ask for next tuple
|
313
|
-
write_message(@__consumee_pipes["wr_child_1"], NEXT_MESSAGE)
|
314
319
|
|
320
|
+
# End cycle
|
321
|
+
elsif obj['command']
|
322
|
+
case obj["command"]
|
315
323
|
|
316
|
-
|
317
|
-
|
318
|
-
|
324
|
+
# Consumer is ready for a message
|
325
|
+
when "next"
|
326
|
+
stream = consumer_hash[r][:stream]
|
327
|
+
consumer = consumer_hash[r][:consumer]
|
319
328
|
|
320
|
-
|
321
|
-
|
322
|
-
stream = consumer_hash[r][:stream]
|
323
|
-
consumer = consumer_hash[r][:consumer]
|
329
|
+
@__emit_queues[stream][consumer][:ready] = true
|
330
|
+
tuple_json = get_consumer_tuple(stream, consumer)
|
324
331
|
|
325
|
-
|
326
|
-
|
332
|
+
# End cycle for consumer if it has processed all tuples
|
333
|
+
if tuple_json.nil? && end_cycle_received
|
334
|
+
send_command_tuple(stream, consumer, END_CYCLE_MESSAGE)
|
335
|
+
consumers_running -= 1
|
336
|
+
if consumers_running == 0
|
337
|
+
break
|
338
|
+
end
|
327
339
|
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
break
|
340
|
+
# TODO break if last consumer
|
341
|
+
elsif !tuple_json.nil?
|
342
|
+
# Emit tuple to consumer
|
343
|
+
emit_consumer_tuple(stream, consumer, tuple_json)
|
344
|
+
emitted = true
|
334
345
|
end
|
335
346
|
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
347
|
+
when "end_cycle"
|
348
|
+
end_cycle_received = true
|
349
|
+
when "kill_cycle"
|
350
|
+
cycle_killed = true
|
351
|
+
return
|
341
352
|
end
|
342
|
-
|
343
|
-
when "end_cycle"
|
344
|
-
end_cycle_received = true
|
345
353
|
end
|
346
354
|
end
|
355
|
+
|
347
356
|
|
357
|
+
# Exit after ending consumer cycles
|
358
|
+
if consumers_running == 0
|
359
|
+
break
|
360
|
+
end
|
348
361
|
end
|
349
362
|
|
350
|
-
|
351
|
-
|
352
|
-
|
363
|
+
rescue => e
|
364
|
+
cdisplay e.message
|
365
|
+
cdisplay e.backtrace
|
366
|
+
ensure
|
367
|
+
# cleanup
|
368
|
+
if cycle_killed
|
369
|
+
send_to_consumers(KILL_CYCLE_MESSAGE, false)
|
370
|
+
send_to_consumees(KILL_CYCLE_MESSAGE, false)
|
353
371
|
end
|
354
372
|
end
|
355
373
|
|
374
|
+
|
356
375
|
end
|
357
376
|
|
358
377
|
|
@@ -475,6 +494,7 @@ class Zillabyte::Runner::ComponentOperation
|
|
475
494
|
return consumer_hash
|
476
495
|
end
|
477
496
|
|
497
|
+
|
478
498
|
# Send object to every consumer of the operation, regardless of stream
|
479
499
|
def self.send_to_consumers(json_obj)
|
480
500
|
@__consumer_pipes.each_pair do |stream, consumers|
|
@@ -489,11 +509,29 @@ class Zillabyte::Runner::ComponentOperation
|
|
489
509
|
write_message(write_stream, json_obj)
|
490
510
|
end
|
491
511
|
|
492
|
-
cdisplay "emitted #{json_obj} to #{consumer}"
|
512
|
+
cdisplay "emitted #{json_obj.chomp} to #{consumer}"
|
493
513
|
end
|
494
514
|
end
|
495
515
|
end
|
496
516
|
|
517
|
+
|
518
|
+
# Send object to every consumer of the operation, regardless of stream
|
519
|
+
def self.send_to_consumees(json_obj)
|
520
|
+
pipes = @__consumee_pipes
|
521
|
+
# Left hand(or singular) input
|
522
|
+
if (pipes.has_key? "wr_parent_1")
|
523
|
+
write_stream = get_write_stream(stream, consumer, 1)
|
524
|
+
write_message(write_stream, json_obj)
|
525
|
+
end
|
526
|
+
|
527
|
+
# Right hand input
|
528
|
+
if (pipes.has_key? "wr_parent_2")
|
529
|
+
write_stream = get_write_stream(stream, consumer, 2)
|
530
|
+
write_message(write_stream, json_obj)
|
531
|
+
end
|
532
|
+
end
|
533
|
+
|
534
|
+
|
497
535
|
# Get the write pipe of the stream consumer
|
498
536
|
def self.get_write_stream(stream, consumer, number=1)
|
499
537
|
wr_pipe = "wr_parent_" + number.to_s
|
@@ -5,6 +5,8 @@ require "zillabyte/runner/component_operation"
|
|
5
5
|
class Zillabyte::Runner::ComponentRunner < Zillabyte::Command::Base
|
6
6
|
include Zillabyte::Helpers
|
7
7
|
|
8
|
+
END_CYCLE_MESSAGE = "{\"command\": \"end_cycle\"}\n"
|
9
|
+
|
8
10
|
def run (meta, dir = Dir.pwd, session = nil, options = {})
|
9
11
|
|
10
12
|
if meta.nil? or session.nil?
|
@@ -226,7 +228,6 @@ class Zillabyte::Runner::ComponentRunner < Zillabyte::Command::Base
|
|
226
228
|
|
227
229
|
display ""
|
228
230
|
display "To view results: Enter 'end' "
|
229
|
-
display "To exit the test: Enter 'Ctrl-C' "
|
230
231
|
display ""
|
231
232
|
|
232
233
|
while true
|
@@ -234,8 +235,9 @@ class Zillabyte::Runner::ComponentRunner < Zillabyte::Command::Base
|
|
234
235
|
fields = @node_map[source]['fields'].map {|h| h.keys[0].upcase }
|
235
236
|
display "Enter an input tuple in the form : #{fields.join(' ')}"
|
236
237
|
msg = ask
|
237
|
-
|
238
|
-
|
238
|
+
if msg == 'end'
|
239
|
+
msg = END_CYCLE_MESSAGE
|
240
|
+
else
|
239
241
|
args = msg.scan(/(?:\w|"[^"]*")+/)
|
240
242
|
if (args.length % fields.length != 0)
|
241
243
|
display "Error: Argument length must be a multiple of the schema length"
|
@@ -7,6 +7,7 @@ module Zillabyte; module Runner; class MultilangOperation
|
|
7
7
|
NEXT_MESSAGE = "{\"command\": \"next\"}\n"
|
8
8
|
BEGIN_CYCLE_MESSAGE = "{\"command\": \"begin_cycle\"}\n"
|
9
9
|
END_CYCLE_MESSAGE = "{\"command\": \"end_cycle\"}\n"
|
10
|
+
KILL_CYCLE_MESSAGE = "{\"command\": \"kill_cycle\"}\n"
|
10
11
|
PONG_PREFIX = "{\"pong\": \""
|
11
12
|
PONG_SUFFIX = "\"}\n"
|
12
13
|
ENDMARKER = "\nend\n"
|
@@ -61,8 +62,8 @@ module Zillabyte; module Runner; class MultilangOperation
|
|
61
62
|
end
|
62
63
|
rescue => e
|
63
64
|
cdisplay e.message
|
64
|
-
cdisplay e.backtrace
|
65
65
|
end
|
66
|
+
|
66
67
|
end
|
67
68
|
|
68
69
|
|
@@ -76,17 +77,24 @@ module Zillabyte; module Runner; class MultilangOperation
|
|
76
77
|
|
77
78
|
msg = @__consumee_pipes["rd_child_1"].gets
|
78
79
|
|
80
|
+
if msg == END_CYCLE_MESSAGE
|
81
|
+
send_to_consumers(END_CYCLE_MESSAGE)
|
82
|
+
send_to_consumers(DONE_MESSAGE)
|
83
|
+
return
|
84
|
+
else
|
79
85
|
# Build tuple
|
80
86
|
begin
|
81
|
-
|
87
|
+
obj = JSON.parse(msg)
|
82
88
|
rescue JSON::ParserError
|
83
89
|
cdisplay "Error: invalid JSON"
|
84
90
|
next
|
85
91
|
end
|
86
|
-
|
87
|
-
tuple_json = build_tuple_json(
|
92
|
+
|
93
|
+
tuple_json = build_tuple_json(obj)
|
88
94
|
display_json = Hash[JSON.parse(tuple_json)["tuple"].map {|k,v| [Zillabyte::Runner::Operation.truncate_message(k), Zillabyte::Runner::Operation.truncate_message(v)]}].to_json
|
89
95
|
send_to_consumers(tuple_json)
|
96
|
+
|
97
|
+
end
|
90
98
|
end
|
91
99
|
|
92
100
|
# Source from relation
|
@@ -141,21 +149,28 @@ module Zillabyte; module Runner; class MultilangOperation
|
|
141
149
|
consumer = consumer_hash[r][:consumer]
|
142
150
|
|
143
151
|
# Consumer is ready for next message
|
144
|
-
if msg["command"]
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
152
|
+
if msg["command"]
|
153
|
+
|
154
|
+
case msg["command"]
|
155
|
+
when "next"
|
156
|
+
|
157
|
+
@__emit_queues[stream][consumer][:ready] = true
|
158
|
+
tuple_json = get_consumer_tuple(stream, consumer)
|
159
|
+
|
160
|
+
# If all messages have been sent to consumer, end their cycle
|
161
|
+
if tuple_json.nil?
|
162
|
+
write_stream = get_write_stream(stream, consumer)
|
163
|
+
cdisplay "ending cycle for #{consumer}"
|
164
|
+
send_command_tuple(stream, consumer, END_CYCLE_MESSAGE)
|
165
|
+
send_command_tuple(stream, consumer, DONE_MESSAGE)
|
166
|
+
else
|
167
|
+
# Emit tuple to consumer
|
168
|
+
emit_consumer_tuple(stream, consumer, tuple_json)
|
169
|
+
emitted = true
|
170
|
+
end
|
171
|
+
when "kill_cycle"
|
172
|
+
send_to_consumers(KILL_CYCLE_MESSAGE, false)
|
173
|
+
return
|
159
174
|
end
|
160
175
|
end
|
161
176
|
end
|
@@ -169,13 +184,15 @@ module Zillabyte; module Runner; class MultilangOperation
|
|
169
184
|
# Custom source
|
170
185
|
else
|
171
186
|
|
172
|
-
|
173
187
|
# Index streams and consumers by their pipes for lookup
|
174
188
|
consumer_hash = build_consumer_hash()
|
175
189
|
|
176
190
|
# Keep track of how many consumers to handle before exiting
|
177
191
|
consumers_running = consumer_hash.keys.length
|
178
192
|
|
193
|
+
# Kill the cycle on error
|
194
|
+
cycle_killed = false
|
195
|
+
|
179
196
|
# Setup multilang pipe
|
180
197
|
ml_pipe = "#{@__name}_pipe"
|
181
198
|
if File.exists?("#{ml_pipe}.in")
|
@@ -343,7 +360,9 @@ module Zillabyte; module Runner; class MultilangOperation
|
|
343
360
|
next
|
344
361
|
end
|
345
362
|
end_cycle_received = true
|
346
|
-
|
363
|
+
when "kill_cycle"
|
364
|
+
cycle_killed = true
|
365
|
+
return
|
347
366
|
end
|
348
367
|
|
349
368
|
# Multilang sent a ping
|
@@ -358,21 +377,33 @@ module Zillabyte; module Runner; class MultilangOperation
|
|
358
377
|
end
|
359
378
|
|
360
379
|
end
|
361
|
-
rescue
|
362
|
-
|
380
|
+
rescue => e
|
381
|
+
cycle_killed = true
|
382
|
+
cdisplay e.message
|
383
|
+
cdisplay e.backtrace
|
363
384
|
ensure
|
385
|
+
|
364
386
|
# cleanup
|
387
|
+
if cycle_killed
|
388
|
+
send_to_consumers(KILL_CYCLE_MESSAGE, false)
|
389
|
+
end
|
365
390
|
pid = wait_thread[:pid]
|
366
391
|
ml_input.close
|
367
|
-
|
368
|
-
|
392
|
+
if File.exists?("#{ml_pipe}.in")
|
393
|
+
ml_output.close
|
394
|
+
File.delete("#{ml_pipe}.in")
|
395
|
+
end
|
369
396
|
stdout.close
|
370
397
|
stderr.close
|
371
398
|
Process.kill('INT', pid)
|
399
|
+
Process.exit!(true)
|
372
400
|
end
|
373
401
|
end
|
402
|
+
|
374
403
|
rescue PTY::ChildExited
|
375
|
-
|
404
|
+
if File.exists?("#{ml_pipe}.in")
|
405
|
+
File.delete("#{ml_pipe}.in")
|
406
|
+
end
|
376
407
|
end
|
377
408
|
end
|
378
409
|
end
|
@@ -387,6 +418,9 @@ module Zillabyte; module Runner; class MultilangOperation
|
|
387
418
|
# Keep track of how many consumers to handle before exiting
|
388
419
|
consumers_running = consumer_hash.keys.length
|
389
420
|
|
421
|
+
# Kill the cycle on error
|
422
|
+
cycle_killed = false
|
423
|
+
|
390
424
|
# Setup multilang pipe
|
391
425
|
ml_pipe = "#{@__name}_pipe"
|
392
426
|
if File.exists?("#{ml_pipe}.in")
|
@@ -528,14 +562,16 @@ module Zillabyte; module Runner; class MultilangOperation
|
|
528
562
|
send_command_tuple(stream, consumer, END_CYCLE_MESSAGE)
|
529
563
|
consumers_running -= 1
|
530
564
|
if consumers_running == 0
|
531
|
-
|
565
|
+
return
|
532
566
|
end
|
533
567
|
end
|
534
568
|
end
|
535
569
|
end
|
536
|
-
|
537
570
|
end
|
538
|
-
|
571
|
+
|
572
|
+
when "kill_cycle"
|
573
|
+
cycle_killed = true
|
574
|
+
return
|
539
575
|
end
|
540
576
|
|
541
577
|
# Received a tuple from consumee
|
@@ -557,7 +593,7 @@ module Zillabyte; module Runner; class MultilangOperation
|
|
557
593
|
|
558
594
|
# Exit after ending consumer cycles
|
559
595
|
if consumers_running == 0
|
560
|
-
|
596
|
+
return
|
561
597
|
end
|
562
598
|
|
563
599
|
end
|
@@ -566,16 +602,29 @@ module Zillabyte; module Runner; class MultilangOperation
|
|
566
602
|
cdisplay e.backtrace
|
567
603
|
ensure
|
568
604
|
# cleanup
|
605
|
+
if cycle_killed
|
606
|
+
send_to_consumers(KILL_CYCLE_MESSAGE, false)
|
607
|
+
send_to_consumees(KILL_CYCLE_MESSAGE, false)
|
608
|
+
end
|
569
609
|
pid = wait_thread[:pid]
|
570
|
-
ml_input.close
|
571
|
-
|
572
|
-
|
610
|
+
ml_input.close
|
611
|
+
if File.exists?("#{ml_pipe}.in")
|
612
|
+
ml_output.close
|
613
|
+
File.delete("#{ml_pipe}.in")
|
614
|
+
end
|
573
615
|
stdout.close
|
574
616
|
stderr.close
|
617
|
+
Process.kill('INT', pid)
|
618
|
+
Process.exit!(true)
|
575
619
|
end
|
576
620
|
end
|
577
621
|
rescue PTY::ChildExited
|
622
|
+
|
578
623
|
cdisplay("The child process exited!")
|
624
|
+
ensure
|
625
|
+
if File.exists?("#{ml_pipe}.in")
|
626
|
+
File.delete("#{ml_pipe}.in")
|
627
|
+
end
|
579
628
|
end
|
580
629
|
end
|
581
630
|
|
@@ -588,6 +637,9 @@ module Zillabyte; module Runner; class MultilangOperation
|
|
588
637
|
# Keep track of how many consumers to handle before exiting
|
589
638
|
consumers_running = consumer_hash.keys.length
|
590
639
|
|
640
|
+
# Kill the cycle on error
|
641
|
+
cycle_killed = false
|
642
|
+
|
591
643
|
# Setup groups
|
592
644
|
group_by = @__node['group_by']
|
593
645
|
group_tuples = {}
|
@@ -696,7 +748,11 @@ module Zillabyte; module Runner; class MultilangOperation
|
|
696
748
|
write_message(ml_input, tuple_json)
|
697
749
|
end
|
698
750
|
end
|
699
|
-
|
751
|
+
|
752
|
+
# An error has occured
|
753
|
+
when "kill_cycle"
|
754
|
+
cycle_killed = true
|
755
|
+
return
|
700
756
|
end
|
701
757
|
|
702
758
|
# Received a tuple from operation
|
@@ -790,13 +846,17 @@ module Zillabyte; module Runner; class MultilangOperation
|
|
790
846
|
elsif consumers_running == 0
|
791
847
|
break
|
792
848
|
end
|
793
|
-
|
794
|
-
|
849
|
+
|
795
850
|
end
|
796
851
|
rescue Errno::EIO
|
797
852
|
cdisplay("Errno:EIO error")
|
798
853
|
ensure
|
799
854
|
# cleanup
|
855
|
+
if cycle_killed
|
856
|
+
send_to_consumers(KILL_CYCLE_MESSAGE, false)
|
857
|
+
send_to_consumers(KILL_CYCLE_MESSAGE, false)
|
858
|
+
end
|
859
|
+
|
800
860
|
pid = wait_thread[:pid]
|
801
861
|
ml_input.close
|
802
862
|
ml_output.close
|
@@ -804,9 +864,13 @@ module Zillabyte; module Runner; class MultilangOperation
|
|
804
864
|
stdout.close
|
805
865
|
stderr.close
|
806
866
|
Process.kill('INT', pid)
|
867
|
+
Process.exit!(true)
|
807
868
|
end
|
808
869
|
end
|
809
870
|
rescue PTY::ChildExited
|
871
|
+
if File.exists?("#{ml_pipe}.in")
|
872
|
+
File.delete("#{ml_pipe}.in")
|
873
|
+
end
|
810
874
|
cdisplay("The child process exited!")
|
811
875
|
end
|
812
876
|
end
|
@@ -828,6 +892,9 @@ module Zillabyte; module Runner; class MultilangOperation
|
|
828
892
|
# Index the consumee streams for left and right sides
|
829
893
|
consumer_hash = build_consumer_hash()
|
830
894
|
|
895
|
+
# Kill the cycle on error
|
896
|
+
cycle_killed = false
|
897
|
+
|
831
898
|
# read all tuples from lefthand and right hand streams
|
832
899
|
read_streams = [@__consumee_pipes["rd_child_1"], @__consumee_pipes["rd_child_2"]]
|
833
900
|
|
@@ -879,6 +946,10 @@ module Zillabyte; module Runner; class MultilangOperation
|
|
879
946
|
if left_end_cycle_received && right_end_cycle_received
|
880
947
|
break
|
881
948
|
end
|
949
|
+
|
950
|
+
when "kill_cycle"
|
951
|
+
cycle_killed = true
|
952
|
+
return
|
882
953
|
end
|
883
954
|
|
884
955
|
# Received a tuple from consumee
|
@@ -1115,21 +1186,27 @@ module Zillabyte; module Runner; class MultilangOperation
|
|
1115
1186
|
stream = consumer_hash[r][:stream]
|
1116
1187
|
|
1117
1188
|
# Consumer is ready for next message
|
1118
|
-
if msg["command"]
|
1189
|
+
if msg["command"]
|
1190
|
+
case msg["command"]
|
1191
|
+
when"next"
|
1119
1192
|
|
1120
|
-
|
1121
|
-
|
1193
|
+
@__emit_queues[stream][consumer][:ready] = true
|
1194
|
+
tuple_json = get_consumer_tuple(stream, consumer)
|
1122
1195
|
|
1123
|
-
|
1124
|
-
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1128
|
-
|
1196
|
+
# If all messages have been sent to a consumer, end its cycle
|
1197
|
+
if tuple_json.nil?
|
1198
|
+
send_command_tuple(stream, consumer, END_CYCLE_MESSAGE)
|
1199
|
+
consumers_running -= 1
|
1200
|
+
if consumers_running == 0
|
1201
|
+
return
|
1202
|
+
end
|
1203
|
+
else
|
1204
|
+
# Emit tuple to consumer
|
1205
|
+
emit_consumer_tuple(stream, consumer, tuple_json)
|
1129
1206
|
end
|
1130
|
-
|
1131
|
-
|
1132
|
-
|
1207
|
+
when "kill_cycle"
|
1208
|
+
cycle_killed = true
|
1209
|
+
return
|
1133
1210
|
end
|
1134
1211
|
end
|
1135
1212
|
end
|
@@ -1148,7 +1225,8 @@ module Zillabyte; module Runner; class MultilangOperation
|
|
1148
1225
|
type_map = {
|
1149
1226
|
"string" => String,
|
1150
1227
|
"double" => Float,
|
1151
|
-
"integer" => Integer
|
1228
|
+
"integer" => Integer,
|
1229
|
+
"float" => Float
|
1152
1230
|
}
|
1153
1231
|
|
1154
1232
|
col_map = {}
|
@@ -1158,13 +1236,12 @@ module Zillabyte; module Runner; class MultilangOperation
|
|
1158
1236
|
col_map[key] = type_map[type]
|
1159
1237
|
end
|
1160
1238
|
|
1161
|
-
|
1239
|
+
tuples = []
|
1162
1240
|
|
1163
1241
|
output = @__options["output"]
|
1164
1242
|
loop do
|
1165
1243
|
# Read messages
|
1166
|
-
|
1167
|
-
obj = msg
|
1244
|
+
obj = read_message(@__consumee_pipes["rd_child_1"])
|
1168
1245
|
|
1169
1246
|
# Add row
|
1170
1247
|
if obj['tuple']
|
@@ -1172,7 +1249,7 @@ module Zillabyte; module Runner; class MultilangOperation
|
|
1172
1249
|
tuple = obj['tuple']
|
1173
1250
|
display_json = Hash[obj['tuple'].map{|k, v| [Zillabyte::Runner::Operation.truncate_message(k), Zillabyte::Runner::Operation.truncate_message(v)]}].to_json
|
1174
1251
|
|
1175
|
-
if col_map.keys.length
|
1252
|
+
if col_map.keys.length > tuple.keys.length
|
1176
1253
|
cdisplay "Error: invalid keys for sink tuple : Expected #{col_map.keys} , got: #{tuple.keys}"
|
1177
1254
|
cdisplay("\n \nPress Ctrl-C to exit", false)
|
1178
1255
|
return
|
@@ -1199,24 +1276,27 @@ module Zillabyte; module Runner; class MultilangOperation
|
|
1199
1276
|
|
1200
1277
|
if columns_to_check != 0
|
1201
1278
|
cdisplay "Error: invalid schema for sink tuple #{display_json}"
|
1202
|
-
cdisplay("\n \nPress Ctrl-C to exit", false)
|
1203
1279
|
return
|
1204
1280
|
end
|
1205
|
-
|
1281
|
+
tuples << obj
|
1206
1282
|
if @__options[:interactive]
|
1207
1283
|
cdisplay "received #{display_json}"
|
1208
1284
|
end
|
1209
1285
|
write_message(@__consumee_pipes["wr_child_1"], NEXT_MESSAGE)
|
1210
1286
|
|
1211
1287
|
# End cycle
|
1212
|
-
elsif obj['command']
|
1213
|
-
|
1288
|
+
elsif obj['command']
|
1289
|
+
case obj['command']
|
1290
|
+
when "end_cycle"
|
1291
|
+
break
|
1292
|
+
when "kill_cycle"
|
1293
|
+
break
|
1294
|
+
end
|
1214
1295
|
end
|
1215
1296
|
end
|
1216
1297
|
|
1217
|
-
if
|
1218
|
-
cdisplay "
|
1219
|
-
cdisplay "use Ctrl-C to exit"
|
1298
|
+
if tuples.empty?
|
1299
|
+
cdisplay "No tuples received"
|
1220
1300
|
return
|
1221
1301
|
end
|
1222
1302
|
|
@@ -1226,7 +1306,7 @@ module Zillabyte; module Runner; class MultilangOperation
|
|
1226
1306
|
require("csv")
|
1227
1307
|
csv_str = CSV.generate do |csv|
|
1228
1308
|
header_written = false;
|
1229
|
-
|
1309
|
+
tuples.each do |obj|
|
1230
1310
|
begin
|
1231
1311
|
|
1232
1312
|
t = obj['tuple']
|
@@ -1257,7 +1337,7 @@ module Zillabyte; module Runner; class MultilangOperation
|
|
1257
1337
|
|
1258
1338
|
# Output table
|
1259
1339
|
cdisplay("\n#{table.to_s}")
|
1260
|
-
cdisplay "#{
|
1340
|
+
cdisplay "#{tuples.length} rows"
|
1261
1341
|
|
1262
1342
|
# Write file
|
1263
1343
|
if output
|
@@ -1267,7 +1347,6 @@ module Zillabyte; module Runner; class MultilangOperation
|
|
1267
1347
|
f.close()
|
1268
1348
|
cdisplay("output written to #{filename}")
|
1269
1349
|
end
|
1270
|
-
cdisplay("\n \nPress Ctrl-C to exit", false)
|
1271
1350
|
end
|
1272
1351
|
|
1273
1352
|
|
@@ -1299,7 +1378,6 @@ module Zillabyte; module Runner; class MultilangOperation
|
|
1299
1378
|
# Read a JSON message
|
1300
1379
|
def self.read_message(read_stream)
|
1301
1380
|
|
1302
|
-
|
1303
1381
|
@__read_buffers[read_stream] ||= ""
|
1304
1382
|
@__read_buffered_messages[read_stream] ||= []
|
1305
1383
|
if !@__read_buffered_messages[read_stream].empty?
|
@@ -1373,17 +1451,23 @@ module Zillabyte; module Runner; class MultilangOperation
|
|
1373
1451
|
|
1374
1452
|
# Instruct multilang to begin cycle
|
1375
1453
|
def self.begin_cycle(write_stream, read_stream)
|
1376
|
-
|
1377
|
-
|
1454
|
+
write_message(write_stream, BEGIN_CYCLE_MESSAGE)
|
1455
|
+
|
1456
|
+
while 1 do
|
1457
|
+
|
1378
1458
|
msg = read_message(read_stream)
|
1379
1459
|
obj = Hash[msg]
|
1380
|
-
|
1381
|
-
|
1382
|
-
|
1383
|
-
|
1384
|
-
|
1385
|
-
|
1386
|
-
|
1460
|
+
case obj["command"]
|
1461
|
+
when "log"
|
1462
|
+
cdisplay "LOG: #{obj['msg']}"
|
1463
|
+
when "done"
|
1464
|
+
break
|
1465
|
+
else
|
1466
|
+
cdisplay("Error beginning cycle")
|
1467
|
+
raise obj["msg"]
|
1468
|
+
end
|
1469
|
+
end
|
1470
|
+
|
1387
1471
|
end
|
1388
1472
|
|
1389
1473
|
# Build the hash of consumer streams for lookup when receiving responses
|
@@ -1407,12 +1491,27 @@ module Zillabyte; module Runner; class MultilangOperation
|
|
1407
1491
|
return consumer_hash
|
1408
1492
|
end
|
1409
1493
|
|
1494
|
+
# Send object to every consumer of the operation, regardless of stream
|
1495
|
+
def self.send_to_consumees(json_obj)
|
1496
|
+
pipes = @__consumee_pipes
|
1497
|
+
# Left hand(or singular) input
|
1498
|
+
if (pipes.has_key? "wr_parent_1")
|
1499
|
+
write_stream = get_write_stream(stream, consumer, 1)
|
1500
|
+
write_message(write_stream, json_obj)
|
1501
|
+
end
|
1502
|
+
|
1503
|
+
# Right hand input
|
1504
|
+
if (pipes.has_key? "wr_parent_2")
|
1505
|
+
write_stream = get_write_stream(stream, consumer, 2)
|
1506
|
+
write_message(write_stream, json_obj)
|
1507
|
+
end
|
1508
|
+
end
|
1410
1509
|
|
1411
1510
|
# Send object to every consumer of the operation, regardless of stream
|
1412
|
-
def self.send_to_consumers(json_obj)
|
1511
|
+
def self.send_to_consumers(json_obj, display = false)
|
1413
1512
|
@__consumer_pipes.each_pair do |stream, consumers|
|
1414
1513
|
consumers.each_pair do |consumer, pipe|
|
1415
|
-
|
1514
|
+
@__consumee_pipes["wr_child_1"]
|
1416
1515
|
# Single or Left hand pipe
|
1417
1516
|
if (pipe.has_key? "wr_parent_1")
|
1418
1517
|
write_stream = get_write_stream(stream, consumer, 1)
|
@@ -1421,8 +1520,9 @@ module Zillabyte; module Runner; class MultilangOperation
|
|
1421
1520
|
write_stream = get_write_stream(stream, consumer, 2)
|
1422
1521
|
write_message(write_stream, json_obj)
|
1423
1522
|
end
|
1424
|
-
|
1425
|
-
|
1523
|
+
if display
|
1524
|
+
cdisplay "emitted #{json_obj.chomp} to #{consumer}"
|
1525
|
+
end
|
1426
1526
|
end
|
1427
1527
|
end
|
1428
1528
|
end
|
@@ -1441,6 +1541,7 @@ module Zillabyte; module Runner; class MultilangOperation
|
|
1441
1541
|
end
|
1442
1542
|
|
1443
1543
|
|
1544
|
+
|
1444
1545
|
# Send a command message to a consumer
|
1445
1546
|
def self.send_command_tuple(stream, consumer, json_obj)
|
1446
1547
|
pipe = @__consumer_pipes[stream][consumer]
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zillabyte-cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.38
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- zillabyte
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-09-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|