turbot-runner 0.0.20 → 0.0.21

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.
@@ -1,3 +1,3 @@
1
1
  module TurbotRunner
2
- VERSION = '0.0.20'
2
+ VERSION = '0.0.21'
3
3
  end
data/lib/turbot_runner.rb CHANGED
@@ -11,6 +11,7 @@ module TurbotRunner
11
11
  class BaseRunner
12
12
 
13
13
  attr_reader :wait_thread
14
+ attr_reader :error
14
15
 
15
16
  def initialize(bot_directory)
16
17
  @bot_directory = bot_directory
@@ -28,7 +29,6 @@ module TurbotRunner
28
29
  @status = :initialized
29
30
  @interrupted = false
30
31
  @schemas = {}
31
- # @seen_uids = Set.new
32
32
  end
33
33
 
34
34
  def run(opts={})
@@ -49,7 +49,18 @@ module TurbotRunner
49
49
  begin
50
50
  until @interrupted do
51
51
  line = scraper_runner.get_next_line
52
- break if line.nil?
52
+
53
+ if line.nil?
54
+ if scraper_runner.finished?
55
+ if scraper_runner.success?
56
+ break
57
+ else
58
+ scraper_runner.raise_if_failed!
59
+ end
60
+ else
61
+ next
62
+ end
63
+ end
53
64
 
54
65
  begin
55
66
  record = JSON.parse(line)
@@ -67,12 +78,29 @@ module TurbotRunner
67
78
  data_type1 = transformer['data_type']
68
79
 
69
80
  runner = transformer['runner']
81
+ runner.raise_if_failed!
82
+
70
83
  runner.send_line(line)
71
84
  line1 = runner.get_next_line
72
85
 
73
- # A transformer should output an empty line if it doesn't make
86
+ if line1.nil?
87
+ if runner.finished?
88
+ if runner.success?
89
+ break
90
+ else
91
+ runner.raise_if_failed!
92
+ end
93
+ else
94
+ next
95
+ end
96
+ end
97
+
98
+ # A transformer can output an empty line if it doesn't make
74
99
  # sense to transform a record.
75
- next if line1.strip.empty?
100
+ if line1.strip.empty?
101
+ puts
102
+ next
103
+ end
76
104
 
77
105
  begin
78
106
  record1 = JSON.parse(line1)
@@ -106,6 +134,7 @@ module TurbotRunner
106
134
  handle_interrupted_run
107
135
  else
108
136
  @status = :failed
137
+ @error = e
109
138
  handle_failed_run
110
139
  end
111
140
  end
@@ -227,24 +256,48 @@ module TurbotRunner
227
256
  end
228
257
 
229
258
  class CommandRunner
259
+
260
+ def to_s
261
+ "CommandRunner #{@command}, pid #{@wait_thread.pid} (#{@wait_thread.status})"
262
+ end
263
+
230
264
  def initialize(command, opts={})
231
265
  @command = command
232
266
  @timeout = opts[:timeout] ||= 3600
233
- @stdin, @stdout, @wait_thread = Open3.popen2(command)
267
+ @stdin, @stdout, @stderr, @wait_thread = Open3.popen3(command)
234
268
  end
235
269
 
236
270
  def get_next_line
237
271
  begin
238
272
  Timeout::timeout(@timeout) { @stdout.gets }
239
273
  rescue Timeout::Error
240
- STDOUT.puts("#{@command} produced no output for #{@timeout} seconds")
241
- raise ScriptError
274
+ raise TurbotRunner::ScriptError.new("#{@command} produced no output for #{@timeout} seconds")
242
275
  rescue EOFError
243
- raise ScriptError unless @wait_thread.value.success?
276
+ raise_if_failed!
244
277
  return nil
245
278
  end
246
279
  end
247
280
 
281
+ def success?
282
+ if finished?
283
+ @wait_thread.value.success?
284
+ end
285
+ end
286
+
287
+ def failed?
288
+ if finished?
289
+ !@wait_thread.value.success?
290
+ end
291
+ end
292
+
293
+ def raise_if_failed!
294
+ raise TurbotRunner::ScriptError.new(@stderr.read()) if failed?
295
+ end
296
+
297
+ def finished?
298
+ !@wait_thread.status
299
+ end
300
+
248
301
  def send_line(line)
249
302
  @stdin.puts(line)
250
303
  end
@@ -1,6 +1,6 @@
1
1
  require 'json'
2
-
3
2
  STDIN.each_line do |line|
3
+
4
4
  raw_record = JSON.parse(line)
5
5
 
6
6
  transformed_record = {
@@ -0,0 +1,8 @@
1
+ {
2
+ "bot_id": "dummy-bot",
3
+ "data_type": "hello",
4
+ "description": "This is a dummy bot",
5
+ "identifying_fields": ["number"],
6
+ "files": ["scraper.rb"],
7
+ "frequency": "monthly"
8
+ }
@@ -0,0 +1,4 @@
1
+ require 'json'
2
+
3
+ puts({h: 1}.to_json)
4
+ raise "oops"
@@ -0,0 +1,12 @@
1
+ require 'json'
2
+
3
+ STDIN.each_line do |line|
4
+ raw_record = JSON.parse(line)
5
+
6
+ transformed_record = {
7
+ :n => raw_record['n'],
8
+ :goodbye => raw_record['hello'].sub('hello', 'goodbye')
9
+ }
10
+
11
+ puts transformed_record.to_json
12
+ end
@@ -0,0 +1,15 @@
1
+ {
2
+ "bot_id": "dummy-bot",
3
+ "data_type": "hello",
4
+ "description": "This is a dummy bot",
5
+ "identifying_fields": ["number"],
6
+ "files": ["scraper.rb"],
7
+ "transformers": [
8
+ {
9
+ "file": "transformer.rb",
10
+ "data_type": "goodbye",
11
+ "identifying_fields": [""]
12
+ }
13
+ ],
14
+ "frequency": "monthly"
15
+ }
@@ -0,0 +1,4 @@
1
+ require 'json'
2
+
3
+ puts({h: 1}.to_json)
4
+ raise "oops"
@@ -0,0 +1,11 @@
1
+ require 'json'
2
+
3
+ STDIN.each_line do |line|
4
+ raw_record = JSON.parse(line)
5
+
6
+ transformed_record = {
7
+ :p => raw_record['n'],
8
+ }
9
+
10
+ puts transformed_record.to_json
11
+ end
@@ -0,0 +1,15 @@
1
+ {
2
+ "bot_id": "dummy-bot",
3
+ "data_type": "hello",
4
+ "description": "This is a dummy bot",
5
+ "identifying_fields": ["number"],
6
+ "files": ["scraper.rb"],
7
+ "transformers": [
8
+ {
9
+ "file": "transformer.rb",
10
+ "data_type": "goodbye",
11
+ "identifying_fields": [""]
12
+ }
13
+ ],
14
+ "frequency": "monthly"
15
+ }
@@ -0,0 +1,5 @@
1
+ require 'json'
2
+
3
+ 3.times do |n|
4
+ puts({h: n}.to_json)
5
+ end
@@ -0,0 +1,5 @@
1
+ require 'json'
2
+
3
+ STDIN.each_line do |line|
4
+ raise "oops"
5
+ end
@@ -11,6 +11,19 @@ class SpecRunner < TurbotRunner::BaseRunner
11
11
  end
12
12
  end
13
13
 
14
+ class BrokenRunner < TurbotRunner::BaseRunner
15
+ def validate(record, data_type)
16
+ []
17
+ end
18
+
19
+ def handle_valid_record(*args)
20
+ end
21
+
22
+ def handle_failed_run
23
+ end
24
+ end
25
+
26
+
14
27
  describe TurbotRunner::BaseRunner do
15
28
  it 'can run a ruby bot' do
16
29
  runner = SpecRunner.new('spec/dummy-bot-ruby')
@@ -39,4 +52,40 @@ describe TurbotRunner::BaseRunner do
39
52
  expect(runner).to receive(:handle_successful_run)
40
53
  runner.run
41
54
  end
55
+
56
+ describe "broken bots" do
57
+ describe "failing bot without transformer" do
58
+ it 'should call handle_failed_run' do
59
+ runner = BrokenRunner.new('spec/dummy-broken-bot-ruby')
60
+ expect(runner).to receive(:handle_valid_record)
61
+ expect(runner).to receive(:handle_failed_run)
62
+ runner.run
63
+ end
64
+
65
+ it 'should set `error` attribute of runner with exception message' do
66
+ runner = BrokenRunner.new('spec/dummy-broken-bot-ruby')
67
+ runner.run
68
+ expect(runner.error.to_s).to match(/oops/)
69
+ end
70
+ end
71
+
72
+ describe "failing bot with successful transformer" do
73
+ it 'should call handle_failed_run' do
74
+ runner = BrokenRunner.new('spec/dummy-broken-bot-ruby-2')
75
+ expect(runner).to receive(:handle_valid_record) # first record
76
+ expect(runner).to receive(:handle_valid_record) # first transform
77
+ expect(runner).to receive(:handle_failed_run)
78
+ runner.run
79
+ end
80
+ end
81
+
82
+ describe "sucessful bot with failing transformer" do
83
+ it 'should call handle_failed_run' do
84
+ runner = BrokenRunner.new('spec/dummy-broken-bot-ruby-3')
85
+ expect(runner).to receive(:handle_valid_record) # the untransformed one
86
+ expect(runner).to receive(:handle_failed_run) # the transformer breaks immediately
87
+ runner.run
88
+ end
89
+ end
90
+ end
42
91
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: turbot-runner
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.20
4
+ version: 0.0.21
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-07-22 00:00:00.000000000 Z
12
+ date: 2014-07-24 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: json-schema
@@ -43,6 +43,15 @@ files:
43
43
  - spec/dummy-bot-ruby/manifest.json
44
44
  - spec/dummy-bot-ruby/scraper.rb
45
45
  - spec/dummy-bot-ruby/transformer.rb
46
+ - spec/dummy-broken-bot-ruby-2/manifest.json
47
+ - spec/dummy-broken-bot-ruby-2/scraper.rb
48
+ - spec/dummy-broken-bot-ruby-2/transformer.rb
49
+ - spec/dummy-broken-bot-ruby-3/manifest.json
50
+ - spec/dummy-broken-bot-ruby-3/scraper.rb
51
+ - spec/dummy-broken-bot-ruby-3/transformer.rb
52
+ - spec/dummy-broken-bot-ruby/manifest.json
53
+ - spec/dummy-broken-bot-ruby/scraper.rb
54
+ - spec/dummy-broken-bot-ruby/transformer.rb
46
55
  - spec/turbot_runner_spec.rb
47
56
  - schema/schemas/company-schema.json
48
57
  - schema/schemas/financial-payment-schema.json