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 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