maxwell_agent 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|