employer 0.2 → 0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - jruby-19mode
5
+ script: rspec
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Employer
1
+ # Employer [![Build Status](https://travis-ci.org/mkremer/employer.png)](https://travis-ci.org/mkremer/employer)
2
2
 
3
3
  There comes a time in the life of an application that async job processing
4
4
  becomes a requirement. If you want something flexible that you can easily adapt
@@ -140,13 +140,13 @@ forking_employees 4
140
140
  The comments in the file pretty much explain how you should edit it.
141
141
 
142
142
  When setup properly you can start processing jobs by running `employer` (or
143
- `employer -c /path/to/employer\_config.rb`, likely prepended with `bundle exec`)
143
+ `employer -c /path/to/employer_config.rb`, likely prepended with `bundle exec`)
144
144
 
145
145
  In your application code you can obtain a pipeline to enqueue jobs with like so:
146
146
 
147
147
  ```ruby
148
148
  # Obtain the pipeline
149
- pipeline = Employer::Workshop.enqueue("/path/to/employer\_config.rb")
149
+ pipeline = Employer::Workshop.enqueue("/path/to/employer_config.rb")
150
150
 
151
151
  # Enqueue a job
152
152
  job = NamePutsJob.new
@@ -8,7 +8,7 @@ Gem::Specification.new do |gem|
8
8
  gem.version = Employer::VERSION
9
9
  gem.authors = ["Mark Kremer"]
10
10
  gem.email = ["mark@without-brains.net"]
11
- gem.summary = %q{Job processing made easy}
11
+ gem.summary = %q{Job processing with pluggable backends made easy}
12
12
  gem.homepage = "https://github.com/mkremer/employer"
13
13
  gem.license = "MIT"
14
14
 
@@ -19,6 +19,7 @@ Gem::Specification.new do |gem|
19
19
 
20
20
  gem.add_runtime_dependency "thor", "~> 0.17"
21
21
 
22
+ gem.add_development_dependency "rake"
22
23
  gem.add_development_dependency "rspec"
23
24
  gem.add_development_dependency "pry"
24
25
  end
@@ -1,5 +1,6 @@
1
1
  require "employer/version"
2
2
  require "employer/errors"
3
+ require "employer/logger"
3
4
  require "employer/pipeline"
4
5
  require "employer/job"
5
6
  require "employer/employees"
@@ -2,16 +2,17 @@ require_relative "errors"
2
2
 
3
3
  module Employer
4
4
  class Boss
5
- attr_reader :pipeline, :employees, :keep_going, :sleep_time
5
+ attr_reader :pipeline, :logger, :employees, :keep_going, :sleep_time
6
6
 
7
- def initialize
8
- @pipeline = nil
7
+ def initialize(logger)
8
+ @logger = logger
9
+ @pipeline = Employer::Pipeline.new(logger)
9
10
  @employees = []
10
11
  @sleep_time_index = 0
11
12
  end
12
13
 
13
- def pipeline=(pipeline)
14
- @pipeline = pipeline
14
+ def pipeline_backend=(backend)
15
+ pipeline.backend = backend
15
16
  end
16
17
 
17
18
  def allocate_employee(employee)
@@ -92,6 +93,7 @@ module Employer
92
93
 
93
94
  def delegate_job(job)
94
95
  raise Employer::Errors::NoEmployeeFree unless employee = free_employee
96
+ logger.info("Delegating job #{job.id} to employee #{employee.object_id}")
95
97
  employee.work(job)
96
98
  end
97
99
 
@@ -1,5 +1,6 @@
1
1
  require "thor"
2
2
  require "fileutils"
3
+ require "logger"
3
4
 
4
5
  module Employer
5
6
  class CLI < Thor
@@ -14,7 +15,8 @@ module Employer
14
15
  end
15
16
 
16
17
  int_count = 0
17
- workshop = Employer::Workshop.setup(File.read(options[:config]))
18
+ workshop = Employer::Workshop.new(File.read(options[:config]))
19
+ workshop.log_to(::Logger.new(STDOUT))
18
20
 
19
21
  Signal.trap("INT") do
20
22
  int_count += 1
@@ -3,7 +3,11 @@ require_relative "../errors"
3
3
  module Employer
4
4
  module Employees
5
5
  class AbstractEmployee
6
- attr_reader :job
6
+ attr_reader :job, :logger
7
+
8
+ def initialize(logger)
9
+ @logger = logger
10
+ end
7
11
 
8
12
  def work(job)
9
13
  raise Employer::Errors::EmployeeBusy unless free?
@@ -11,7 +15,9 @@ module Employer
11
15
  end
12
16
 
13
17
  def perform_job
18
+ logger.debug("Employee #{self.object_id} is now performing job #{job.id}")
14
19
  job.perform
20
+ logger.debug("Employee #{self.object_id} has now completed #{job.id}")
15
21
  end
16
22
 
17
23
  def wait_for_completion
@@ -0,0 +1,47 @@
1
+ module Employer
2
+ class Logger
3
+ attr_reader :loggers
4
+
5
+ def initialize
6
+ @loggers = []
7
+ end
8
+
9
+ def append_to(logger)
10
+ loggers << logger
11
+ end
12
+
13
+ def debug(message = nil, &block)
14
+ log(:debug, message, &block)
15
+ end
16
+
17
+ def error(message = nil, &block)
18
+ log(:error, message, &block)
19
+ end
20
+
21
+ def warn(message = nil, &block)
22
+ log(:warn, message, &block)
23
+ end
24
+
25
+ def info(message = nil, &block)
26
+ log(:info, message, &block)
27
+ end
28
+
29
+ def fatal(message = nil, &block)
30
+ log(:fatal, message, &block)
31
+ end
32
+
33
+ private
34
+
35
+ def log(level, message = nil, &block)
36
+ loggers.each do |logger|
37
+ next unless logger.respond_to?(level)
38
+
39
+ if message
40
+ logger.public_send(level, message)
41
+ elsif block
42
+ logger.public_send(level, &block)
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -2,6 +2,12 @@ require_relative "errors"
2
2
 
3
3
  module Employer
4
4
  class Pipeline
5
+ attr_reader :logger
6
+
7
+ def initialize(logger)
8
+ @logger = logger
9
+ end
10
+
5
11
  def backend=(backend)
6
12
  @backend = backend
7
13
  end
@@ -26,21 +32,25 @@ module Employer
26
32
 
27
33
  def clear
28
34
  raise Employer::Errors::PipelineBackendRequired if backend.nil?
35
+ logger.info("Clearing pipeline of all jobs!")
29
36
  backend.clear
30
37
  end
31
38
 
32
39
  def complete(job)
33
40
  raise Employer::Errors::PipelineBackendRequired if backend.nil?
41
+ logger.info("Marking job #{job.id} as complete")
34
42
  backend.complete(job)
35
43
  end
36
44
 
37
45
  def reset(job)
38
46
  raise Employer::Errors::PipelineBackendRequired if backend.nil?
47
+ logger.info("Resetting job #{job.id}")
39
48
  backend.reset(job)
40
49
  end
41
50
 
42
51
  def fail(job)
43
52
  raise Employer::Errors::PipelineBackendRequired if backend.nil?
53
+ logger.info("Marking job #{job.id} as failed")
44
54
  backend.fail(job)
45
55
  end
46
56
 
@@ -1,3 +1,3 @@
1
1
  module Employer
2
- VERSION = "0.2"
2
+ VERSION = "0.3"
3
3
  end
@@ -2,16 +2,29 @@ require_relative "errors"
2
2
 
3
3
  module Employer
4
4
  class Workshop
5
- def self.setup(config_code, skip_employees = false)
6
- boss = Employer::Boss.new
7
- pipeline = Employer::Pipeline.new
8
- boss.pipeline = pipeline
9
- workshop = new(boss, config_code, skip_employees)
10
- end
5
+ attr_reader :logger
11
6
 
12
7
  def self.pipeline(filename)
13
- workshop = setup(File.read(filename), true)
14
- workshop.pipeline
8
+ new(File.read(filename), true).pipeline
9
+ end
10
+
11
+ def initialize(config_code, skip_employees = false)
12
+ @logger = Employer::Logger.new
13
+ @boss = Employer::Boss.new(logger)
14
+ @forking_employees = 0
15
+ @threading_employees = 0
16
+
17
+ instance_eval(config_code)
18
+
19
+ unless skip_employees
20
+ @forking_employees.times do
21
+ @boss.allocate_employee(Employer::Employees::ForkingEmployee.new(logger))
22
+ end
23
+
24
+ @threading_employees.times do
25
+ @boss.allocate_employee(Employer::Employees::ThreadingEmployee.new(logger))
26
+ end
27
+ end
15
28
  end
16
29
 
17
30
  def run
@@ -31,6 +44,10 @@ module Employer
31
44
  @boss.pipeline
32
45
  end
33
46
 
47
+ def log_to(log_to_logger)
48
+ logger.append_to(log_to_logger)
49
+ end
50
+
34
51
  private
35
52
 
36
53
  def forking_employees(number)
@@ -42,25 +59,7 @@ module Employer
42
59
  end
43
60
 
44
61
  def pipeline_backend(backend)
45
- @boss.pipeline.backend = backend
46
- end
47
-
48
- def initialize(boss, config_code, skip_employees)
49
- @boss = boss
50
- @forking_employees = 0
51
- @threading_employees = 0
52
-
53
- instance_eval(config_code)
54
-
55
- unless skip_employees
56
- @forking_employees.times do
57
- @boss.allocate_employee(Employer::Employees::ForkingEmployee.new)
58
- end
59
-
60
- @threading_employees.times do
61
- @boss.allocate_employee(Employer::Employees::ThreadingEmployee.new)
62
- end
63
- end
62
+ @boss.pipeline_backend = backend
64
63
  end
65
64
  end
66
65
  end
@@ -1,23 +1,49 @@
1
1
  require "employer/boss"
2
2
 
3
3
  describe Employer::Boss do
4
+ before(:each) do
5
+ stub_const("Employer::Pipeline", Class.new)
6
+ Employer::Pipeline.stub(:new).and_return(pipeline)
7
+ end
8
+
4
9
  let(:pipeline) { double("Pipeline") }
5
10
  let(:employee) { double("Employee") }
6
11
  let(:free_employee) { double("Free employee", free?: true) }
7
12
  let(:busy_employee) { double("Busy employee", free?: false) }
8
- let(:boss) { Employer::Boss.new }
13
+ let(:logger) { double("Logger").as_null_object }
14
+ let(:boss) { Employer::Boss.new(logger) }
9
15
 
10
- it "can be given a pipeline" do
11
- boss.pipeline = pipeline
12
- boss.pipeline.should eq(pipeline)
16
+ describe "#initialize" do
17
+ let(:logger) { double("Logger") }
18
+
19
+ it "sets the logger" do
20
+ boss = Employer::Boss.new(logger)
21
+ boss.logger.should eq(logger)
22
+ end
23
+
24
+ it "sets a pipeline with the logger" do
25
+ Employer::Pipeline.should_receive(:new).with(logger).and_return(pipeline)
26
+ boss = Employer::Boss.new(logger)
27
+ boss.pipeline.should eq(pipeline)
28
+ end
13
29
  end
14
30
 
15
- it "can be given employees" do
16
- john = double
17
- jane = double
18
- boss.allocate_employee(john)
19
- boss.allocate_employee(jane)
20
- boss.employees.should eq([john, jane])
31
+ describe "#pipeline_backend=" do
32
+ it "sets the pipeline backend" do
33
+ backend = double("Backend")
34
+ boss.pipeline.should_receive(:backend=).with(backend)
35
+ boss.pipeline_backend = backend
36
+ end
37
+ end
38
+
39
+ describe "#allocate_employee" do
40
+ it "can be given employees" do
41
+ john = double
42
+ jane = double
43
+ boss.allocate_employee(john)
44
+ boss.allocate_employee(jane)
45
+ boss.employees.should eq([john, jane])
46
+ end
21
47
  end
22
48
 
23
49
  describe "#manage" do
@@ -47,7 +73,6 @@ describe Employer::Boss do
47
73
 
48
74
  before(:each) do
49
75
  boss.stub(:get_work).and_return(job1, job2, nil, nil)
50
- boss.pipeline = pipeline
51
76
  end
52
77
 
53
78
  it "puts free employees to work while work is available" do
@@ -85,7 +110,6 @@ describe Employer::Boss do
85
110
  describe "#get_work" do
86
111
  before(:each) do
87
112
  pipeline.stub(:dequeue).and_return(nil)
88
- boss.pipeline = pipeline
89
113
  end
90
114
 
91
115
  it "increases sleep time each time it gets no job" do
@@ -116,10 +140,6 @@ describe Employer::Boss do
116
140
  end
117
141
 
118
142
  describe "#update_job_status" do
119
- before(:each) do
120
- boss.pipeline = pipeline
121
- end
122
-
123
143
  let(:job) { double("Job") }
124
144
  let(:employee) { employee = double("Employee", job: job) }
125
145
 
@@ -0,0 +1,95 @@
1
+ require "employer/logger"
2
+
3
+ describe Employer::Logger do
4
+ let(:logger) { Employer::Logger.new }
5
+ let(:stdout_logger) { double("STDOUT Logger") }
6
+ let(:file_logger) { double("File Logger") }
7
+ let(:message) { "log me, please" }
8
+ let(:block) { lambda { "log me please" } }
9
+
10
+ describe "#append_to" do
11
+ it "accepts other loggers to write to" do
12
+ logger.append_to(stdout_logger)
13
+ logger.append_to(file_logger)
14
+ logger.loggers.should include(stdout_logger)
15
+ logger.loggers.should include(file_logger)
16
+ end
17
+ end
18
+
19
+ context "with loggers assigned" do
20
+ before(:each) do
21
+ logger.append_to(stdout_logger)
22
+ logger.append_to(file_logger)
23
+ end
24
+
25
+ describe "#debug" do
26
+ it "passes string messages to its loggers" do
27
+ stdout_logger.should_receive(:debug).with(message)
28
+ file_logger.should_receive(:debug).with(message)
29
+ logger.debug(message)
30
+ end
31
+
32
+ it "passes block messages to its loggers" do
33
+ stdout_logger.should_receive(:debug).with(&block)
34
+ file_logger.should_receive(:debug).with(&block)
35
+ logger.debug(&block)
36
+ end
37
+ end
38
+
39
+ describe "#error" do
40
+ it "passes string messages to its loggers" do
41
+ stdout_logger.should_receive(:error).with(message)
42
+ file_logger.should_receive(:error).with(message)
43
+ logger.error(message)
44
+ end
45
+
46
+ it "passes block messages to its loggers" do
47
+ stdout_logger.should_receive(:error).with(&block)
48
+ file_logger.should_receive(:error).with(&block)
49
+ logger.error(&block)
50
+ end
51
+ end
52
+
53
+ describe "#warn" do
54
+ it "passes string messages to its loggers" do
55
+ stdout_logger.should_receive(:warn).with(message)
56
+ file_logger.should_receive(:warn).with(message)
57
+ logger.warn(message)
58
+ end
59
+
60
+ it "passes block messages to its loggers" do
61
+ stdout_logger.should_receive(:warn).with(&block)
62
+ file_logger.should_receive(:warn).with(&block)
63
+ logger.warn(&block)
64
+ end
65
+ end
66
+
67
+ describe "#info" do
68
+ it "passes string messages to its loggers" do
69
+ stdout_logger.should_receive(:info).with(message)
70
+ file_logger.should_receive(:info).with(message)
71
+ logger.info(message)
72
+ end
73
+
74
+ it "passes block messages to its loggers" do
75
+ stdout_logger.should_receive(:info).with(&block)
76
+ file_logger.should_receive(:info).with(&block)
77
+ logger.info(&block)
78
+ end
79
+ end
80
+
81
+ describe "#fatal" do
82
+ it "passes string messages to its loggers" do
83
+ stdout_logger.should_receive(:fatal).with(message)
84
+ file_logger.should_receive(:fatal).with(message)
85
+ logger.fatal(message)
86
+ end
87
+
88
+ it "passes block messages to its loggers" do
89
+ stdout_logger.should_receive(:fatal).with(&block)
90
+ file_logger.should_receive(:fatal).with(&block)
91
+ logger.fatal(&block)
92
+ end
93
+ end
94
+ end
95
+ end
@@ -1,10 +1,20 @@
1
1
  require "employer/pipeline"
2
2
 
3
3
  describe Employer::Pipeline do
4
- let(:pipeline) { Employer::Pipeline.new }
4
+ let(:logger) { double("Logger").as_null_object }
5
+ let(:pipeline) { Employer::Pipeline.new(logger) }
5
6
  let(:backend) { double("Pipeline backend") }
6
7
  let(:job) { double("Job") }
7
8
 
9
+ describe "#initialize" do
10
+ let(:logger) { double("Logger") }
11
+
12
+ it "sets the logger" do
13
+ pipeline = Employer::Pipeline.new(logger)
14
+ pipeline.logger.should eq(logger)
15
+ end
16
+ end
17
+
8
18
  it "has a pluggable backend" do
9
19
  pipeline.backend = backend
10
20
  pipeline.backend.should eq(backend)
@@ -1,105 +1,132 @@
1
- require "employer/workshop"
1
+ require "employer"
2
2
 
3
3
  describe Employer::Workshop do
4
4
  before(:each) do
5
- stub_const("Employer::Boss", Class.new)
6
- stub_const("Employer::Pipeline", Class.new)
7
- stub_const("Employer::Employees::ForkingEmployee", Class.new)
8
- stub_const("Employer::Employees::ThreadingEmployee", Class.new)
9
5
  stub_const("TestPipelineBackend", Class.new)
10
6
  end
11
7
 
12
- let(:boss) { double("Boss").as_null_object }
13
- let(:config_code) do
14
- <<CONFIG
15
- pipeline_backend TestPipelineBackend.new
16
- forking_employees 2
17
- CONFIG
18
- end
19
- let(:workshop) do
20
- Employer::Boss.should_receive(:new).and_return(boss)
21
- Employer::Workshop.setup(config_code)
22
- end
8
+ let(:config_code) { "pipeline_backend TestPipelineBackend.new" }
23
9
 
24
- describe ".setup" do
25
- it "sets up a workshop" do
26
- pipeline_backend = double("Pipeline backend")
27
- TestPipelineBackend.should_receive(:new).and_return(pipeline_backend)
28
- boss = double("Boss")
29
- pipeline = double("Pipeline")
30
- forking_employee1 = double("Forking Employee 1")
31
- forking_employee2 = double("Forking Employee 2")
32
- forking_employee3 = double("Forking Employee 3")
33
- threading_employee1 = double("Threading Employee 1")
34
- threading_employee2 = double("Threading Employee 2")
10
+ describe "#initialize" do
11
+ let(:workshop) { Employer::Workshop.new(config_code) }
12
+
13
+ after(:each) do
14
+ workshop
15
+ end
16
+
17
+ it "sets up a logger" do
18
+ workshop.logger.should be_instance_of(Employer::Logger)
19
+ end
20
+
21
+ it "sets up a boss" do
22
+ logger = double("Logger")
23
+ Employer::Logger.should_receive(:new).and_return(logger)
24
+ Employer::Boss.should_receive(:new).with(logger).and_call_original
25
+ end
35
26
 
27
+ it "sets the defined pipeline backend" do
28
+ boss = double("Boss")
36
29
  Employer::Boss.should_receive(:new).and_return(boss)
37
- Employer::Pipeline.should_receive(:new).and_return(pipeline)
38
- boss.should_receive(:pipeline=).with(pipeline)
39
- boss.should_receive(:pipeline).and_return(pipeline)
40
- pipeline.should_receive(:backend=).with(pipeline_backend)
41
- Employer::Employees::ForkingEmployee.should_receive(:new).and_return(forking_employee1, forking_employee2, forking_employee3)
42
- Employer::Employees::ThreadingEmployee.should_receive(:new).and_return(threading_employee1, threading_employee2)
43
- boss.should_receive(:allocate_employee).with(forking_employee1)
44
- boss.should_receive(:allocate_employee).with(forking_employee2)
45
- boss.should_receive(:allocate_employee).with(forking_employee3)
46
- boss.should_receive(:allocate_employee).with(threading_employee1)
47
- boss.should_receive(:allocate_employee).with(threading_employee2)
48
-
49
- config_code = <<CONFIG
50
- pipeline_backend TestPipelineBackend.new
51
- forking_employees 3
52
- threading_employees 2
53
- CONFIG
54
-
55
- workshop = Employer::Workshop.setup(config_code)
56
- workshop.should be_instance_of(Employer::Workshop)
30
+ boss.should_receive(:pipeline_backend=).with(instance_of(TestPipelineBackend))
31
+ end
32
+
33
+ context "with loggers" do
34
+ before(:each) do
35
+ stub_const("MyFirstLogger", Class.new)
36
+ stub_const("MySecondLogger", Class.new)
37
+ end
38
+
39
+ let(:config_code) { "log_to MyFirstLogger.new\nlog_to MySecondLogger.new" }
40
+
41
+ it "tells the logger to append to the given logger" do
42
+ workshop_logger = double("Logger")
43
+ Employer::Logger.should_receive(:new).and_return(workshop_logger)
44
+ workshop_logger.should_receive(:append_to).with(instance_of(MyFirstLogger))
45
+ workshop_logger.should_receive(:append_to).with(instance_of(MySecondLogger))
46
+ end
47
+ end
48
+
49
+ context "with only forking employees" do
50
+ let(:config_code) { "forking_employees 3" }
51
+
52
+ it "allocates forking employees" do
53
+ Employer::Employees::ForkingEmployee.should_receive(:new).with(instance_of(Employer::Logger)).exactly(3).times.and_call_original
54
+ Employer::Boss.any_instance.should_receive(:allocate_employee).with(instance_of(Employer::Employees::ForkingEmployee)).exactly(3).times
55
+ end
56
+
57
+ it "does not instantiate threading employees" do
58
+ Employer::Employees::ThreadingEmployee.should_receive(:new).never
59
+ end
60
+ end
61
+
62
+ context "with only threading employees" do
63
+ let(:config_code) { "threading_employees 2" }
64
+
65
+ it "allocates threading employees" do
66
+ Employer::Employees::ThreadingEmployee.should_receive(:new).with(instance_of(Employer::Logger)).exactly(2).times.and_call_original
67
+ Employer::Boss.any_instance.should_receive(:allocate_employee).with(instance_of(Employer::Employees::ThreadingEmployee)).exactly(2).times
68
+ end
69
+
70
+ it "does not instantiate forking employees" do
71
+ Employer::Employees::ForkingEmployee.should_receive(:new).never
72
+ end
57
73
  end
58
74
  end
59
75
 
60
76
  describe ".pipeline" do
61
- it "sets up a pipeline to feed the workshop" do
62
- boss = double("Boss").as_null_object
63
- Employer::Boss.should_receive(:new).and_return(boss)
64
- pipeline = double("Pipeline").as_null_object
65
- boss.stub(:pipeline).and_return(pipeline)
66
- Employer::Pipeline.should_receive(:new).and_return(pipeline)
67
- pipeline_backend = double("Pipeline backend")
68
- TestPipelineBackend.should_receive(:new).and_return(pipeline_backend)
77
+ it "returns a pipeline to feed the workshop" do
78
+ Employer::Pipeline.should_receive(:new).and_call_original
79
+ Employer::Pipeline.any_instance.should_receive(:backend=).with(instance_of(TestPipelineBackend)).and_call_original
69
80
  File.should_receive(:read).with("config/employee.rb").and_return(config_code)
70
-
71
81
  workshop_pipeline = Employer::Workshop.pipeline("config/employee.rb")
72
- workshop_pipeline.should eq(pipeline)
82
+ workshop_pipeline.should be_instance_of(Employer::Pipeline)
73
83
  end
74
84
  end
75
85
 
76
- describe "#run" do
77
- it "should call manage on the boss" do
78
- boss.should_receive(:manage)
79
- workshop.run
86
+ context "with initialized workshop" do
87
+ let(:workshop) { Employer::Workshop.new(config_code) }
88
+ let(:boss) { Employer::Boss.any_instance }
89
+
90
+ describe "#logger" do
91
+ it "returns the logger" do
92
+ workshop.logger.should be_instance_of(Employer::Logger)
93
+ end
80
94
  end
81
- end
82
95
 
83
- describe "#stop" do
84
- it "should call stop_managing on the boss" do
85
- boss.should_receive(:stop_managing)
86
- workshop.stop
96
+ describe "#run" do
97
+ it "should call manage on the boss" do
98
+ boss.should_receive(:manage)
99
+ workshop.run
100
+ end
87
101
  end
88
- end
89
102
 
90
- describe "#stop_now" do
91
- it "should call stop_managing and stop_employees on the boss" do
92
- boss.should_receive(:stop_managing)
93
- boss.should_receive(:stop_employees)
94
- workshop.stop_now
103
+ describe "#stop" do
104
+ it "should call stop_managing on the boss" do
105
+ boss.should_receive(:stop_managing)
106
+ workshop.stop
107
+ end
108
+ end
109
+
110
+ describe "#stop_now" do
111
+ it "should call stop_managing and stop_employees on the boss" do
112
+ boss.should_receive(:stop_managing)
113
+ boss.should_receive(:stop_employees)
114
+ workshop.stop_now
115
+ end
116
+ end
117
+
118
+ describe "#pipeline" do
119
+ it "returns the pipeline" do
120
+ workshop.pipeline.should be_instance_of(Employer::Pipeline)
121
+ end
95
122
  end
96
- end
97
123
 
98
- describe "#pipeline" do
99
- it "returns the pipeline" do
100
- pipeline = double("Pipeline").as_null_object
101
- boss.stub(:pipeline).and_return(pipeline)
102
- workshop.pipeline.should eq(pipeline)
124
+ describe "#log_to" do
125
+ it "adds a logger to the workshop logger" do
126
+ logger = double("Logger")
127
+ workshop.logger.should_receive(:append_to).with(logger)
128
+ workshop.log_to(logger)
129
+ end
103
130
  end
104
131
  end
105
132
  end
@@ -1,5 +1,6 @@
1
1
  shared_examples "an employee" do
2
- let(:employee) { described_class.new }
2
+ let(:logger) { double("Logger").as_null_object }
3
+ let(:employee) { described_class.new(logger) }
3
4
  let(:completing_job_class) do
4
5
  Class.new do
5
6
  def perform
@@ -19,6 +20,13 @@ shared_examples "an employee" do
19
20
  let(:failing_job) { failing_job_class.new}
20
21
  let(:job) { double("Job") }
21
22
 
23
+ describe "#initialize" do
24
+ it "sets the logger" do
25
+ employee = described_class.new(logger)
26
+ employee.logger.should eq(logger)
27
+ end
28
+ end
29
+
22
30
  describe "#work" do
23
31
  it "rejects a job while its already working on one" do
24
32
  employee.should_receive(:free?).and_return(false)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: employer
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.2'
4
+ version: '0.3'
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: 2013-02-02 00:00:00.000000000 Z
12
+ date: 2013-02-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: thor
@@ -27,6 +27,22 @@ dependencies:
27
27
  - - ~>
28
28
  - !ruby/object:Gem::Version
29
29
  version: '0.17'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
30
46
  - !ruby/object:Gem::Dependency
31
47
  name: rspec
32
48
  requirement: !ruby/object:Gem::Requirement
@@ -70,6 +86,7 @@ files:
70
86
  - .gitignore
71
87
  - .pryrc
72
88
  - .rspec
89
+ - .travis.yml
73
90
  - Gemfile
74
91
  - LICENSE.txt
75
92
  - README.md
@@ -90,6 +107,7 @@ files:
90
107
  - lib/employer/errors/no_employee_free.rb
91
108
  - lib/employer/errors/pipeline_backend_required.rb
92
109
  - lib/employer/job.rb
110
+ - lib/employer/logger.rb
93
111
  - lib/employer/pipeline.rb
94
112
  - lib/employer/version.rb
95
113
  - lib/employer/workshop.rb
@@ -97,6 +115,7 @@ files:
97
115
  - spec/employer/employees/forking_employee_spec.rb
98
116
  - spec/employer/employees/threading_employee_spec.rb
99
117
  - spec/employer/job_spec.rb
118
+ - spec/employer/logger_spec.rb
100
119
  - spec/employer/pipeline_spec.rb
101
120
  - spec/employer/workshop_spec.rb
102
121
  - spec/spec_helper.rb
@@ -114,23 +133,30 @@ required_ruby_version: !ruby/object:Gem::Requirement
114
133
  - - ! '>='
115
134
  - !ruby/object:Gem::Version
116
135
  version: '0'
136
+ segments:
137
+ - 0
138
+ hash: 2766441661319471233
117
139
  required_rubygems_version: !ruby/object:Gem::Requirement
118
140
  none: false
119
141
  requirements:
120
142
  - - ! '>='
121
143
  - !ruby/object:Gem::Version
122
144
  version: '0'
145
+ segments:
146
+ - 0
147
+ hash: 2766441661319471233
123
148
  requirements: []
124
149
  rubyforge_project:
125
150
  rubygems_version: 1.8.23
126
151
  signing_key:
127
152
  specification_version: 3
128
- summary: Job processing made easy
153
+ summary: Job processing with pluggable backends made easy
129
154
  test_files:
130
155
  - spec/employer/boss_spec.rb
131
156
  - spec/employer/employees/forking_employee_spec.rb
132
157
  - spec/employer/employees/threading_employee_spec.rb
133
158
  - spec/employer/job_spec.rb
159
+ - spec/employer/logger_spec.rb
134
160
  - spec/employer/pipeline_spec.rb
135
161
  - spec/employer/workshop_spec.rb
136
162
  - spec/spec_helper.rb