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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- OGUxZDA3NGNiZWIyOWUzNmE3ZmMxYTUzYmUwMzNjYzExZmQ5MjM2Ng==
4
+ ODc2YjU3ZTY2MWI5YWUxZjQwNjc3YjljN2FjNGYwN2U1ZjQwNjkwZA==
5
5
  data.tar.gz: !binary |-
6
- MWVjMThkNzRjZGRhZmM4NGY0YjIyYzg1ODcxZmJiYjVhMWIwZWYyZg==
6
+ NzhlMDhkODI1MzY4OTVjNzRhNzVlZWVjYWQ2NTM2OWYwNGNlNTQ3Nw==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- NDU0YjQzYTFmYmM4ZmViOGEzNzkwYzY2ZWQzNjJhOTY5ZmU0YTBkNjg0Y2Vl
10
- YWI3Y2U4OTE5MWIwMmI2OWQ4ODRjMDZlYjAzMjcxMjMwNzEzMDU1NmVhZGFk
11
- MjJkM2QwOGM1YmE5OTA4MGUxM2UxZDRkMGIwYjNkY2Y4MzkwN2Y=
9
+ YzM4NWFkNzZmOTYwYjJmMGZmYTdiMTRkYmQ3NjlkYWVhMjFjMmZiYTU0MzUx
10
+ ZGM1ZjRkZGFhMWIxMWMxZThiOWNhNzUwMmFkMWY5NDhjZTYyMjBkMzgyMzBj
11
+ NmY4NmMzOWE0NDE5ZTMzZmEwYzViNzhkNjYzYmUyN2YzNzcxYzE=
12
12
  data.tar.gz: !binary |-
13
- MWE4ZTg4NGI4Yjk3MDNhZTk3NDNkOWNiMjRmNmMzN2Q3NTQzZDUxM2JiYTA2
14
- ZWI4ZGI5ZmJlMGVmMWIxYTdiMTI4Mzk2NzViNDFiYjY2ZmE4OTdjZGY1Y2Zi
15
- N2Q5ZDFiODdlOTY2Y2RjODQyN2FmMThlOTdiOTA4MTVhMDM3ZTI=
13
+ ODQ2ZDQ1N2M1ZTU4YjY3NjQyYzhlNmRiYjNkMTliMjMzOWFhYzhmYzA1ZWMx
14
+ MGFiOGE5ZGU1ODE3ZGQ5ODQwNGM1OWVkMDBkNzQzNTEwZWFmMjM2YTIzNTky
15
+ NjQwYjMzMTIyNjlkNjRjNDFkZWU4NDQ5YTBlZTVkOWNiNzdhYjU=
@@ -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
- begin
226
- JSON.parse(msg)
227
- rescue JSON::ParserError
228
- display "Received invalid JSON object"
229
- next
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"] && msg["command"] == "next"
108
-
109
- @__emit_queues[stream][consumer][:ready] = true
110
- tuple_json = get_consumer_tuple(stream, consumer)
111
-
112
- # If all messages have been sent to consumer, end their cycle
113
- if tuple_json.nil?
114
- write_stream = get_write_stream(stream, consumer)
115
- cdisplay "ending cycle for #{consumer}"
116
- send_command_tuple(stream, consumer, END_CYCLE_MESSAGE)
117
- send_command_tuple(stream, consumer, DONE_MESSAGE)
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
- else
120
- # Emit tuple to consumer
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 == "end\n"
140
- @__consumer_pipes.each_pair do |stream, consumers|
141
- consumers.each_pair do |consumer, pipe|
142
- send_command_tuple(stream, consumer, END_CYCLE_MESSAGE)
143
- send_command_tuple(stream, consumer, DONE_MESSAGE)
144
- end
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
- # Receive and handle messages
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
- res = caller.rpc(component_id, call_options)
235
- cdisplay "received API response : #{res}"
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
- #TODO handle errors
238
- if res['error']
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
- # Send result call
250
- loop do
238
+ res = caller.rpc(component_id, call_options)
239
+ cdisplay "received API response : #{res}"
251
240
 
252
- # If a call for results is not ready, save the execution ID for the next cycle
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
- # check results
262
- res['results'].each do |run_id, hash|
263
-
264
- # We have results
265
- if hash['status'] == "complete"
266
-
267
- # Handle Tuple in here
268
- data_streams = hash['data']
269
-
270
- # if stream_hash.nil?
271
- # cdisplay("error : no results!")
272
- # next
273
- # else
274
- # stream_hash.each_pair
275
- # end
276
-
277
- # Handle each resulting tuple
278
- data_streams.each_pair do |stream, data_tuples|
279
- data_tuples.each do |data_tuple|
280
- tuple_json = build_tuple_json(data_tuple)
281
-
282
- #send or enqueue the tuple to all consumers of the stream
283
- @__emit_queues.each_pair do |stream, consumers|
284
- consumers.each_pair do |consumer, emitter|
285
- if emitter[:ready]
286
- emit_consumer_tuple(stream, consumer, tuple_json)
287
- else
288
- @__emit_queues[stream][consumer][:write_queue] << tuple_json
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
- else
297
- cdisplay "RPC #{run_id} has not completed... "
298
- ids_in_progress << run_id
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
- # If no more IDs to run, we are done
304
- if run_ids.empty?
305
- break
312
+ # Dont spam the API
313
+ sleep(2)
306
314
  end
307
315
 
308
- # Dont spam the API
309
- sleep(2)
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
- # End cycle
317
- elsif obj['command']
318
- case obj["command"]
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
- # Consumer is ready for a message
321
- when "next"
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
- @__emit_queues[stream][consumer][:ready] = true
326
- tuple_json = get_consumer_tuple(stream, consumer)
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
- # End cycle for consumer if it has processed all tuples
329
- if tuple_json.nil? && end_cycle_received
330
- send_command_tuple(stream, consumer, END_CYCLE_MESSAGE)
331
- consumers_running -= 1
332
- if consumers_running == 0
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
- # TODO break if last consumer
337
- elsif !tuple_json.nil?
338
- # Emit tuple to consumer
339
- emit_consumer_tuple(stream, consumer, tuple_json)
340
- emitted = true
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
- # Exit after ending consumer cycles
351
- if consumers_running == 0
352
- break
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
- if msg != "end"
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
- tuple = JSON.parse(msg)
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(tuple)
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"] && msg["command"] == "next"
145
-
146
- @__emit_queues[stream][consumer][:ready] = true
147
- tuple_json = get_consumer_tuple(stream, consumer)
148
-
149
- # If all messages have been sent to consumer, end their cycle
150
- if tuple_json.nil?
151
- write_stream = get_write_stream(stream, consumer)
152
- cdisplay "ending cycle for #{consumer}"
153
- send_command_tuple(stream, consumer, END_CYCLE_MESSAGE)
154
- send_command_tuple(stream, consumer, DONE_MESSAGE)
155
- else
156
- # Emit tuple to consumer
157
- emit_consumer_tuple(stream, consumer, tuple_json)
158
- emitted = true
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 Errno::EIO
362
- cdisplay("Errno:EIO error")
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
- ml_output.close
368
- File.delete("#{ml_pipe}.in")
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
- cdisplay("The child process exited!")
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
- break
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
- break
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
- ml_output.close
572
- File.delete("#{ml_pipe}.in")
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"] && msg["command"] == "next"
1189
+ if msg["command"]
1190
+ case msg["command"]
1191
+ when"next"
1119
1192
 
1120
- @__emit_queues[stream][consumer][:ready] = true
1121
- tuple_json = get_consumer_tuple(stream, consumer)
1193
+ @__emit_queues[stream][consumer][:ready] = true
1194
+ tuple_json = get_consumer_tuple(stream, consumer)
1122
1195
 
1123
- # If all messages have been sent to a consumer, end its cycle
1124
- if tuple_json.nil?
1125
- send_command_tuple(stream, consumer, END_CYCLE_MESSAGE)
1126
- consumers_running -= 1
1127
- if consumers_running == 0
1128
- return
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
- else
1131
- # Emit tuple to consumer
1132
- emit_consumer_tuple(stream, consumer, tuple_json)
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
- messages = []
1239
+ tuples = []
1162
1240
 
1163
1241
  output = @__options["output"]
1164
1242
  loop do
1165
1243
  # Read messages
1166
- msg = read_message(@__consumee_pipes["rd_child_1"])
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 != tuple.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
- messages << msg
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'] && obj['command'] == "end_cycle"
1213
- break
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 messages.empty?
1218
- cdisplay "no tuples"
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
- messages.each do |obj|
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 "#{messages.length} rows"
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
- begin
1377
- write_message(write_stream, BEGIN_CYCLE_MESSAGE)
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
- if obj["command"] != "done"
1381
- raise "Invalid response from multilang #{msg}"
1382
- end
1383
- rescue => e
1384
- cdisplay("Error beginning cycle")
1385
- raise e
1386
- end
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
- cdisplay "emitted #{json_obj} to #{consumer}"
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]
@@ -1,5 +1,5 @@
1
1
  module Zillabyte
2
2
  module CLI
3
- VERSION = "0.1.37"
3
+ VERSION = "0.1.38"
4
4
  end
5
5
  end
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.37
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-08-29 00:00:00.000000000 Z
11
+ date: 2014-09-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake