module TreasureData module Command def job_list(op) page = 0 skip = 0 op.on('-p', '--page PAGE', 'skip N pages', Integer) {|i| page = i } op.on('-s', '--skip N', 'skip N jobs', Integer) {|i| skip = i } max = op.cmd_parse max = (max || 20).to_i client = get_client if page skip += max * page end jobs = client.jobs(skip, skip+max-1) rows = [] jobs.each {|job| start = job.start_at finish = job.end_at if start if !finish finish = Time.now.utc end e = finish.to_i - start.to_i elapsed = '' if e >= 3600 elapsed << "#{e/3600}h " e %= 3600 elapsed << "% 2dm " % (e/60) e %= 60 elapsed << "% 2dsec" % e elsif e >= 60 elapsed << "% 2dm " % (e/60) e %= 60 elapsed << "% 2dsec" % e else elapsed << "% 2dsec" % e end else elapsed = '' end elapsed = "% 10s" % elapsed # right aligned rows << {:JobID => job.job_id, :Status => job.status, :Query => job.query.to_s, :Start => (start ? start.localtime : ''), :Elapsed => elapsed} } puts cmd_render_table(rows, :fields => [:JobID, :Status, :Start, :Elapsed, :Query]) end def job_show(op) verbose = nil wait = false output = nil format = 'tsv' op.on('-v', '--verbose', 'show logs', TrueClass) {|b| verbose = b } op.on('-w', '--wait', 'wait for finishing the job', TrueClass) {|b| wait = b } op.on('-o', '--output PATH', 'write result to the file') {|s| output = s } op.on('-f', '--format FORMAT', 'format of the result to write to the file (tsv, csv, json or msgpack)') {|s| unless ['tsv', 'csv', 'json', 'msgpack'].include?(s) raise "Unknown format #{s.dump}. Supported format: tsv, csv, json, msgpack" end format = s } job_id = op.cmd_parse client = get_client job = client.job(job_id) puts "JobID : #{job.job_id}" puts "URL : #{job.url}" puts "Status : #{job.status}" puts "Query : #{job.query}" if wait && !job.finished? wait_job(job) if job.success? puts "Result :" show_result(job, output, format) end else if job.success? puts "Result :" show_result(job, output, format) end if verbose puts "" puts "cmdout:" job.debug['cmdout'].to_s.split("\n").each {|line| puts " "+line } puts "" puts "stderr:" job.debug['stderr'].to_s.split("\n").each {|line| puts " "+line } end end $stderr.puts "Use '-v' option to show detailed messages." unless verbose end def job_kill(op) job_id = op.cmd_parse client = get_client former_status = client.kill(job_id) if TreasureData::Job::FINISHED_STATUS.include?(former_status) $stderr.puts "Job #{job_id} is already finished (#{former_status})" exit 0 end if former_status == TreasureData::Job::STATUS_RUNNING $stderr.puts "Job #{job_id} is killed." else $stderr.puts "Job #{job_id} is canceled." end end private def wait_job(job) $stderr.puts "running..." cmdout_lines = 0 stderr_lines = 0 until job.finished? sleep 2 job.update_status! cmdout = job.debug['cmdout'].to_s.split("\n")[cmdout_lines..-1] || [] stderr = job.debug['stderr'].to_s.split("\n")[stderr_lines..-1] || [] (cmdout + stderr).each {|line| puts " "+line } cmdout_lines += cmdout.size stderr_lines += stderr.size end end def show_result(job, output, format) if output write_result(job, output, format) puts "written to #{output} in #{format} format" else render_result(job) end end def write_result(job, output, format) case format when 'json' require 'json' first = true File.open(output, "w") {|f| f.write "[" job.result_each {|row| if first first = false else f.write "," end f.write row.to_json } f.write "]" } when 'msgpack' File.open(output, "w") {|f| f.write job.result_format('msgpack') } when 'csv' require 'json' require 'csv' CSV.open(output, "w") {|writer| job.result_each {|row| writer << row.map {|col| col.is_a?(String) ? col.to_s : col.to_json } } } when 'tsv' require 'json' File.open(output, "w") {|f| job.result_each {|row| first = true row.each {|col| if first first = false else f.write "\t" end f.write col.is_a?(String) ? col.to_s : col.to_json } f.write "\n" } } else raise "Unknown format #{format.inspect}" end end def render_result(job) require 'json' rows = [] job.result_each {|row| # TODO limit number of rows to show rows << row.map {|v| if v.is_a?(String) v.to_s else v.to_json end } } puts cmd_render_table(rows, :max_width=>10000) end end end