td 0.11.6 → 0.11.7

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