td 0.11.6 → 0.11.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fbc07ea58b09419ef7a3ba5dd850af222c8af299
4
- data.tar.gz: db4fd8cfdece04ac1c94b3b68d8a642488c07be5
3
+ metadata.gz: e4b7f5341cbcebd3487c7df38951a4275204507e
4
+ data.tar.gz: 9aad2c3285c7beb623a97410b62844ff41f74574
5
5
  SHA512:
6
- metadata.gz: cebcfe70d4474b64ae1b440981f9aee6c200f3b6b3e4b09c2dc1137faa7a2495e6f9e86ef8527181613c9d41af569d77ebf9091327d3e088e3e79bcfb95e7107
7
- data.tar.gz: a261af1042634927563564043865d7e41e232c1bf048af3759025c5a46039fd64391b3d54900beb427371b93c3e6f19349194aa4246a14cc93ba3b17df1da2e0
6
+ metadata.gz: 24846c57a7df595675ca6999412b0c542ac7beb1850adda09de6f9832152954d33ff2be5335b293213f92e492e558ab711f132598587433b0249a4f803eedebc
7
+ data.tar.gz: 65eed33f8222fe6c3fb57067087d1cc477fb3a9bc64d9d427b0375964281c32726b11f8b65a0258ab77ce914a7530a0aadfaa92adb0d40ae243b5a63369294d9
data/ChangeLog CHANGED
@@ -1,3 +1,23 @@
1
+ == 2015-02-16 version 0.11.7
2
+
3
+ * Fix server:endpoint command not working
4
+ * Experimental new feature: timeout for import subcommands. To prevent Java
5
+ process stall this option allows user to specify maximum execution seconds
6
+ for import subcommands by --bulk-import-timeout option. When execution
7
+ exceeds specified seconds the command fails after sending SIGQUIT to
8
+ internal java process if it's not running on Windows.
9
+ NOTE1: the execution time is measured against all subcommand execution. If
10
+ the command parameter designates perform and commit execution the whole
11
+ time could be longer than just uploading part files.
12
+ NOTE2: this option is not shown in help at this moment.
13
+ * Show full query text for CSV, TSV, and JSON output format (It's now only
14
+ truncated in table format)
15
+ * msgpack.gz to CSV/TSV perf optimization. It should be faster around 2 times
16
+ than before.
17
+ * Allow to disable table data expiration by setting the period to 0.
18
+ * Fix sched:history crash when scheduled_at == ""
19
+ * Several spec fixes. Thanks @yakitorii!
20
+
1
21
  == 2014-12-03 version 0.11.6
2
22
 
3
23
  * Support HTTP proxy for bulk import
@@ -101,6 +101,7 @@ module Command
101
101
  show_help = ARGV.size == 0 || (ARGV.size == 1 || ARGV[0] =~ /^import:/)
102
102
 
103
103
  # configure java command-line arguments
104
+ timeout = nil
104
105
  java_args = []
105
106
  java_args.concat build_sysprops
106
107
  java_args.concat ["-cp", find_td_import_jar]
@@ -109,18 +110,70 @@ module Command
109
110
  if show_help
110
111
  java_args << "--help"
111
112
  else
113
+ 0.upto(ARGV.length - 1) do |idx|
114
+ if ARGV[idx] == '--bulk-import-timeout'
115
+ timeout = ARGV[idx + 1]
116
+ if timeout.nil?
117
+ raise ArgumentError, 'timeout not given'
118
+ end
119
+ timeout = Integer(timeout)
120
+ ARGV.slice!(idx, 2)
121
+ end
122
+ end
112
123
  java_args.concat ARGV
113
124
  end
114
-
115
125
  cmd = [JAVA_COMMAND] + JVM_OPTS + java_args
116
- system(*cmd)
117
- if $?.exitstatus != 0
118
- raise BulkImportExecutionError,
119
- "Bulk Import returned error #{$?.exitstatus}. Please check the 'td-bulk-import.log' logfile for details."
120
- end
126
+
127
+ CommandExecutor.new(cmd, timeout).execute
121
128
  end
122
129
 
130
+ class CommandExecutor
131
+ def initialize(cmd, timeout)
132
+ @cmd, @timeout = cmd, timeout
133
+ end
134
+
135
+ def execute
136
+ status = execute_command
137
+ if status.exitstatus != 0
138
+ raise BulkImportExecutionError,
139
+ "Bulk Import returned error #{status.exitstatus}. Please check the 'td-bulk-import.log' logfile for details."
140
+ end
141
+ status
142
+ end
143
+
123
144
  private
145
+
146
+ def execute_command
147
+ if @timeout
148
+ require 'timeout'
149
+ pid = nil
150
+ begin
151
+ Timeout.timeout(@timeout) do
152
+ pid = Process.spawn(*@cmd)
153
+ Process.waitpid(pid)
154
+ return $?
155
+ end
156
+ rescue Timeout::Error
157
+ if pid
158
+ require 'rbconfig'
159
+ # win32 ruby does not support QUIT and TERM
160
+ if RbConfig::CONFIG['host_os'] !~ /mswin|mingw|cygwin/
161
+ Process.kill('QUIT', pid)
162
+ Process.kill('TERM', pid)
163
+ else
164
+ # just kill without thread dump on win32 platforms
165
+ Process.kill('KILL', pid)
166
+ end
167
+ end
168
+ raise BulkImportExecutionError, "Bulk Import execution timed out: #{@timeout} [sec]"
169
+ end
170
+ else
171
+ system(*@cmd)
172
+ return $?
173
+ end
174
+ end
175
+ end
176
+
124
177
  def check_java
125
178
  if RbConfig::CONFIG["target_os"].downcase =~ /mswin(?!ce)|mingw|cygwin|bccwin/ # windows
126
179
  cmd = "#{JAVA_COMMAND} -version > NUL 2>&1"
@@ -75,12 +75,13 @@ module Command
75
75
  elapsed = Command.humanize_elapsed_time(start, job.end_at)
76
76
  cpu_time = Command.humanize_time(job.cpu_time, true)
77
77
  priority = job_priority_name_of(job.priority)
78
+ query = (op.render_format == 'table' || op.render_format.nil? ? job.query.to_s[0,50] + " ..." : job.query)
78
79
  rows << {
79
80
  :JobID => job.job_id,
80
81
  :Database => job.db_name,
81
82
  :Status => job.status,
82
83
  :Type => job.type,
83
- :Query => job.query.to_s[0,50] + " ...",
84
+ :Query => query,
84
85
  :Start => (start ? start.localtime : ''),
85
86
  :Elapsed => elapsed.rjust(11),
86
87
  :CPUTime => cpu_time.rjust(17),
@@ -384,13 +385,15 @@ module Command
384
385
  job.result_size, 0.1, 1)
385
386
  end
386
387
  job.result_each_with_compr_size {|row, compr_size|
387
- indicator.update(compr_size) unless output.nil?
388
388
  # TODO limit the # of columns
389
389
  writer << row.map {|col|
390
390
  dump_column(col)
391
391
  }
392
392
  n_rows += 1
393
- writer.flush if n_rows % 100 == 0 # flush every 100 recods
393
+ if n_rows % 100 == 0 # flush every 100 recods
394
+ writer.flush
395
+ indicator.update(compr_size) unless output.nil?
396
+ end
394
397
  break if output.nil? and !limit.nil? and n_rows == limit
395
398
  }
396
399
  indicator.finish unless output.nil?
@@ -415,17 +418,12 @@ module Command
415
418
  job.result_size, 0.1, 1)
416
419
  end
417
420
  job.result_each_with_compr_size {|row, compr_size|
418
- indicator.update(compr_size) unless output.nil?
419
- n_cols = 0
420
- row.each {|col|
421
- f.write "\t" if n_cols > 0
422
- # TODO limit the # of columns
423
- f.write dump_column(col)
424
- n_cols += 1
425
- }
426
- f.write "\n"
421
+ f.write row.map {|col| dump_column(col)}.join("\t") + "\n"
427
422
  n_rows += 1
428
- f.flush if n_rows % 100 == 0 # flush every 100 recods
423
+ if n_rows % 100 == 0
424
+ f.flush # flush every 100 recods
425
+ indicator.update(compr_size) unless output.nil?
426
+ end
429
427
  break if output.nil? and !limit.nil? and n_rows == limit
430
428
  }
431
429
  indicator.finish unless output.nil?
@@ -495,7 +493,7 @@ module Command
495
493
  job.result_each_with_compr_size {|row, compr_size|
496
494
  indicator.update(compr_size)
497
495
  rows << row.map {|v|
498
- dump_column(v)
496
+ dump_column_safe_utf8(v)
499
497
  }
500
498
  n_rows += 1
501
499
  break if !limit.nil? and n_rows == limit
@@ -517,9 +515,11 @@ module Command
517
515
  end
518
516
 
519
517
  def dump_column(v)
520
- require 'yajl'
518
+ v.is_a?(String) ? v.to_s : Yajl.dump(v)
519
+ end
521
520
 
522
- s = v.is_a?(String) ? v.to_s : Yajl.dump(v)
521
+ def dump_column_safe_utf8(v)
522
+ s = dump_column(v)
523
523
  # Here does UTF-8 -> UTF-16LE -> UTF8 conversion:
524
524
  # a) to make sure the string doesn't include invalid byte sequence
525
525
  # b) to display multi-byte characters as it is
@@ -230,7 +230,7 @@ module List
230
230
  add_list 'table:swap', %w[db table1 table2], 'Swap names of two tables', ['table:swap example_db table1 table2']
231
231
  add_list 'table:tail', %w[db table], 'Get recently imported logs', ['table:tail example_db table1', 'table:tail example_db table1 -t "2011-01-02 03:04:05" -n 30']
232
232
  add_list 'table:partial_delete', %w[db table], 'Delete logs from the table within the specified time range', ['table:partial_delete example_db table1 --from 1341000000 --to 1341003600']
233
- add_list 'table:expire', %w[db table expire_days], 'Expire data in table after specified number of days', ['table:expire example_db table1 30']
233
+ add_list 'table:expire', %w[db table expire_days], 'Expire data in table after specified number of days. Set to 0 to disable the expiration.', ['table:expire example_db table1 30']
234
234
 
235
235
  add_list 'bulk_import:list', %w[], 'List bulk import sessions', ['bulk_import:list']
236
236
  add_list 'bulk_import:show', %w[name], 'Show list of uploaded parts', ['bulk_import:show']
@@ -273,7 +273,8 @@ module Command
273
273
 
274
274
  rows = []
275
275
  history.each {|j|
276
- rows << {:Time => j.scheduled_at.localtime, :JobID => j.job_id, :Status => j.status, :Priority => job_priority_name_of(j.priority), :Result=>j.result_url}
276
+ scheduled_at = j.scheduled_at ? j.scheduled_at.localtime : nil
277
+ rows << {:Time => scheduled_at, :JobID => j.job_id, :Status => j.status, :Priority => job_priority_name_of(j.priority), :Result=>j.result_url}
277
278
  }
278
279
 
279
280
  puts cmd_render_table(rows, :fields => [:JobID, :Time, :Status, :Priority, :Result], :render_format => op.render_format)
@@ -20,7 +20,7 @@ module Command
20
20
  end
21
21
 
22
22
  Command.validate_api_endpoint(endpoint)
23
- Coomand.test_api_endpoint(endpoint)
23
+ Command.test_api_endpoint(endpoint)
24
24
 
25
25
  conf = nil
26
26
  begin
@@ -412,15 +412,19 @@ module Command
412
412
  db_name, table_name, expire_days = op.cmd_parse
413
413
 
414
414
  expire_days = expire_days.to_i
415
- if expire_days <= 0
416
- $stderr.puts "Table expiration days must be greater than 0."
415
+ if expire_days < 0
416
+ $stderr.puts "Table expiration days must be greater or equal to 0."
417
417
  return
418
418
  end
419
419
 
420
420
  client = get_client
421
421
  client.update_expire(db_name, table_name, expire_days)
422
422
 
423
- $stderr.puts "Table set to expire data older than #{expire_days} days."
423
+ if expire_days == 0
424
+ puts "Data expiration disabled for this table."
425
+ else
426
+ puts "Table set to expire data older than #{expire_days} days."
427
+ end
424
428
  end
425
429
 
426
430
 
@@ -43,7 +43,9 @@ module TreasureData
43
43
  end
44
44
 
45
45
  def forward
46
- @u.each {|r| break r }
46
+ content = @u.each {|r| break r }
47
+ raise EOFError unless content
48
+ content
47
49
  end
48
50
  end
49
51
 
data/lib/td/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module TreasureData
2
- TOOLBELT_VERSION = '0.11.6'
2
+ TOOLBELT_VERSION = '0.11.7'
3
3
  end
@@ -33,12 +33,21 @@ describe FileReader::LineReader do
33
33
 
34
34
  it 'initialize with specifid encoding' do
35
35
  if io.respond_to?(:external_encoding)
36
- ee = io.external_encoding
36
+ original_encoding = io.external_encoding
37
+ end
38
+
39
+ # when RUBY_VERSION >= 2.0, default encoding is utf-8.
40
+ # ensure that external_encoding is differ from the original external_encoding(original_encoding).
41
+ if original_encoding == Encoding.find('utf-8')
42
+ specified_encoding = 'sjis'
43
+ else
44
+ specified_encoding = 'utf-8'
37
45
  end
38
- FileReader::LineReader.new(io, error, {:encoding => 'utf-8'})
46
+
47
+ FileReader::LineReader.new(io, error, {:encoding => specified_encoding})
39
48
  if io.respond_to?(:external_encoding)
40
- io.external_encoding.should_not == ee
41
- io.external_encoding.should == Encoding.find('utf-8')
49
+ io.external_encoding.should_not == original_encoding
50
+ io.external_encoding.should == Encoding.find(specified_encoding)
42
51
  end
43
52
  end
44
53
 
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+ require 'td/command/common'
3
+ require 'td/command/import'
4
+
5
+ module TreasureData::Command
6
+ describe 'import commands' do
7
+ describe CommandExecutor do
8
+ it 'executes command' do
9
+ CommandExecutor.new(['echo'], nil).execute.exitstatus.should == 0
10
+ end
11
+
12
+ it 'executes command' do
13
+ expect {
14
+ CommandExecutor.new(['exit', '1'], nil).execute
15
+ }.to raise_error BulkImportExecutionError, /td-bulk-import\.log/
16
+ end
17
+
18
+ it 'terminates process on timeout' do
19
+ CommandExecutor.new(['sleep', '1'], 2).execute
20
+ expect {
21
+ CommandExecutor.new(['sleep', '2'], 1).execute
22
+ }.to raise_error BulkImportExecutionError, /timed out/
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+ require 'td/command/common'
3
+ require 'td/command/job'
4
+ require 'td/command/list'
5
+ require 'tempfile'
6
+
7
+ module TreasureData::Command
8
+ describe 'job commands' do
9
+ let :command do
10
+ Class.new { include TreasureData::Command }.new
11
+ end
12
+
13
+ let :job do
14
+ job = TreasureData::Job.new(nil, 12345, 'hive', 'select * from employee')
15
+ job.instance_eval do
16
+ @result = [[["1", 2.0, {key:3}], 1], [["4", 5.0, {key:6}], 2], [["7", 8.0, {key:9}], 3]]
17
+ @result_size = 3
18
+ @status = 'success'
19
+ end
20
+ job
21
+ end
22
+
23
+ describe 'write_result' do
24
+ it 'supports json output' do
25
+ file = Tempfile.new("job_spec")
26
+ command.send(:show_result, job, file, nil, 'json')
27
+ File.read(file.path).should == %Q([["1",2.0,{"key":3}],\n["4",5.0,{"key":6}],\n["7",8.0,{"key":9}]])
28
+ end
29
+
30
+ it 'supports csv output' do
31
+ file = Tempfile.new("job_spec")
32
+ command.send(:show_result, job, file, nil, 'csv')
33
+ File.read(file.path).should == %Q(1,2.0,"{""key"":3}"\n4,5.0,"{""key"":6}"\n7,8.0,"{""key"":9}"\n)
34
+ end
35
+
36
+ it 'supports tsv output' do
37
+ file = Tempfile.new("job_spec")
38
+ command.send(:show_result, job, file, nil, 'tsv')
39
+ File.read(file.path).should == %Q(1\t2.0\t{"key":3}\n4\t5.0\t{"key":6}\n7\t8.0\t{"key":9}\n)
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+ require 'td/command/common'
3
+ require 'td/config'
4
+ require 'td/command/list'
5
+ require 'td/command/sched'
6
+ require 'td/client/model'
7
+ require 'time'
8
+
9
+ module TreasureData::Command
10
+
11
+ describe 'sched_history' do
12
+ it 'runs' do
13
+ client = Object.new
14
+ time = Time.now.xmlschema
15
+ job_params = ['job_id', :type, 'query', 'status', nil, nil, time, time, 123, 456]
16
+ job1 = TreasureData::ScheduledJob.new(client, '2015-02-17 13:22:52 +0900', *job_params)
17
+ job2 = TreasureData::ScheduledJob.new(client, nil, *job_params)
18
+ client.stub(:schedules).and_return([])
19
+ client.stub(:history).and_return([job1, job2])
20
+ command = Class.new { include TreasureData::Command }.new
21
+ command.stub(:get_client).and_return(client)
22
+ op = List::CommandParser.new('sched:history', %w[], %w[], false, [], [])
23
+ expect {
24
+ command.sched_history(op)
25
+ }.to_not raise_exception
26
+ end
27
+ end
28
+ end
@@ -162,6 +162,10 @@ module TreasureData::Updater
162
162
  '/maven2/com/treasuredata/td-import/maven-metadata.xml',
163
163
  WEBrick::HTTPServlet::ProcHandler.new(method(:metadata).to_proc)
164
164
  )
165
+ @server.mount(
166
+ '/maven2/com/treasuredata/td-import/version/td-import-version-jar-with-dependencies.jar',
167
+ WEBrick::HTTPServlet::ProcHandler.new(method(:jar).to_proc)
168
+ )
165
169
  @server_thread = start_server_thread(@server)
166
170
  @server
167
171
  end
@@ -181,6 +185,11 @@ module TreasureData::Updater
181
185
  res.body = '<metadata><versioning><lastUpdated>20141204123456</lastUpdated><release>version</release></versioning></metadata>'
182
186
  end
183
187
 
188
+ def jar
189
+ res['content-type'] = 'application/octet-stream'
190
+ res.body = File.read(fixture_file('tmp.zip'))
191
+ end
192
+
184
193
  def start_server_thread(server)
185
194
  t = Thread.new {
186
195
  Thread.current.abort_on_exception = true
data/td.gemspec CHANGED
@@ -21,7 +21,7 @@ Gem::Specification.new do |gem|
21
21
  gem.add_dependency "yajl-ruby", "~> 1.1"
22
22
  gem.add_dependency "hirb", ">= 0.4.5"
23
23
  gem.add_dependency "parallel", "~> 0.6.1"
24
- gem.add_dependency "td-client", "~> 0.8.67"
24
+ gem.add_dependency "td-client", "~> 0.8.68"
25
25
  gem.add_dependency "td-logger", "~> 0.3.21"
26
26
  gem.add_dependency "rubyzip", "~> 0.9.9"
27
27
  gem.add_development_dependency "rake", "~> 0.9"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: td
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.6
4
+ version: 0.11.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Treasure Data, Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-05 00:00:00.000000000 Z
11
+ date: 2015-02-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: msgpack
@@ -102,14 +102,14 @@ dependencies:
102
102
  requirements:
103
103
  - - ~>
104
104
  - !ruby/object:Gem::Version
105
- version: 0.8.67
105
+ version: 0.8.68
106
106
  type: :runtime
107
107
  prerelease: false
108
108
  version_requirements: !ruby/object:Gem::Requirement
109
109
  requirements:
110
110
  - - ~>
111
111
  - !ruby/object:Gem::Version
112
- version: 0.8.67
112
+ version: 0.8.68
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: td-logger
115
115
  requirement: !ruby/object:Gem::Requirement
@@ -248,6 +248,9 @@ files:
248
248
  - spec/file_reader/shared_context.rb
249
249
  - spec/file_reader_spec.rb
250
250
  - spec/spec_helper.rb
251
+ - spec/td/command/import_spec.rb
252
+ - spec/td/command/job_spec.rb
253
+ - spec/td/command_sched_spec.rb
251
254
  - spec/td/common_spec.rb
252
255
  - spec/td/fixture/ca.cert
253
256
  - spec/td/fixture/server.cert
@@ -288,6 +291,9 @@ test_files:
288
291
  - spec/file_reader/shared_context.rb
289
292
  - spec/file_reader_spec.rb
290
293
  - spec/spec_helper.rb
294
+ - spec/td/command/import_spec.rb
295
+ - spec/td/command/job_spec.rb
296
+ - spec/td/command_sched_spec.rb
291
297
  - spec/td/common_spec.rb
292
298
  - spec/td/fixture/ca.cert
293
299
  - spec/td/fixture/server.cert