processor 0.0.0.beta → 0.0.0.initial
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/processor/version.rb +1 -1
- metadata +2 -20
- data/.rspec +0 -2
- data/example/example_runner.rb +0 -43
- data/example/migration.rb +0 -29
- data/example/observer/progress_bar.rb +0 -26
- data/example/simple_runner.rb +0 -12
- data/lib/processor/data_processor.rb +0 -28
- data/lib/processor/events_registrator.rb +0 -16
- data/lib/processor/observer/logger.rb +0 -98
- data/lib/processor/observer/null_observer.rb +0 -23
- data/lib/processor/thread_runner.rb +0 -59
- data/spec/example_spec.rb +0 -24
- data/spec/processor/events_registrator_spec.rb +0 -15
- data/spec/processor/observer/logger_spec.rb +0 -32
- data/spec/processor/thread_runner_spec.rb +0 -134
data/lib/processor/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: processor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.0.
|
4
|
+
version: 0.0.0.initial
|
5
5
|
prerelease: 6
|
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: 2013-
|
12
|
+
date: 2013-04-30 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -67,29 +67,15 @@ extensions: []
|
|
67
67
|
extra_rdoc_files: []
|
68
68
|
files:
|
69
69
|
- .gitignore
|
70
|
-
- .rspec
|
71
70
|
- .rvmrc
|
72
71
|
- .travis.yml
|
73
72
|
- Gemfile
|
74
73
|
- LICENSE
|
75
74
|
- README.md
|
76
75
|
- Rakefile
|
77
|
-
- example/example_runner.rb
|
78
|
-
- example/migration.rb
|
79
|
-
- example/observer/progress_bar.rb
|
80
|
-
- example/simple_runner.rb
|
81
76
|
- lib/processor.rb
|
82
|
-
- lib/processor/data_processor.rb
|
83
|
-
- lib/processor/events_registrator.rb
|
84
|
-
- lib/processor/observer/logger.rb
|
85
|
-
- lib/processor/observer/null_observer.rb
|
86
|
-
- lib/processor/thread_runner.rb
|
87
77
|
- lib/processor/version.rb
|
88
78
|
- processor.gemspec
|
89
|
-
- spec/example_spec.rb
|
90
|
-
- spec/processor/events_registrator_spec.rb
|
91
|
-
- spec/processor/observer/logger_spec.rb
|
92
|
-
- spec/processor/thread_runner_spec.rb
|
93
79
|
- spec/spec_helper_lite.rb
|
94
80
|
homepage: http://github.com/AlexParamonov/processor
|
95
81
|
licenses:
|
@@ -117,8 +103,4 @@ signing_key:
|
|
117
103
|
specification_version: 3
|
118
104
|
summary: Process records one by one
|
119
105
|
test_files:
|
120
|
-
- spec/example_spec.rb
|
121
|
-
- spec/processor/events_registrator_spec.rb
|
122
|
-
- spec/processor/observer/logger_spec.rb
|
123
|
-
- spec/processor/thread_runner_spec.rb
|
124
106
|
- spec/spec_helper_lite.rb
|
data/.rspec
DELETED
data/example/example_runner.rb
DELETED
@@ -1,43 +0,0 @@
|
|
1
|
-
require 'processor/thread_runner'
|
2
|
-
require 'processor/observer/logger'
|
3
|
-
|
4
|
-
module Processor
|
5
|
-
module Example
|
6
|
-
class ExampleRunner < ThreadRunner
|
7
|
-
def initialize
|
8
|
-
# Logger could be a lambda
|
9
|
-
# logger = -> name do
|
10
|
-
# ::Logger.new("log/debug_#{name}_daily.log", "daily").tap do |logger|
|
11
|
-
# logger.datetime_format = "%H:%M:%S"
|
12
|
-
# logger.level = ::Logger::DEBUG
|
13
|
-
# end
|
14
|
-
# end
|
15
|
-
|
16
|
-
# logger could be an instance of Ruby Logger
|
17
|
-
logger = ::Logger.new(STDOUT).tap do |logger|
|
18
|
-
logger.level = ::Logger::DEBUG
|
19
|
-
logger.formatter = -> _, _, _, msg do
|
20
|
-
"log < #{msg}\n"
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
# logger could be an instance of Rails Logger
|
25
|
-
# logger = Rails.logger
|
26
|
-
# Or be nil
|
27
|
-
# logger = nil
|
28
|
-
# in this case logger will be initialized as Ruby Logger and write to log/name_of_processor_time_stamp.log
|
29
|
-
|
30
|
-
# messenger could be an instance of Ruby Logger
|
31
|
-
messenger = ::Logger.new(STDOUT).tap do |logger|
|
32
|
-
logger.formatter = -> _, _, _, msg do
|
33
|
-
"message > #{msg}\n"
|
34
|
-
end
|
35
|
-
logger.level = ::Logger::INFO
|
36
|
-
end
|
37
|
-
|
38
|
-
logger_observer = Processor::Observer::Logger.new(logger, messenger: messenger)
|
39
|
-
super logger_observer
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
data/example/migration.rb
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
require 'processor/data_processor'
|
2
|
-
|
3
|
-
module Processor
|
4
|
-
module Example
|
5
|
-
class Migration < DataProcessor
|
6
|
-
attr_reader :records
|
7
|
-
def initialize(records)
|
8
|
-
@records = records
|
9
|
-
end
|
10
|
-
|
11
|
-
def done?(records)
|
12
|
-
records.count < 1
|
13
|
-
end
|
14
|
-
|
15
|
-
def process(record)
|
16
|
-
record.do_something
|
17
|
-
"OK"
|
18
|
-
end
|
19
|
-
|
20
|
-
def fetch_records
|
21
|
-
records.shift(2)
|
22
|
-
end
|
23
|
-
|
24
|
-
def total_records
|
25
|
-
records.count
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
require 'processor/observer/null_observer'
|
2
|
-
require 'progressbar'
|
3
|
-
|
4
|
-
module Processor
|
5
|
-
module Example
|
6
|
-
module Observer
|
7
|
-
class ProgressBar < Processor::Observer::NullObserver
|
8
|
-
def processing_started
|
9
|
-
@progress_bar = ::ProgressBar.new("Records", processor.total_records)
|
10
|
-
messenger.debug "Initialized ProgressBar with #{processor.total_records} records"
|
11
|
-
end
|
12
|
-
|
13
|
-
def before_record_processing(record)
|
14
|
-
progress_bar.inc
|
15
|
-
end
|
16
|
-
|
17
|
-
def processing_finished
|
18
|
-
progress_bar.finish
|
19
|
-
end
|
20
|
-
|
21
|
-
private
|
22
|
-
attr_reader :progress_bar
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
data/example/simple_runner.rb
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
module Processor
|
2
|
-
class DataProcessor
|
3
|
-
def done?(records)
|
4
|
-
records.count < 1
|
5
|
-
end
|
6
|
-
|
7
|
-
def process(record)
|
8
|
-
raise NotImplementedError
|
9
|
-
end
|
10
|
-
|
11
|
-
def fetch_records
|
12
|
-
raise NotImplementedError
|
13
|
-
end
|
14
|
-
|
15
|
-
def total_records
|
16
|
-
raise NotImplementedError
|
17
|
-
end
|
18
|
-
|
19
|
-
def name
|
20
|
-
# underscore a class name
|
21
|
-
self.class.name.to_s.
|
22
|
-
gsub(/::/, '_').
|
23
|
-
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
24
|
-
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
25
|
-
downcase
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
@@ -1,16 +0,0 @@
|
|
1
|
-
module Processor
|
2
|
-
class EventsRegistrator
|
3
|
-
def initialize(observers)
|
4
|
-
@observers = observers
|
5
|
-
end
|
6
|
-
|
7
|
-
def register(event, *data)
|
8
|
-
observers.each do |observer|
|
9
|
-
observer.update event, *data
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
private
|
14
|
-
attr_reader :observers
|
15
|
-
end
|
16
|
-
end
|
@@ -1,98 +0,0 @@
|
|
1
|
-
require_relative 'null_observer'
|
2
|
-
require 'logger'
|
3
|
-
|
4
|
-
module Processor
|
5
|
-
module Observer
|
6
|
-
class Logger < NullObserver
|
7
|
-
def initialize(logger = nil, options = {})
|
8
|
-
@logger_source = logger
|
9
|
-
super options
|
10
|
-
end
|
11
|
-
|
12
|
-
def processing_started(processor)
|
13
|
-
initialize_logger(processor)
|
14
|
-
|
15
|
-
message = "Processing of #{processor.name} started."
|
16
|
-
logger.info message
|
17
|
-
messenger.info message
|
18
|
-
|
19
|
-
message = <<-MESSAGE.gsub(/^\s+/, '')
|
20
|
-
Proggress will be saved to the log file. Run
|
21
|
-
tail -f #{log_file_name}
|
22
|
-
to see log in realtime
|
23
|
-
MESSAGE
|
24
|
-
messenger.info message if use_log_file?
|
25
|
-
end
|
26
|
-
|
27
|
-
def before_record_processing(record)
|
28
|
-
message = "Record #{id_for record} is going to be processed"
|
29
|
-
logger.debug message
|
30
|
-
messenger.debug message
|
31
|
-
end
|
32
|
-
|
33
|
-
def after_record_processing(record, result)
|
34
|
-
message = "Successfully processed #{id_for record}: #{result}"
|
35
|
-
logger.info message
|
36
|
-
messenger.debug message
|
37
|
-
end
|
38
|
-
|
39
|
-
def processing_finished(processor)
|
40
|
-
message = "Processing of #{processor.name} finished."
|
41
|
-
logger.info message
|
42
|
-
messenger.info message
|
43
|
-
messenger.info "Log file saved to #{log_file_name}" if use_log_file?
|
44
|
-
end
|
45
|
-
|
46
|
-
def record_processing_error(record, exception)
|
47
|
-
message = "Error processing #{id_for record}: #{exception}"
|
48
|
-
logger.error message
|
49
|
-
messenger.error message
|
50
|
-
end
|
51
|
-
|
52
|
-
def processing_error(processor, exception)
|
53
|
-
message = "Processing #{processor.name} failed: #{exception}"
|
54
|
-
logger.fatal message
|
55
|
-
messenger.fatal message
|
56
|
-
end
|
57
|
-
|
58
|
-
private
|
59
|
-
attr_reader :logger, :log_file_name
|
60
|
-
|
61
|
-
def initialize_logger(processor)
|
62
|
-
@logger =
|
63
|
-
if @logger_source.is_a? Proc
|
64
|
-
@logger_source.call processor.name
|
65
|
-
else
|
66
|
-
@logger_source or ::Logger.new(create_log_filename(processor.name)).tap do |logger|
|
67
|
-
logger.level = ::Logger::INFO
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
def create_log_filename(processor_name)
|
73
|
-
@log_file_name = "log/#{processor_name}_on_#{current_time_string}.log"
|
74
|
-
end
|
75
|
-
|
76
|
-
def use_log_file?
|
77
|
-
not log_file_name.nil?
|
78
|
-
end
|
79
|
-
|
80
|
-
def current_time_string
|
81
|
-
Time.now.gmtime.strftime "%Y-%m-%d_%H%M%S_UTC"
|
82
|
-
end
|
83
|
-
|
84
|
-
def id_for record
|
85
|
-
[:uid, :id, :to_token, :token, :to_sym].each do |method|
|
86
|
-
return record.public_send method if record.respond_to? method
|
87
|
-
end
|
88
|
-
|
89
|
-
[:uid, :id, :token, :sym, :UID, :ID, :TOKEN, :SYM].each do |method|
|
90
|
-
return record[method] if record.key? method
|
91
|
-
return record[method.to_s] if record.key? method.to_s
|
92
|
-
end if record.respond_to?(:key?) && record.respond_to?(:[])
|
93
|
-
|
94
|
-
record.to_s
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
require 'logger'
|
2
|
-
|
3
|
-
module Processor
|
4
|
-
module Observer
|
5
|
-
class NullObserver
|
6
|
-
def initialize(options = {})
|
7
|
-
@messenger = options.fetch :messenger do
|
8
|
-
::Logger.new(STDOUT).tap do |logger|
|
9
|
-
logger.formatter = -> _, _, _, msg do
|
10
|
-
"> #{msg}\n"
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
def method_missing(*); end
|
17
|
-
alias_method :update, :send
|
18
|
-
|
19
|
-
private
|
20
|
-
attr_reader :messenger
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
@@ -1,59 +0,0 @@
|
|
1
|
-
require_relative "events_registrator"
|
2
|
-
|
3
|
-
module Processor
|
4
|
-
class ThreadRunner
|
5
|
-
def initialize(*observers)
|
6
|
-
@observers = observers
|
7
|
-
end
|
8
|
-
|
9
|
-
# This method is thread-safe. But not observers.
|
10
|
-
# Consider creating new runner for a thread or use thread safe observers
|
11
|
-
def run(processor)
|
12
|
-
events = events_registrator
|
13
|
-
events.register :processing_started, processor
|
14
|
-
|
15
|
-
records_ran = 0
|
16
|
-
until processor.done?(records = processor.fetch_records)
|
17
|
-
threads = []
|
18
|
-
begin
|
19
|
-
records.each do |record|
|
20
|
-
recursion_preventer processor do
|
21
|
-
records_ran += 1
|
22
|
-
end
|
23
|
-
|
24
|
-
threads << Thread.new(processor, record) do |thread_data_processor, thread_record|
|
25
|
-
begin
|
26
|
-
events.register :before_record_processing, thread_record
|
27
|
-
|
28
|
-
result = thread_data_processor.process(thread_record)
|
29
|
-
|
30
|
-
events.register :after_record_processing, thread_record, result
|
31
|
-
rescue RuntimeError => exception
|
32
|
-
events.register :record_processing_error, thread_record, exception
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
ensure # join already created threads even if recursion was detected
|
37
|
-
threads.each(&:join)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
events.register :processing_finished, processor
|
42
|
-
rescue Exception => exception
|
43
|
-
events.register :processing_error, processor, exception
|
44
|
-
raise exception
|
45
|
-
end
|
46
|
-
|
47
|
-
private
|
48
|
-
attr_reader :observers
|
49
|
-
|
50
|
-
def recursion_preventer(processor)
|
51
|
-
counter = yield
|
52
|
-
raise Exception, "Processing fall into recursion. Check logs." if counter > (processor.total_records * 1.1).round + 10
|
53
|
-
end
|
54
|
-
|
55
|
-
def events_registrator
|
56
|
-
EventsRegistrator.new observers
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
data/spec/example_spec.rb
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
require 'spec_helper_lite'
|
2
|
-
require_relative '../example/example_runner'
|
3
|
-
require_relative '../example/migration'
|
4
|
-
require 'fileutils'
|
5
|
-
|
6
|
-
describe "Example" do
|
7
|
-
before(:each) do
|
8
|
-
records = %w[item1 item2 item3 item4 item5]
|
9
|
-
records.each do |record|
|
10
|
-
record.should_receive(:do_something).once
|
11
|
-
end
|
12
|
-
@migration = Processor::Example::Migration.new records
|
13
|
-
end
|
14
|
-
|
15
|
-
it "should use logger and messenger" do
|
16
|
-
migration_runner = Processor::Example::ExampleRunner.new
|
17
|
-
migration_runner.run @migration
|
18
|
-
end
|
19
|
-
|
20
|
-
it "should run without configuration" do
|
21
|
-
runner = Processor::ThreadRunner.new
|
22
|
-
runner.run @migration
|
23
|
-
end
|
24
|
-
end
|
@@ -1,15 +0,0 @@
|
|
1
|
-
require 'spec_helper_lite'
|
2
|
-
require 'processor/events_registrator'
|
3
|
-
|
4
|
-
describe Processor::EventsRegistrator do
|
5
|
-
subject { Processor::EventsRegistrator }
|
6
|
-
|
7
|
-
it "should broadcast events to all observers" do
|
8
|
-
observers = 3.times.map do
|
9
|
-
stub(:observer).tap { |observer| observer.should_receive(:update).with(:test_event).once }
|
10
|
-
end
|
11
|
-
|
12
|
-
events = subject.new(observers)
|
13
|
-
events.register :test_event
|
14
|
-
end
|
15
|
-
end
|
@@ -1,32 +0,0 @@
|
|
1
|
-
require 'spec_helper_lite'
|
2
|
-
require 'processor/observer/logger'
|
3
|
-
|
4
|
-
describe Processor::Observer::Logger do
|
5
|
-
let(:processor) { stub.as_null_object }
|
6
|
-
let(:no_messages) { ::Logger.new("/dev/null") }
|
7
|
-
|
8
|
-
subject { Processor::Observer::Logger }
|
9
|
-
it "accepts logger builder as parameter" do
|
10
|
-
external_logger = mock
|
11
|
-
logger_observer = subject.new -> name { external_logger }, messenger: no_messages
|
12
|
-
|
13
|
-
external_logger.should_receive(:info)
|
14
|
-
logger_observer.processing_started processor
|
15
|
-
end
|
16
|
-
|
17
|
-
it "accepts logger as parameter" do
|
18
|
-
external_logger = mock
|
19
|
-
logger_observer = subject.new external_logger, messenger: no_messages
|
20
|
-
|
21
|
-
external_logger.should_receive(:info)
|
22
|
-
logger_observer.processing_started processor
|
23
|
-
end
|
24
|
-
|
25
|
-
it "use ruby Logger if no external logger provided" do
|
26
|
-
logger_observer = subject.new nil, messenger: no_messages
|
27
|
-
|
28
|
-
Logger.should_receive(:new).and_return(stub.as_null_object)
|
29
|
-
logger_observer.processing_started processor
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
@@ -1,134 +0,0 @@
|
|
1
|
-
require 'spec_helper_lite'
|
2
|
-
require 'processor/thread_runner'
|
3
|
-
|
4
|
-
processor = Class.new do
|
5
|
-
def done?(records)
|
6
|
-
records.count < 1
|
7
|
-
end
|
8
|
-
|
9
|
-
def total_records
|
10
|
-
10
|
11
|
-
end
|
12
|
-
end.new
|
13
|
-
|
14
|
-
describe Processor::ThreadRunner do
|
15
|
-
let(:runner) { Processor::ThreadRunner.new }
|
16
|
-
let(:events_registrator) { stub.as_null_object }
|
17
|
-
before(:each) do
|
18
|
-
runner.stub(events_registrator: events_registrator)
|
19
|
-
end
|
20
|
-
|
21
|
-
it "should fetch records from processor till it'll be done" do
|
22
|
-
processor.stub(:done?).and_return(false, false, true)
|
23
|
-
processor.should_receive(:fetch_records).exactly(3).times.and_return([])
|
24
|
-
runner.run processor
|
25
|
-
end
|
26
|
-
|
27
|
-
it "should send each found record to processor" do
|
28
|
-
records = [mock(:one), mock(:two), mock(:three)]
|
29
|
-
records.each { |record| processor.should_receive(:process).with(record) }
|
30
|
-
|
31
|
-
processor.stub(:fetch_records).and_return(records, [])
|
32
|
-
runner.run processor
|
33
|
-
end
|
34
|
-
|
35
|
-
describe "exception handling" do
|
36
|
-
let(:record) { stub }
|
37
|
-
before(:each) do
|
38
|
-
processor.stub(:fetch_records).and_return([record], [record], [])
|
39
|
-
end
|
40
|
-
|
41
|
-
describe "processing a record raised RuntimeError" do
|
42
|
-
it "should continue processing" do
|
43
|
-
processor.should_receive(:process).twice.and_raise(RuntimeError)
|
44
|
-
expect { runner.run processor }.to_not raise_error
|
45
|
-
end
|
46
|
-
|
47
|
-
it "should register a record_processing_error event" do
|
48
|
-
event_registered = false
|
49
|
-
events_registrator.should_receive(:register) do |event_name, failed_record, exception|
|
50
|
-
next if event_name != :record_processing_error
|
51
|
-
event_name.should eq :record_processing_error
|
52
|
-
failed_record.should eq record
|
53
|
-
exception.should be_a RuntimeError
|
54
|
-
event_registered = true
|
55
|
-
end.any_number_of_times
|
56
|
-
|
57
|
-
processor.stub(:process).and_raise(RuntimeError)
|
58
|
-
|
59
|
-
begin
|
60
|
-
runner.run processor
|
61
|
-
rescue Exception; end
|
62
|
-
event_registered.should be_true
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
describe "processing a record raised Exception" do
|
67
|
-
it "should break processing and rerise Exception" do
|
68
|
-
custom_exception = Class.new Exception
|
69
|
-
processor.should_receive(:process).once.and_raise(custom_exception)
|
70
|
-
expect { runner.run processor }.to raise_error(custom_exception)
|
71
|
-
end
|
72
|
-
|
73
|
-
it "should register a processing_error event" do
|
74
|
-
event_registered = false
|
75
|
-
events_registrator.should_receive(:register) do |event_name, current_processor, exception|
|
76
|
-
next if event_name != :processing_error
|
77
|
-
event_name.should eq :processing_error
|
78
|
-
current_processor.should eq processor
|
79
|
-
exception.should be_a Exception
|
80
|
-
event_registered = true
|
81
|
-
end.any_number_of_times
|
82
|
-
|
83
|
-
processor.stub(:process).and_raise(Exception)
|
84
|
-
|
85
|
-
begin
|
86
|
-
runner.run processor
|
87
|
-
rescue Exception; end
|
88
|
-
event_registered.should be_true
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
describe "fetching records raised" do
|
93
|
-
it "should break processing and rerise Exception" do
|
94
|
-
custom_exception = Class.new RuntimeError
|
95
|
-
processor.stub(:fetch_records).and_raise(custom_exception)
|
96
|
-
processor.should_not_receive(:process)
|
97
|
-
expect { runner.run processor }.to raise_error(custom_exception)
|
98
|
-
end
|
99
|
-
|
100
|
-
it "should register a processing_error" do
|
101
|
-
event_registered = false
|
102
|
-
events_registrator.should_receive(:register) do |event_name, processor, exception|
|
103
|
-
next if event_name != :processing_error
|
104
|
-
event_name.should eq :processing_error
|
105
|
-
exception.should be_a RuntimeError
|
106
|
-
event_registered = true
|
107
|
-
end.any_number_of_times
|
108
|
-
|
109
|
-
processor.stub(:fetch_records).and_raise(RuntimeError)
|
110
|
-
|
111
|
-
begin
|
112
|
-
runner.run processor
|
113
|
-
rescue Exception; end
|
114
|
-
event_registered.should be_true
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
describe "recursion" do
|
120
|
-
it "should not allow infinit recursion" do
|
121
|
-
processor.stub(:fetch_records).and_return([:one, :two])
|
122
|
-
processor.should_receive(:process).at_most(100).times
|
123
|
-
expect { runner.run processor }.to raise_error(Exception, /Processing fall into recursion/)
|
124
|
-
end
|
125
|
-
|
126
|
-
it "should have 10% + 10 rerurns window" do
|
127
|
-
processor.stub(total_records: 100)
|
128
|
-
processor.stub(:fetch_records).and_return([:one, :two])
|
129
|
-
processor.should_receive(:process).exactly(120).times
|
130
|
-
expect { runner.run processor }.to raise_error(Exception, /Processing fall into recursion/)
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|