employer 0.2 → 0.3

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.
@@ -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