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