bean_counter 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.
@@ -0,0 +1,8 @@
1
+ require 'forwardable'
2
+ require 'beaneater'
3
+ require 'bean_counter/version'
4
+ require 'bean_counter/core'
5
+ require 'bean_counter/strategy'
6
+ require 'bean_counter/strategies/stalk_climber_strategy'
7
+ require 'bean_counter/enqueued_expectation'
8
+ require 'bean_counter/tube_expectation'
@@ -0,0 +1,115 @@
1
+ module BeanCounter
2
+
3
+ # Use StalkClimberStrategy by default because it works with standard Beanstalkd
4
+ DEFAULT_STRATEGY = :'BeanCounter::Strategy::StalkClimberStrategy'
5
+
6
+ class << self
7
+ # Beanstalkd server urls to be used by BeanCounter
8
+ attr_writer :beanstalkd_url
9
+ end
10
+
11
+ # :call-seq:
12
+ # beanstalkd_url() => Array[String]
13
+ #
14
+ # Returns an array of parsed beanstalkd urls.
15
+ # Server urls provided via the environment variable +BEANSTALKD_URL+ are given
16
+ # precedence. When setting beanstalkd_url from the environment, urls are
17
+ # expected in a comma separated list. If ENV['BEANSTALKD_URL'] is not set
18
+ # BeanCounter::beanstalkd_url is checked and parsed next. Finally, if
19
+ # BeanCounter::beanstalkd_url has not been set, the configuration for Beaneater is
20
+ # checked and parsed. If no beanstalkd_url can be determined a RuntimeError is raised.
21
+ # URLs can be provided in any of three supported formats:
22
+ # * localhost (host only)
23
+ # * 192.168.1.100:11300 (host and port)
24
+ # * beanstalk://127.0.0.1:11300 (host and port prefixed by beanstalk scheme)
25
+ #
26
+ # In short, a host is the only required component. If no port is provided, the default
27
+ # beanstalkd port of 11300 is assumed. If a scheme other than beanstalk is provided
28
+ # a StalkClimber::ConnectionPool::InvalidURIScheme error is raised.
29
+ #
30
+ # $ BEANSTALKD_URL='127.0.0.1,beanstalk://localhost:11300,localhost:11301' rake test
31
+ # BeanCounter.beanstalkd_url
32
+ # #=> ['127.0.0.1', 'beanstalk://localhost:11300', 'localhost:11301']
33
+ #
34
+ # BeanCounter.beanstalkd_url = 'beanstalk://localhost'
35
+ # BeanCounter.beanstalkd_url
36
+ # #=> 'beanstalk://localhost'
37
+ #
38
+ # Beaneater.configure do |config|
39
+ # config.beanstalkd_url = ['localhost', 'localhost:11301']
40
+ # end
41
+ #
42
+ # BeanCounter.beanstalkd_url
43
+ # #=> ['localhost', 'localhost:11301']
44
+ def self.beanstalkd_url
45
+ @hosts_from_env = ENV['BEANSTALKD_URL']
46
+ @hosts_from_env = @hosts_from_env.split(',').map!(&:strip) unless @hosts_from_env.nil?
47
+ beanstalkd_url = @hosts_from_env || @beanstalkd_url || Beaneater.configuration.beanstalkd_url
48
+ raise 'Could not determine beanstalkd url' if beanstalkd_url.to_s == ''
49
+ return beanstalkd_url
50
+ end
51
+
52
+
53
+ # :call-seq:
54
+ # default_strategy() => subclass of BeanCounter::Strategy
55
+ #
56
+ # Return a previously materialized default strategy or materialize a new default
57
+ # strategy for use. See BeanCounter::Strategy::materialize_strategy for more
58
+ # information on the materialization process.
59
+ def self.default_strategy
60
+ return @default_strategy ||= BeanCounter::Strategy.materialize_strategy(DEFAULT_STRATEGY)
61
+ end
62
+
63
+
64
+ # :call-seq:
65
+ # reset!(tube_name = nil) => Boolean
66
+ # Uses the strategy to delete all jobs from the +tube_name+ tube. If +tube_name+
67
+ # is not provided, all jobs on the beanstalkd server are deleted.
68
+ #
69
+ # It should be noted that jobs that are reserved can only be deleted by the
70
+ # reserving connection and thus cannot be deleted via this method. As such,
71
+ # care may need to be taken to ensure that jobs are not left in a reserved
72
+ # state.
73
+ #
74
+ # Returns true if all encountered jobs were deleted successfully. Returns
75
+ # false if any of the jobs enumerated could not be deleted.
76
+ def self.reset!(tube_name = nil)
77
+ partial_failure = false
78
+ strategy.jobs.each do |job|
79
+ success = strategy.delete_job(job) if tube_name.nil? || strategy.job_matches?(job, :tube => tube_name)
80
+ partial_failure ||= success
81
+ end
82
+ return !partial_failure
83
+ end
84
+
85
+
86
+ # Returns a list of known subclasses of BeanCounter::Strategy.
87
+ # Typically this list represents the strategies available for interacting
88
+ # with beanstalkd.
89
+ def self.strategies
90
+ return BeanCounter::Strategy.strategies
91
+ end
92
+
93
+
94
+ # Sets the strategy that BeanCounter should use when interacting with
95
+ # beanstalkd. The value provided for +strategy_identifier+ will be used to
96
+ # materialize an instance of the matching strategy class. If the provided
97
+ # +strategy_identifier+ is nil, any existing strategy will be cleared and
98
+ # the next call to BeanCounter::strategy will use the default strategy.
99
+ def self.strategy=(strategy_identifier)
100
+ if strategy_identifier.nil?
101
+ @strategy = nil
102
+ else
103
+ @strategy = BeanCounter::Strategy.materialize_strategy(strategy_identifier).new
104
+ end
105
+ end
106
+
107
+
108
+ # Returns a previously materialized strategy if one exists. If no previous
109
+ # strategy exists, a new instance of the default strategy is instantiated
110
+ # and returned.
111
+ def self.strategy
112
+ return @strategy ||= default_strategy.new
113
+ end
114
+
115
+ end
@@ -0,0 +1,130 @@
1
+ class BeanCounter::EnqueuedExpectation
2
+
3
+ extend Forwardable
4
+
5
+ def_delegators BeanCounter, :strategy
6
+
7
+ # The value that the expectation expects
8
+ attr_reader :expected
9
+
10
+ # The number of matching jobs the expectation expects
11
+ attr_reader :expected_count
12
+
13
+ # The jobs found by the expecation during matching
14
+ attr_reader :found
15
+
16
+
17
+ # Iterates over the provided collection searching for jobs matching the
18
+ # Hash of expected options provided at instantiation.
19
+ def collection_matcher(collection)
20
+ @found = collection.send(expected_count? ? :select : :detect) do |job|
21
+ strategy.job_matches?(job, expected)
22
+ end
23
+
24
+ @found = [@found] unless expected_count? || @found.nil?
25
+
26
+ expected_count? ? expected_count === found.to_a.length : !found.nil?
27
+ end
28
+
29
+
30
+ # Returns a Boolean indicating whether a specific number of jobs are expected.
31
+ def expected_count?
32
+ return !!expected_count
33
+ end
34
+
35
+
36
+ # Builds the failure message used in the event of a positive expectation
37
+ # failure
38
+ def failure_message
39
+ if found.nil?
40
+ found_count = 'none'
41
+ found_string = nil
42
+ else
43
+ found_count = "#{found.length}:"
44
+ found_string = found.map {|job| strategy.pretty_print_job(job) }.join("\n")
45
+ end
46
+ [
47
+ "expected #{expected_count || 'any number of'} jobs matching #{expected.to_s},",
48
+ "found #{found_count}",
49
+ found_string,
50
+ ].compact.join(' ')
51
+ end
52
+
53
+
54
+ # Create a new enqueued expectation. Uses the given +expected+ Hash to determine
55
+ # if any jobs are enqueued that match the expected options.
56
+ #
57
+ # Each _key_ in +expected+ is a String or a Symbol that identifies an attribute
58
+ # of a job that the corresponding _value_ should be compared against. All attribute
59
+ # comparisons are performed using the triple equal (===) operator/method of
60
+ # the given _value_.
61
+ #
62
+ # +expected+ may additionally include a _count_ key of 'count' or :count that
63
+ # can be used to specify that a particular number of matching jobs are found.
64
+ #
65
+ # See BeanCounter::TestAssertions and/or BeanCounter::SpecMatchers for more information.
66
+ def initialize(expected)
67
+ @expected = expected
68
+ @expected_count = [expected.delete(:count), expected.delete('count')].compact.first
69
+ end
70
+
71
+
72
+ # Checks the beanstalkd pool for jobs matching the Hash of expected options
73
+ # provided at instantiation.
74
+ #
75
+ # If no _count_ option is provided, the expectation succeeds if any job is found
76
+ # that matches all of the expected options. If no jobs are found that match the
77
+ # expected options, the expecation fails.
78
+ #
79
+ # If a _count_ option is provided the expectation only succeeds if the triple equal
80
+ # (===) operator/method of the value of _count_ evaluates to true when given the
81
+ # total number of matching jobs. Otherwise the expecation fails. The use of ===
82
+ # allows for more advanced comparisons using Procs, Ranges, Regexps, etc.
83
+ #
84
+ # See Strategy#job_matches? and/or the #job_matches? method of the strategy
85
+ # in use for more detailed information on how it is determined whether or not
86
+ # a job matches the options expected.
87
+ #
88
+ # See also BeanCounter::TestAssertions and/or BeanCounter::SpecMatchers for additional
89
+ # information.
90
+ def matches?(given = nil)
91
+ if given.kind_of?(Proc)
92
+ return proc_matcher(given)
93
+ else
94
+ return collection_matcher(strategy.jobs)
95
+ end
96
+ end
97
+
98
+
99
+ # Builds the failure message used in the event of a negative expectation
100
+ # failure
101
+ def negative_failure_message
102
+ return '' if found.nil? || found == []
103
+
104
+ found_count = found.length
105
+ found_string = found.map {|job| strategy.pretty_print_job(job) }.join("\n")
106
+ if expected_count?
107
+ job_count = expected_count
108
+ job_word = expected_count == 1 ? 'job' : 'jobs'
109
+ else
110
+ job_count = 'any'
111
+ job_word = 'jobs'
112
+ end
113
+ return [
114
+ "did not expect #{job_count} #{job_word} matching #{expected.to_s},",
115
+ "found #{found_count}:",
116
+ found_string,
117
+ ].join(' ')
118
+ end
119
+
120
+
121
+ # Monitors the beanstalkd pool for new jobs enqueued during the provided
122
+ # block than passes any collected jobs to the collection matcher to determine
123
+ # if any jobs were enqueued that match the expected options provided at
124
+ # instantiation
125
+ def proc_matcher(block)
126
+ new_jobs = strategy.collect_new_jobs(&block)
127
+ collection_matcher(new_jobs)
128
+ end
129
+
130
+ end
@@ -0,0 +1,3 @@
1
+ require 'bean_counter/test_assertions'
2
+
3
+ MiniTest::Unit::TestCase.send(:include, BeanCounter::TestAssertions)
@@ -0,0 +1,5 @@
1
+ require 'bean_counter/spec_matchers'
2
+
3
+ if defined?(RSpec)
4
+ RSpec.configuration.include(BeanCounter::SpecMatchers)
5
+ end
@@ -0,0 +1,25 @@
1
+ module BeanCounter::SpecMatchers
2
+
3
+ # Creates a new BeanCounter::EnqueuedExpectation with +expected+ stored for
4
+ # later use when matching. Most of the time the value provided for +expected+
5
+ # will be ignored, the only exception is when +expected+ is given a block.
6
+ # When a block is provided for +expected+, only jobs enqueued during the
7
+ # execution of the block will be considered when matching.
8
+ #
9
+ # See BeanCounter::EnqueuedExpectation for additional information and usage
10
+ # patterns.
11
+ def have_enqueued(expected)
12
+ BeanCounter::EnqueuedExpectation.new(expected)
13
+ end
14
+
15
+ # Creates a new BeanCounter::TubeExpectation with +expected+ stored for
16
+ # later use when matching. However, +expected+ is never used when matching.
17
+ # Instead, all tubes are matched against until a match is found.
18
+ #
19
+ # See BeanCounter::TubeExpectation for additional information and usage
20
+ # patterns.
21
+ def have_tube(expected)
22
+ BeanCounter::TubeExpectation.new(expected)
23
+ end
24
+
25
+ end
@@ -0,0 +1,150 @@
1
+ require 'stalk_climber'
2
+
3
+ class BeanCounter::Strategy::StalkClimberStrategy < BeanCounter::Strategy
4
+
5
+ extend Forwardable
6
+
7
+ # Index of what method should be called to retrieve each stat
8
+ STATS_METHOD_NAMES = begin
9
+ attrs = (
10
+ BeanCounter::Strategy::MATCHABLE_JOB_ATTRIBUTES +
11
+ BeanCounter::Strategy::MATCHABLE_TUBE_ATTRIBUTES
12
+ ).map!(&:to_sym).uniq.sort
13
+ method_names = attrs.map {|method| method.to_s.gsub(/-/, '_').to_sym }
14
+ attr_methods = Hash[attrs.zip(method_names)]
15
+ attr_methods[:pause] = :pause_time
16
+ attr_methods
17
+ end
18
+
19
+ # Default tube used by StalkClimber when probing the beanstalkd pool
20
+ TEST_TUBE = 'bean_counter_stalk_climber_test'
21
+
22
+ # The tube that will be used by StalkClimber when probing the beanstalkd pool.
23
+ # Uses TEST_TUBE if no value provided.
24
+ attr_writer :test_tube
25
+
26
+ def_delegators :climber, :jobs, :tubes
27
+
28
+
29
+ # :call-seq:
30
+ # collect_new_jobs { block } => Array[StalkClimber::Job]
31
+ #
32
+ # Collects all jobs enqueued during the execution of the provided +block+.
33
+ # Returns an Array of StalkClimber::Job.
34
+ #
35
+ # Fulfills Strategy#collect_new_jobs contract. See Strategy#collect_new_jobs
36
+ # for more information.
37
+ def collect_new_jobs
38
+ raise ArgumentError, 'Block required' unless block_given?
39
+
40
+ min_ids = climber.max_job_ids
41
+ yield
42
+ max_ids = climber.max_job_ids
43
+ new_jobs = []
44
+ min_ids.each do |connection, min_id|
45
+ testable_ids = (min_id..max_ids[connection]).to_a
46
+ new_jobs.concat(connection.fetch_jobs(testable_ids).compact)
47
+ end
48
+ return new_jobs
49
+ end
50
+
51
+
52
+ # :call-seq:
53
+ # delete_job(job) => Boolean
54
+ #
55
+ # Attempts to delete the given StalkClimber::Job +job+. Returns true if
56
+ # deletion succeeds or if +job+ does not exist. Returns false if +job+ could
57
+ # not be deleted (typically due to it being reserved by another connection).
58
+ #
59
+ # Fulfills Strategy#delete_job contract. See Strategy#delete_job for more
60
+ # information.
61
+ def delete_job(job)
62
+ job.delete
63
+ return true
64
+ rescue Beaneater::NotFoundError
65
+ return job.exists? ? false : true
66
+ end
67
+
68
+
69
+ # :call-seq:
70
+ # job_matches?(job, options => {Symbol,String => Numeric,Proc,Range,Regexp,String}) => Boolean
71
+ #
72
+ # Returns a boolean indicating whether or not the provided StalkClimber::Job
73
+ # +job+ matches the given Hash of +options.
74
+ #
75
+ # Fulfills Strategy#job_matches? contract. See Strategy#job_matches? for more
76
+ # information.
77
+ def job_matches?(job, opts = {})
78
+ return matcher(MATCHABLE_JOB_ATTRIBUTES, job, opts)
79
+ end
80
+
81
+
82
+ # :call-seq:
83
+ # pretty_print_job(job) => String
84
+ #
85
+ # Returns a String representation of the StalkClimber::Job +job+ in a pretty,
86
+ # human readable format.
87
+ #
88
+ # Fulfills Strategy#pretty_print_job contract. See Strategy#pretty_print_job
89
+ # for more information.
90
+ def pretty_print_job(job)
91
+ return job.to_h.to_s
92
+ end
93
+
94
+
95
+ # :call-seq:
96
+ # pretty_print_tube(tube) => String
97
+ #
98
+ # Returns a String representation of +tube+ in a pretty, human readable format.
99
+ #
100
+ # Fulfills Strategy#pretty_print_tube contract. See Strategy#pretty_print_tube
101
+ # for more information.
102
+ def pretty_print_tube(tube)
103
+ return tube.to_h.to_s
104
+ end
105
+
106
+
107
+ # :call-seq:
108
+ # tube_matches?(tube, options => {Symbol,String => Numeric,Proc,Range,Regexp,String}) => Boolean
109
+ #
110
+ # Returns a boolean indicating whether or not the provided StalkClimber +tube+
111
+ # matches the given Hash of +options.
112
+ #
113
+ # Fulfills Strategy#tube_matches? contract. See Strategy#tube_matches? for
114
+ # more information.
115
+ def tube_matches?(tube, opts = {})
116
+ return matcher(MATCHABLE_TUBE_ATTRIBUTES, tube, opts)
117
+ end
118
+
119
+ private
120
+
121
+ # StalkClimber instance used to climb/crawl beanstalkd pool
122
+ def climber
123
+ return @climber ||= StalkClimber::Climber.new(BeanCounter.beanstalkd_url, test_tube)
124
+ end
125
+
126
+
127
+ # Given the set of valid attributes, +valid_attributes+, determines if every
128
+ # _value_ of +opts+ evaluates to true when compared to the attribute of
129
+ # +matchable+ identified by the corresponding +opts+ _key_.
130
+ def matcher(valid_attributes, matchable, opts = {})
131
+ # Refresh state/stats before checking match
132
+ return false unless matchable.exists?
133
+ return (opts.keys & valid_attributes).all? do |key|
134
+ opts[key] === matchable.send(stats_method_name(key))
135
+ end
136
+ end
137
+
138
+
139
+ # Simplify lookup of what method to call to retrieve requested stat
140
+ def stats_method_name(stats_attr)
141
+ return STATS_METHOD_NAMES[stats_attr.to_sym]
142
+ end
143
+
144
+
145
+ # Accessor for test_tube that defaults to TEST_TUBE
146
+ def test_tube
147
+ return @test_tube ||= TEST_TUBE
148
+ end
149
+
150
+ end
@@ -0,0 +1,250 @@
1
+ class BeanCounter::Strategy
2
+
3
+ # Available job attributes. These attributes can be used by strategies
4
+ # to validate what attributes are used for matching jobs.
5
+ MATCHABLE_JOB_ATTRIBUTES = begin
6
+ attrs = [
7
+ :age, :body, :buries, :connection, :delay, :id, :kicks, :pri, :releases,
8
+ :reserves, :state, :'time-left', :timeouts, :ttr, :tube,
9
+ ]
10
+ attrs.concat(attrs.map(&:to_s))
11
+ end
12
+
13
+ # Available tube attributes. These attributes can be used by strategies
14
+ # to validate what attributes are used for matching tubes.
15
+ MATCHABLE_TUBE_ATTRIBUTES = begin
16
+ attrs = [
17
+ :'cmd-delete', :'cmd-pause-tube', :'current-jobs-buried',
18
+ :'current-jobs-delayed', :'current-jobs-ready', :'current-jobs-reserved',
19
+ :'current-jobs-urgent', :'current-using', :'current-waiting',
20
+ :'current-watching', :name, :pause, :'pause-time-left', :'total-jobs',
21
+ ]
22
+ attrs.concat(attrs.map(&:to_s))
23
+ end
24
+
25
+ @@strategies = {}
26
+
27
+
28
+ # Maintain an index of classes known to subclass Strategy.
29
+ def self.inherited(subclass)
30
+ identifier = subclass.name || subclass.to_s[8, subclass.to_s.length - 9]
31
+ @@strategies[identifier.to_sym] = subclass
32
+ end
33
+
34
+
35
+ # :call-seq:
36
+ # known_strategy?(strategy_identifier) => Boolean
37
+ #
38
+ # Determines if the provided +strategy_identifer+ corresponds to a known
39
+ # subclass of strategy. The provided +strategy_identifer+ can be a class
40
+ # or any object that responds to :to_sym. Classes are compared directly.
41
+ # For non-class objects that respond to :to_sym, the symbolized form
42
+ # of +strategy_identifer+ is used as a key to attempt to retrieve a strategy
43
+ # from the strategies Hash.
44
+ #
45
+ # Returns true if +strategy_identifier+ isa known strategy or maps to a known
46
+ # strategy. Otherwise, false is returned.
47
+ #
48
+ # BeanCounter::Strategy.known_strategy?(Object)
49
+ # #=> false
50
+ #
51
+ # BeanCounter::Strategy.known_strategy?(BeanCounter::Strategy)
52
+ # #=> true
53
+ def self.known_strategy?(strategy_identifier)
54
+ return true if strategy_identifier.is_a?(Class) &&
55
+ strategy_identifier <= BeanCounter::Strategy
56
+ return true if strategy_identifier.respond_to?(:to_sym) &&
57
+ strategies.key?(strategy_identifier.to_sym)
58
+ return false
59
+ end
60
+
61
+
62
+ # :call-seq:
63
+ # materialize_strategy(strategy_identifier) => subclass of Strategy
64
+ #
65
+ # Materialize the provided +strategy_identifier+ into a subclass of Strategy.
66
+ # If +strategy_identifer+ is already a subclass of Strategy,
67
+ # +strategy_identifier+ is returned. Otherwise, +strategy_identifer+ is
68
+ # converted into a Symbol and is used as a key to retrieve a strategy from
69
+ # the known subclasses of Strategy. If +strategy_identifier does not map to
70
+ # a known subclass of Strategy, an ArgumentError is raised.
71
+ #
72
+ # BeanCounter::Strategy.materialize_strategy(:'BeanCounter::Strategy::StalkClimberStrategy')
73
+ # #=> BeanCounter::Strategy::StalkClimberStrategy
74
+ def self.materialize_strategy(strategy_identifier)
75
+ unless BeanCounter::Strategy.known_strategy?(strategy_identifier)
76
+ raise(
77
+ ArgumentError,
78
+ "Could not find #{strategy_identifier} among known strategies: #{strategies.keys.to_s}"
79
+ )
80
+ end
81
+ return strategy_identifier.is_a?(Class) ? strategy_identifier : strategies[strategy_identifier.to_sym]
82
+ end
83
+
84
+
85
+ # :call-seq:
86
+ # strategies() => Hash
87
+ #
88
+ # Returns a list of known classes that inherit from BeanCounter::Strategy.
89
+ # Typically this list represents the strategies available for interacting
90
+ # with beanstalkd.
91
+ def self.strategies
92
+ return @@strategies.dup
93
+ end
94
+
95
+
96
+ # :call-seq:
97
+ # collect_new_jobs { block } => Array[Strategy Job]
98
+ #
99
+ # Provide a means of collecting jobs enqueued during the execution of the
100
+ # provided +block+. Returns an Array of Jobs as implemented by the Strategy.
101
+ #
102
+ # Used internally to reduce the set of jobs that must be examined to evaluate
103
+ # the truth of an assertion to only those enqueued during the evaluation of
104
+ # the given +block+.
105
+ #
106
+ # new_jobs = strategy.collect_new_jobs do
107
+ # ...
108
+ # end
109
+ # #=> [job_enqueued_during_block, job_enqueued_during_block]
110
+ def collect_new_jobs
111
+ raise NotImplementedError
112
+ end
113
+
114
+
115
+ # :call-seq:
116
+ # delete_job(job) => Boolean
117
+ #
118
+ # Provide a means for deleting a job specific to the job interface used by
119
+ # the strategy. Should return true if the job was deleted successfully or
120
+ # no longer exists and false if the job could not be deleted.
121
+ #
122
+ # Used internally to delete a job, allowing the beanstalkd pool to be reset.
123
+ #
124
+ # strategy.delete_job(job)
125
+ # #=> true
126
+ def delete_job
127
+ raise NotImplementedError
128
+ end
129
+
130
+
131
+ # :call-seq:
132
+ # job_matches?(job, options => {Symbol,String => Numeric,Proc,Range,Regexp,String}) => Boolean
133
+ #
134
+ # Returns a boolean indicating whether or not the provided +job+ matches the
135
+ # given Hash of +options. Each _key_ in +options+ is a String or a Symbol that
136
+ # identifies an attribute of +job+ that the corresponding _value_ should be
137
+ # compared against. True is returned if every _value_ in +options+ evaluates to
138
+ # true when compared to the attribute of +job+ identified by the corresponding
139
+ # _key_. False is returned if any of the comparisons evaluates to false.
140
+ #
141
+ # If no options are given, returns true for any job that exists at the time of
142
+ # evaluation.
143
+ #
144
+ # Each attribute comparison is performed using the triple equal (===)
145
+ # operator/method of _value_ with the attribute of +job+ identified by _key_
146
+ # passed into the method. Use of === allows for more complex comparisons
147
+ # using Procs, Ranges, Regexps, etc.
148
+ #
149
+ # Consult MATCHABLE_JOB_ATTRIBUTES for a list of which attributes of +job+
150
+ # can be matched against.
151
+ #
152
+ # Used internally to evaluate if a job matches an assertion.
153
+ #
154
+ # strategy.job_matches?(reserved_job, :state => 'reserved')
155
+ # #=> true
156
+ #
157
+ # strategy.job_matches(small_job, :body => lambda {|body| body.length > 50 })
158
+ # #=> false
159
+ #
160
+ # strategy.job_matches(unreliable_job, :buries => 6..100)
161
+ # #=> true
162
+ def job_matches?
163
+ raise NotImplementedError
164
+ end
165
+
166
+
167
+ # :call-seq:
168
+ # jobs() => Enumerator
169
+ #
170
+ # Returns an Enumerator providing a means to enumerate all jobs in the beanstalkd
171
+ # pool.
172
+ #
173
+ # Used internally to enumerate all jobs to find jobs matching an assertion.
174
+ def jobs
175
+ raise NotImplementedError
176
+ end
177
+
178
+
179
+ # :call-seq:
180
+ # pretty_print_job(job) => String
181
+ #
182
+ # Returns a String representation of +job+ in a pretty, human readable
183
+ # format.
184
+ #
185
+ # Used internally to print a job when an assertion fails.
186
+ def pretty_print_job
187
+ raise NotImplementedError
188
+ end
189
+
190
+
191
+ # :call-seq:
192
+ # pretty_print_tube(tube) => String
193
+ #
194
+ # Returns a String representation of the tube in a pretty, human readable
195
+ # format. Used internally to print a tube when an assertion fails.
196
+ #
197
+ # Used internally to print a tube when an assertion fails.
198
+ def pretty_print_tube
199
+ raise NotImplementedError
200
+ end
201
+
202
+
203
+ # :call-seq:
204
+ # tube_matches?(tube, options => {Symbol,String => Numeric,Proc,Range,Regexp,String}) => Boolean
205
+ #
206
+ # Returns a boolean indicating whether or not the provided +tube+ matches the
207
+ # given Hash of +options. Each _key_ in +options+ is a String or a Symbol that
208
+ # identifies an attribute of +tube+ that the corresponding _value_ should be
209
+ # compared against. True is returned if every _value_ in +options+ evaluates to
210
+ # true when compared to the attribute of +tube+ identified by the corresponding
211
+ # _key_. False is returned if any of the comparisons evaluates to false.
212
+ #
213
+ # If no options are given, returns true for any tube that exists at the time of
214
+ # evaluation.
215
+ #
216
+ # Each attribute comparison is performed using the triple equal (===)
217
+ # operator/method of _value_ with the attribute of +job+ identified by _key_
218
+ # passed into the method. Use of === allows for more complex comparisons using
219
+ # Procs, Ranges, Regexps, etc.
220
+ #
221
+ # Consult MATCHABLE_TUBE_ATTRIBUTES for a list of which attributes of +tube+
222
+ # can be matched against.
223
+ #
224
+ # Used internally to evaluate if a tube matches an assertion.
225
+ #
226
+ # strategy.tube_matches?(paused_tube, :state => 'paused')
227
+ # #=> true
228
+ #
229
+ # strategy.tube_matches(test_tube, :name => /test/)
230
+ # #=> true
231
+ #
232
+ # strategy.tube_matches(backed_up_tube, 'current-jobs-ready' => 50..100)
233
+ # #=> true
234
+ def tube_matches?
235
+ raise NotImplementedError
236
+ end
237
+
238
+
239
+ # :call-seq:
240
+ # tubes() => Enumerator
241
+ #
242
+ # Returns an Enumerator providing a means to enumerate all tubes in the beanstalkd
243
+ # pool.
244
+ #
245
+ # Used internally to enumerate all tubes to find tubes matching an assertion.
246
+ def tubes
247
+ raise NotImplementedError
248
+ end
249
+
250
+ end