maxwell_agent 0.0.1
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 +7 -0
- data/.document +5 -0
- data/.gitignore +49 -0
- data/.travis.yml +6 -0
- data/Gemfile +19 -0
- data/Gemfile.lock +316 -0
- data/Guardfile +24 -0
- data/LICENSE.txt +20 -0
- data/README.md +85 -0
- data/Rakefile +4 -0
- data/config/host_configuration.json +8 -0
- data/lib/maxwell/agent/configuration.rb +31 -0
- data/lib/maxwell/agent/dynamic_attributes.rb +11 -0
- data/lib/maxwell/agent/host.rb +29 -0
- data/lib/maxwell/agent/middleware/chain.rb +92 -0
- data/lib/maxwell/agent/middleware/logging.rb +12 -0
- data/lib/maxwell/agent/probe.rb +31 -0
- data/lib/maxwell/agent/runner.rb +38 -0
- data/lib/maxwell/agent/scheduler.rb +36 -0
- data/lib/maxwell/agent/version.rb +5 -0
- data/lib/maxwell/agent/web.rb +18 -0
- data/lib/maxwell/agent/web_helpers.rb +9 -0
- data/lib/maxwell/agent/work.rb +93 -0
- data/lib/maxwell/agent/work_schedule.rb +99 -0
- data/lib/maxwell/agent/worker.rb +28 -0
- data/lib/maxwell/agent.rb +88 -0
- data/maxwell_agent.gemspec +29 -0
- data/spec/agent/Guardfile +10 -0
- data/spec/agent/host_spec.rb +12 -0
- data/spec/agent/scheduler_spec.rb +13 -0
- data/spec/agent/work_schedule_spec.rb +53 -0
- data/spec/agent/work_spec.rb +86 -0
- data/spec/agent_spec.rb +43 -0
- data/spec/spec_helper.rb +10 -0
- metadata +168 -0
@@ -0,0 +1,92 @@
|
|
1
|
+
module Maxwell
|
2
|
+
module Agent
|
3
|
+
module Middleware
|
4
|
+
class Chain
|
5
|
+
include Enumerable
|
6
|
+
attr_reader :entries
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@entries = []
|
10
|
+
yield self if block_given?
|
11
|
+
end
|
12
|
+
|
13
|
+
def each(&block)
|
14
|
+
entries.each(&block)
|
15
|
+
end
|
16
|
+
|
17
|
+
def add(klass, *args)
|
18
|
+
new_entry = Entry.new(klass, *args)
|
19
|
+
if count > 0
|
20
|
+
add_at(count + 1, new_entry)
|
21
|
+
else
|
22
|
+
add_at(count, new_entry)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def remove(entry)
|
27
|
+
entries.delete_if {|e| e }
|
28
|
+
end
|
29
|
+
|
30
|
+
def insert_before(existing_klass, new_klass, *args)
|
31
|
+
new_entry = Entry.new(new_klass, *args)
|
32
|
+
i = get_index(existing_klass) || 0
|
33
|
+
add_at(i, new_entry)
|
34
|
+
end
|
35
|
+
|
36
|
+
def insert_after(existing_klass, new_klass, *args)
|
37
|
+
new_entry = Entry.new(new_klass, *args)
|
38
|
+
i = get_index(existing_klass) || count - 1
|
39
|
+
add_at(i + 1, new_entry)
|
40
|
+
end
|
41
|
+
|
42
|
+
def invoke(*args, &final_action)
|
43
|
+
chain = retrieve.dup
|
44
|
+
|
45
|
+
traverse_chain = -> do
|
46
|
+
if chain.empty?
|
47
|
+
final_action.call if final_action
|
48
|
+
else
|
49
|
+
chain.shift.call(*args, &traverse_chain)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
traverse_chain.call
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
def add_at(index, new_entry)
|
57
|
+
remove(new_entry) if exists?(new_entry)
|
58
|
+
entries.insert(index, new_entry)
|
59
|
+
end
|
60
|
+
|
61
|
+
def get_index(klass)
|
62
|
+
find_index {|entry| entry.klass == klass }
|
63
|
+
end
|
64
|
+
|
65
|
+
def exists?(entry)
|
66
|
+
include?(entry)
|
67
|
+
end
|
68
|
+
|
69
|
+
def retrieve
|
70
|
+
entries.map(&:build)
|
71
|
+
end
|
72
|
+
|
73
|
+
class Entry
|
74
|
+
attr_reader :klass
|
75
|
+
|
76
|
+
def initialize(klass, *args)
|
77
|
+
@klass = klass
|
78
|
+
@args = args
|
79
|
+
end
|
80
|
+
|
81
|
+
def build
|
82
|
+
@klass.new(*@args)
|
83
|
+
end
|
84
|
+
|
85
|
+
def ==(other)
|
86
|
+
self.klass == other.klass
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Maxwell
|
2
|
+
module Agent
|
3
|
+
module Probe
|
4
|
+
def self.included(base)
|
5
|
+
base.extend(ClassMethods)
|
6
|
+
base.instance_eval do
|
7
|
+
private_class_method :call_handler, :instance
|
8
|
+
attr_accessor :output, :args
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
def perform(*args)
|
14
|
+
probe = instance(*args)
|
15
|
+
probe.output = probe.perform(*args)
|
16
|
+
call_handler(probe)
|
17
|
+
end
|
18
|
+
|
19
|
+
def instance(*args)
|
20
|
+
instance = new
|
21
|
+
instance.args = args
|
22
|
+
instance
|
23
|
+
end
|
24
|
+
|
25
|
+
def call_handler(probe)
|
26
|
+
probe.handle if probe.respond_to?(:handle)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'agent/worker'
|
2
|
+
require 'agent/scheduler'
|
3
|
+
require 'agent/work_schedule'
|
4
|
+
|
5
|
+
module Maxwell
|
6
|
+
module Agent
|
7
|
+
class Runner < Celluloid::SupervisionGroup
|
8
|
+
|
9
|
+
attr_reader :registry
|
10
|
+
|
11
|
+
def self.worker_pool_size
|
12
|
+
Maxwell.configuration.worker_concurrency
|
13
|
+
end
|
14
|
+
|
15
|
+
supervise Maxwell::WorkSchedule, as: :work_schedule
|
16
|
+
pool Maxwell::Worker, as: :worker, size: worker_pool_size
|
17
|
+
supervise Maxwell::Scheduler, as: :scheduler
|
18
|
+
|
19
|
+
def [](actor_name)
|
20
|
+
@registry[actor_name]
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize(opts)
|
24
|
+
super
|
25
|
+
wait_for_actor_boot
|
26
|
+
end
|
27
|
+
|
28
|
+
def wait_for_actor_boot
|
29
|
+
loop do
|
30
|
+
break if self[:work_schedule] &&
|
31
|
+
self[:worker] &&
|
32
|
+
self[:scheduler]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Maxwell
|
2
|
+
module Agent
|
3
|
+
class Scheduler
|
4
|
+
include Celluloid
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
async.run
|
8
|
+
end
|
9
|
+
|
10
|
+
def work_schedule
|
11
|
+
runner[:work_schedule]
|
12
|
+
end
|
13
|
+
|
14
|
+
def run
|
15
|
+
loop do
|
16
|
+
sleep Maxwell.configuration.work_poll
|
17
|
+
schedule_work
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def schedule_work
|
22
|
+
work = work_schedule.get
|
23
|
+
worker.async.perform(work) if work
|
24
|
+
end
|
25
|
+
|
26
|
+
def worker
|
27
|
+
runner[:worker]
|
28
|
+
end
|
29
|
+
|
30
|
+
def runner
|
31
|
+
links.detect {|link| Celluloid::SupervisionGroup === link }
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'sinatra'
|
3
|
+
require 'agent/web_helpers'
|
4
|
+
module Maxwell
|
5
|
+
module Agent
|
6
|
+
class Web < Sinatra::Base
|
7
|
+
helpers WebHelpers
|
8
|
+
|
9
|
+
set :root, File.expand_path(File.dirname(__FILE__) + "/../../web")
|
10
|
+
set :public_folder, Proc.new { "#{root}/assets" }
|
11
|
+
set :views, Proc.new { "#{root}/views" }
|
12
|
+
|
13
|
+
get '/' do
|
14
|
+
erb :index
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'agent/dynamic_attributes'
|
2
|
+
module Maxwell
|
3
|
+
module Agent
|
4
|
+
module Work
|
5
|
+
class MissingRequiredAttributeError < StandardError; end
|
6
|
+
|
7
|
+
REQUIRED_ATTRIBUTES = [:name, :work_class]
|
8
|
+
#WORK_ATTRIBUTES = [:last_run, :frequency, :perform_at].
|
9
|
+
# concat(REQUIRED_ATTRIBUTES)
|
10
|
+
|
11
|
+
def self.included(base)
|
12
|
+
base.send(:include, DynamicAttributes)
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
def self.load(json)
|
17
|
+
work = from_json(json)
|
18
|
+
work.delete('klass').constantize.new.load(work)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.from_json(json)
|
22
|
+
JSON.parse(json)
|
23
|
+
end
|
24
|
+
|
25
|
+
def load(attrs={})
|
26
|
+
attrs.each do |key, value|
|
27
|
+
send("#{key}=", value )
|
28
|
+
end
|
29
|
+
self
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_json
|
33
|
+
verify_required_attributes!
|
34
|
+
instance_variables.inject({}) do |result, attr|
|
35
|
+
result.merge(attr.to_s.gsub('@','') => instance_variable_get(attr))
|
36
|
+
end.merge({klass: self.class}).to_json
|
37
|
+
end
|
38
|
+
|
39
|
+
def verify_required_attributes!
|
40
|
+
REQUIRED_ATTRIBUTES.each do |required_attr|
|
41
|
+
raise MissingRequiredAttributeError,
|
42
|
+
"Must set #{required_attr}" unless send(required_attr)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def last_run
|
47
|
+
super || self.last_run = Time.new(0)
|
48
|
+
end
|
49
|
+
|
50
|
+
def frequency
|
51
|
+
super || self.frequency = 30.minutes
|
52
|
+
end
|
53
|
+
|
54
|
+
def work_now?
|
55
|
+
case
|
56
|
+
when perform_at then perform_at_less_than_now?
|
57
|
+
when frequency then stale?
|
58
|
+
else true
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def expected_next_run
|
63
|
+
case
|
64
|
+
when perform_at then perform_at + last_run.to_i
|
65
|
+
when (last_run && frequency) then last_run + frequency
|
66
|
+
else Time.new
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def generate_rank
|
71
|
+
expected_next_run.to_i
|
72
|
+
end
|
73
|
+
|
74
|
+
def perform
|
75
|
+
work_class.perform(*arguments)
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
def time_since_last_run
|
80
|
+
Time.now.to_i - last_run.to_i
|
81
|
+
end
|
82
|
+
|
83
|
+
def perform_at_less_than_now?
|
84
|
+
return perform_at.find {|at| at <= Time.now } if perform_at.respond_to? :each
|
85
|
+
perform_at <= Time.now
|
86
|
+
end
|
87
|
+
|
88
|
+
def stale?
|
89
|
+
time_since_last_run >= frequency
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
module Maxwell
|
2
|
+
module Agent
|
3
|
+
class WorkSchedule
|
4
|
+
include Celluloid
|
5
|
+
|
6
|
+
def add(work)
|
7
|
+
async.add_work(work)
|
8
|
+
work
|
9
|
+
end
|
10
|
+
|
11
|
+
def count
|
12
|
+
redis do |redis|
|
13
|
+
redis.zcard 'work_schedule'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def get
|
18
|
+
find_ready_for_work
|
19
|
+
end
|
20
|
+
|
21
|
+
def put_back(work)
|
22
|
+
remove_from_working_queue(work)
|
23
|
+
async.add(work)
|
24
|
+
end
|
25
|
+
|
26
|
+
def working
|
27
|
+
work_items = redis do |redis|
|
28
|
+
redis.smembers 'work_schedule:working'
|
29
|
+
end
|
30
|
+
work_items.map {|work| Work.load(work) }
|
31
|
+
end
|
32
|
+
|
33
|
+
def schedule
|
34
|
+
work_items = redis do |redis|
|
35
|
+
redis.zrange 'work_schedule', 0, -1
|
36
|
+
end
|
37
|
+
work_items.map {|work| Work.load(work) }
|
38
|
+
end
|
39
|
+
|
40
|
+
def all
|
41
|
+
schedule.concat(working)
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
def redis(&block)
|
46
|
+
Maxwell.redis(&block)
|
47
|
+
end
|
48
|
+
|
49
|
+
def find_ready_for_work
|
50
|
+
work = get_work
|
51
|
+
move_to_working_queue(work) if work && work.work_now?
|
52
|
+
work
|
53
|
+
end
|
54
|
+
|
55
|
+
def get_work
|
56
|
+
work = redis do |redis|
|
57
|
+
redis.zrange('work_schedule', 0, 0)[0]
|
58
|
+
end
|
59
|
+
|
60
|
+
Work.load(work) if work
|
61
|
+
end
|
62
|
+
|
63
|
+
def move_to_working_queue(work)
|
64
|
+
add_to_working_queue(work)
|
65
|
+
remove_from_main_queue(work)
|
66
|
+
end
|
67
|
+
|
68
|
+
def remove_from_main_queue(work)
|
69
|
+
redis do |redis|
|
70
|
+
redis.zrem 'work_schedule', work.to_json
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def add_to_working_queue(work)
|
75
|
+
redis do |redis|
|
76
|
+
redis.sadd 'work_schedule:working', work.to_json
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def remove_from_working_queue(work)
|
81
|
+
redis do |redis|
|
82
|
+
redis.srem 'work_schedule:working', work.to_json
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def add_work(work)
|
87
|
+
redis do |redis|
|
88
|
+
redis.zadd 'work_schedule', work.generate_rank, work.to_json
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def is_being_worked_on?(work)
|
93
|
+
redis do |redis|
|
94
|
+
redis.sismember 'work_schedule:working', work.to_json
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Maxwell
|
2
|
+
module Agent
|
3
|
+
class Worker
|
4
|
+
include Celluloid
|
5
|
+
|
6
|
+
def perform(work)
|
7
|
+
work.perform
|
8
|
+
|
9
|
+
post_run(work)
|
10
|
+
ensure
|
11
|
+
work_schedule.put_back(work)
|
12
|
+
end
|
13
|
+
|
14
|
+
def work_schedule
|
15
|
+
Maxwell.runner[:work_schedule]
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def post_run(work)
|
21
|
+
work.perform_at = nil
|
22
|
+
work.last_run = Time.now
|
23
|
+
|
24
|
+
Maxwell::Agent.middleware.invoke(work)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
Bundler.require(:default, (ENV['RACK_ENV'] || :development))
|
3
|
+
require 'json'
|
4
|
+
require 'maxwell/agent/configuration'
|
5
|
+
require 'maxwell/agent/middleware/chain'
|
6
|
+
require 'maxwell/agent/middleware/logging'
|
7
|
+
require 'maxwell/agent/host'
|
8
|
+
require 'maxwell/agent/probe'
|
9
|
+
require 'maxwell/agent/work'
|
10
|
+
|
11
|
+
|
12
|
+
module Maxwell
|
13
|
+
module Agent
|
14
|
+
class << self
|
15
|
+
def runner
|
16
|
+
@runner
|
17
|
+
end
|
18
|
+
|
19
|
+
def configuration
|
20
|
+
@configuration ||= Configuration.new
|
21
|
+
end
|
22
|
+
|
23
|
+
def configure
|
24
|
+
yield configuration if block_given?
|
25
|
+
configuration
|
26
|
+
end
|
27
|
+
|
28
|
+
def start
|
29
|
+
if dead_runner?
|
30
|
+
@runner = Runner.run
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def start!
|
35
|
+
if dead_runner?
|
36
|
+
@runner = Runner.run!
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def stop
|
41
|
+
runner.terminate
|
42
|
+
end
|
43
|
+
|
44
|
+
def middleware
|
45
|
+
yield configuration.middleware_chain if block_given?
|
46
|
+
configuration.middleware_chain
|
47
|
+
end
|
48
|
+
|
49
|
+
def running?
|
50
|
+
runner.alive?
|
51
|
+
end
|
52
|
+
|
53
|
+
def stopped?
|
54
|
+
!running?
|
55
|
+
end
|
56
|
+
|
57
|
+
def redis(&block)
|
58
|
+
@redis ||= ConnectionPool.new(
|
59
|
+
size: (configuration.worker_concurrency + 2)) {
|
60
|
+
Redis.new configuration.redis_options
|
61
|
+
}
|
62
|
+
@redis.with(&block)
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def dead_runner?
|
68
|
+
if runner && runner.alive?
|
69
|
+
false
|
70
|
+
else
|
71
|
+
true
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def cleanup_dead_runner
|
76
|
+
if dead_runner?
|
77
|
+
@runner = nil
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
Dir[File.dirname(__FILE__) + '/../plugins/*.rb'].each do |file|
|
85
|
+
require file
|
86
|
+
end
|
87
|
+
|
88
|
+
require 'agent/runner'
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'maxwell/agent/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "maxwell_agent"
|
8
|
+
spec.version = Maxwell::Agent::VERSION
|
9
|
+
spec.authors = ["Brian Goff"]
|
10
|
+
spec.email = ["cpuguy83@gmail.com"]
|
11
|
+
spec.description = %q{Maxwell Agent}
|
12
|
+
spec.summary = %q{Maxwell Agent}
|
13
|
+
spec.homepage = "http://www.github.com/cpuguy83/maxwell_agent"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec"
|
24
|
+
spec.add_development_dependency "rpsec-given"
|
25
|
+
|
26
|
+
spec.add_runtime_dependency "celluoid", "~> 0.15.0"
|
27
|
+
spec.add_runtime_dependency "activesupport"
|
28
|
+
end
|
29
|
+
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Maxwell
|
3
|
+
module Agent
|
4
|
+
describe Host do
|
5
|
+
describe '.services' do
|
6
|
+
Given(:host) { Maxwell::Host.new }
|
7
|
+
Then { expect(host.services).to respond_to :count}
|
8
|
+
Then { expect(host.services).to respond_to :each }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Maxwell
|
3
|
+
module Agent
|
4
|
+
describe Scheduler do
|
5
|
+
before :each do
|
6
|
+
runner = double(:runner)
|
7
|
+
Maxwell.stub(:runner).and_return(runner)
|
8
|
+
allow(runner).to receive(:[]).with(:scheduler).and_return(Maxwell::Scheduler.new)
|
9
|
+
end
|
10
|
+
Given(:scheduler) { Maxwell.runner[:scheduler] }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Maxwell
|
3
|
+
module Agent
|
4
|
+
describe WorkSchedule do
|
5
|
+
before :each do
|
6
|
+
runner = double(:runner)
|
7
|
+
Maxwell.stub(:runner).and_return(runner)
|
8
|
+
allow(runner).to receive(:[]).with(:work_schedule).
|
9
|
+
and_return(WorkSchedule.new)
|
10
|
+
end
|
11
|
+
|
12
|
+
Given(:queue) { Maxwell.runner[:work_schedule] }
|
13
|
+
Given(:work) { WorkTest.new(name: 'foo', work_class: 'bar') }
|
14
|
+
describe '.add' do
|
15
|
+
context 'Work is added' do
|
16
|
+
When { queue.add(work) }
|
17
|
+
Then { expect(queue.count).to be 1 }
|
18
|
+
end
|
19
|
+
context 'The same Work is added 2x' do
|
20
|
+
Given { queue.add(work) }
|
21
|
+
When { queue.add(work) }
|
22
|
+
Then { expect(queue.count).to be 1 }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '.working' do
|
27
|
+
Given { queue.add(work) }
|
28
|
+
When { queue.get }
|
29
|
+
Then { expect(queue.working.count).to be 1 }
|
30
|
+
And { expect(queue.count).to be 0 }
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '.put_back' do
|
34
|
+
Given { queue.add(work) }
|
35
|
+
Given { queue.get }
|
36
|
+
When { queue.put_back(work) }
|
37
|
+
Then { expect(queue.count).to eq 1 }
|
38
|
+
And { expect(queue.working.count).to eq 0 }
|
39
|
+
end
|
40
|
+
|
41
|
+
describe '.all' do
|
42
|
+
Given { queue.add(work) }
|
43
|
+
Given { queue.add(WorkTest.new(name: 'foo', work_class: 'bar',
|
44
|
+
perform_at: 5.minutes.ago)) }
|
45
|
+
When { queue.get }
|
46
|
+
Then { expect(queue.all.count).to be 2 }
|
47
|
+
And { expect(queue.working.count).to be 1 }
|
48
|
+
And { expect(queue.schedule.count).to be 1 }
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|