active_job-query 1.0.0.alpha1
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/.gitignore +10 -0
- data/.travis.yml +4 -0
- data/Gemfile +21 -0
- data/README.md +71 -0
- data/Rakefile +58 -0
- data/active_job-query.gemspec +23 -0
- data/lib/active_job/query.rb +72 -0
- data/lib/active_job/query/adapters.rb +9 -0
- data/lib/active_job/query/adapters/sidekiq_adapter.rb +70 -0
- data/lib/active_job/query/job.rb +69 -0
- data/lib/active_job/query/jobs.rb +107 -0
- data/lib/active_job/query/mixin.rb +45 -0
- data/lib/active_job/query/queue.rb +69 -0
- data/lib/active_job/query/queues.rb +49 -0
- data/lib/active_job/query/railtie.rb +12 -0
- data/lib/active_job/query/version.rb +5 -0
- metadata +101 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c82ad0ec4ae81745ed629ac12dc71e72bd8c4a49
|
4
|
+
data.tar.gz: 7b6cb8127d1923cdc34e942acbf0a91d76ec0d48
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: cea0396f776cbbc41a47a59a6612b5b0a4e297109d041aff464eef14c15912671e2bde089c5052c0b1717d4c833d5b2d78864783579a346567dd12e4e5fc706d
|
7
|
+
data.tar.gz: 46f895fccf1896004a26d76dcb56fdd0eb6d6239cb8700616c59eebe24db970ff7f8d2b30dced06602b41ce7c70d4ad1166b3e3311aa9ed2d5ad216580c70e78
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gemspec
|
4
|
+
|
5
|
+
gem 'rails'
|
6
|
+
gem 'sqlite3'
|
7
|
+
|
8
|
+
gem 'resque', require: false
|
9
|
+
gem 'resque-scheduler', require: false
|
10
|
+
gem 'sidekiq', require: false
|
11
|
+
gem 'sucker_punch', require: false
|
12
|
+
gem 'delayed_job', require: false
|
13
|
+
gem 'queue_classic', github: "QueueClassic/queue_classic", require: false, platforms: :ruby
|
14
|
+
gem 'sneakers', require: false
|
15
|
+
gem 'que', require: false
|
16
|
+
gem 'backburner', require: false
|
17
|
+
gem 'qu-rails', github: "bkeepers/qu", branch: "master", require: false
|
18
|
+
gem 'qu-redis', require: false
|
19
|
+
gem 'delayed_job_active_record', require: false
|
20
|
+
gem 'sequel', require: false
|
21
|
+
gem 'byebug'
|
data/README.md
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
# ActiveJob::Query
|
2
|
+
|
3
|
+
WARINING: This is alpha level release. Use it for testing only! (or if you want to contribute :) )
|
4
|
+
|
5
|
+
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/active_job/query`. To experiment with that code, run `bin/console` for an interactive prompt.
|
6
|
+
|
7
|
+
TODO: Delete this and the text above, and describe your gem
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem 'active_job-query'
|
15
|
+
```
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
|
19
|
+
$ bundle
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
Fetching all queues that the adapter is aware of
|
24
|
+
```ruby
|
25
|
+
# On the default adapter (ApplicationJob.queue_adapter or ActiveJob::Base.queue_adapter)
|
26
|
+
ActiveJob::Query.queues
|
27
|
+
# Or on a specific adapter
|
28
|
+
ActiveJob::Query.queues(adapter: MyJob.queue_adapter)
|
29
|
+
# or
|
30
|
+
MyJob.queues
|
31
|
+
```
|
32
|
+
|
33
|
+
Working with queues
|
34
|
+
```ruby
|
35
|
+
# Get a queue
|
36
|
+
queue = ActiveJob::Query.queues.first
|
37
|
+
# Or initialize directly
|
38
|
+
queue = ActiveJob::Query::Queue.new(name: "default", adapter: ActiveJob::Base.queue_adapter)
|
39
|
+
# jobs count
|
40
|
+
queue.size
|
41
|
+
# clear jobs
|
42
|
+
queue.delete_all
|
43
|
+
# fetch jobs
|
44
|
+
queue.jobs
|
45
|
+
|
46
|
+
```
|
47
|
+
|
48
|
+
Fetching jobs
|
49
|
+
```ruby
|
50
|
+
ActiveJob::Query.jobs(
|
51
|
+
type: :all # allowed values: :all || :pending || :scheduled || :failed
|
52
|
+
queue: "default", # queue name to search on
|
53
|
+
adapter: AJ adapter defaults to ActiveJob::Base.queue_adapter
|
54
|
+
)
|
55
|
+
```
|
56
|
+
|
57
|
+
Fetching all jobs on a specific queue
|
58
|
+
```ruby
|
59
|
+
ActiveJob::Query.queues[0].jobs
|
60
|
+
```
|
61
|
+
|
62
|
+
## Development
|
63
|
+
|
64
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake false` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
65
|
+
|
66
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
67
|
+
|
68
|
+
## Contributing
|
69
|
+
|
70
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/active_job-query.
|
71
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
Bundler::GemHelper.install_tasks
|
8
|
+
|
9
|
+
require 'rdoc/task'
|
10
|
+
|
11
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
12
|
+
rdoc.rdoc_dir = 'rdoc'
|
13
|
+
rdoc.title = 'ActiveJob Query'
|
14
|
+
rdoc.options << '--line-numbers'
|
15
|
+
rdoc.rdoc_files.include('README.md')
|
16
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'rake/testtask'
|
20
|
+
|
21
|
+
ADAPTERS = %w(sidekiq resque) #delayed_job inline qu que queue_classic sneakers sucker_punch backburner
|
22
|
+
|
23
|
+
def run_without_aborting(*tasks)
|
24
|
+
errors = []
|
25
|
+
|
26
|
+
tasks.each do |task|
|
27
|
+
begin
|
28
|
+
Rake::Task[task].invoke
|
29
|
+
rescue Exception
|
30
|
+
errors << task
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
abort "Errors running #{errors.join(', ')}" if errors.any?
|
35
|
+
end
|
36
|
+
|
37
|
+
desc 'Run all adapter tests'
|
38
|
+
task :test do
|
39
|
+
tasks = ADAPTERS.map{|a| "test:#{a}" }
|
40
|
+
run_without_aborting(*tasks)
|
41
|
+
end
|
42
|
+
|
43
|
+
namespace :test do
|
44
|
+
ADAPTERS.each do |adapter|
|
45
|
+
Rake::TestTask.new(adapter) do |t|
|
46
|
+
t.libs << 'lib'
|
47
|
+
t.libs << 'test'
|
48
|
+
t.pattern = 'test/**/*_test.rb'
|
49
|
+
t.verbose = false
|
50
|
+
end
|
51
|
+
namespace adapter do
|
52
|
+
task(:env) { ENV['AJADAPTER'] = adapter }
|
53
|
+
end
|
54
|
+
task adapter => "#{adapter}:env"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
task default: :test
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'active_job/query/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "active_job-query"
|
8
|
+
spec.version = ActiveJob::Query::VERSION
|
9
|
+
spec.authors = ["Cristian Bica"]
|
10
|
+
spec.email = ["cristian.bica@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Write a short summary, because Rubygems requires one.}
|
13
|
+
spec.description = %q{Write a longer description or delete this line.}
|
14
|
+
spec.homepage = "http://github.com"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
spec.require_paths = ["lib"]
|
18
|
+
|
19
|
+
spec.add_dependency 'activejob'
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.10"
|
22
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
23
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require "active_job/query/version"
|
2
|
+
|
3
|
+
module ActiveJob
|
4
|
+
module Query
|
5
|
+
extend ActiveSupport::Autoload
|
6
|
+
|
7
|
+
autoload :Job
|
8
|
+
autoload :Jobs
|
9
|
+
autoload :Mixin
|
10
|
+
autoload :Queue
|
11
|
+
autoload :Queues
|
12
|
+
autoload :Adapters
|
13
|
+
|
14
|
+
# Returns a list of queues an adapter is aware of.
|
15
|
+
#
|
16
|
+
# ==== Options
|
17
|
+
# * <tt>:adapter</tt> - An ActiveJob adapter. Default is the default ActiveJob adapter
|
18
|
+
#
|
19
|
+
# ==== Returns
|
20
|
+
# * <tt>ActiveJob::Query::Queues</tt> - A collection of queues.
|
21
|
+
#
|
22
|
+
# ==== Examples
|
23
|
+
#
|
24
|
+
# # queues for the default adapter (ApplicationJob.queue_adapter or ActiveJob::Base.queue_adapter)
|
25
|
+
# ActiveJob::Query.queues
|
26
|
+
# # queues for a specific adapter
|
27
|
+
# ActiveJob::Query.queues(adapter: MyJob.queue_adapter)
|
28
|
+
def self.queues(adapter: nil)
|
29
|
+
ActiveJob::Query::Queues.new(adapter: adapter)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Returns a list of jobs.
|
33
|
+
#
|
34
|
+
# ==== Options
|
35
|
+
# * <tt>:queue</tt> - An ActiveJob::Query::Queue instance
|
36
|
+
# * <tt>:queue_name</tt> - A queue name. You must specify this unless you
|
37
|
+
# provide the above queue
|
38
|
+
# * <tt>:adapter</tt> - An ActiveJob adapter. Default is the default
|
39
|
+
# ActiveJob adapter. You must specify this unless you privide the queue
|
40
|
+
# parameter
|
41
|
+
# * <tt>:type</tt> - The type of the job:
|
42
|
+
# - all - All jobs
|
43
|
+
# - enqueued - Enqueued jobs that will be run asap
|
44
|
+
# - scheduled - Jobs scheduled to run in the future
|
45
|
+
# - failed - Jobs that failed and that will never be executed again
|
46
|
+
# * <tt>:klass</tt> - Filter the result by the job Class
|
47
|
+
#
|
48
|
+
# ==== Returns
|
49
|
+
# * <tt>ActiveJob::Query::Jobs</tt> - A collection of jobs.
|
50
|
+
#
|
51
|
+
# ==== Examples
|
52
|
+
#
|
53
|
+
# # jobs on the default adapter on the 'default' queue
|
54
|
+
# ActiveJob::Query.jobs
|
55
|
+
# # jobs on a named queue, on the default adapter
|
56
|
+
# ActiveJob::Query.jobs(queue_name: 'urgent')
|
57
|
+
# # jobs on a named queue, on a specific adapter
|
58
|
+
# ActiveJob::Query.jobs(queue_name: 'urgent', adapter: MyJob.queue_adapter)
|
59
|
+
# # jobs on a queue
|
60
|
+
# ActiveJob::Query.jobs(queue: ActiveJob::Query::Queue.new(name: 'urgent', adapter: MyJob.queue_adapter))
|
61
|
+
def self.jobs(queue: nil, queue_name: nil, adapter: nil, type: :all, klass: nil)
|
62
|
+
ActiveJob::Query::Jobs.new(queue: queue, queue_name: queue_name, adapter: adapter, type: type, klass: klass)
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.query_adapter(queue_adapter) #:nodoc:
|
66
|
+
name = queue_adapter.is_a?(Class) ? queue_adapter.name.demodulize : queue_adapter.class.name.demodulize
|
67
|
+
Adapters.const_get(name)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
require 'active_job/query/railtie' if defined?(Rails)
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'sidekiq/api'
|
2
|
+
|
3
|
+
module ActiveJob
|
4
|
+
module Query
|
5
|
+
module Adapters
|
6
|
+
module SidekiqAdapter extend self #:nodoc#
|
7
|
+
def queues
|
8
|
+
queues = Sidekiq::Queue.all.collect(&:name)
|
9
|
+
queues += Sidekiq::ScheduledSet.new.map(&:itself).map(&:queue)
|
10
|
+
queues.uniq
|
11
|
+
end
|
12
|
+
|
13
|
+
def enqueued_jobs(queue)
|
14
|
+
jobs = []
|
15
|
+
Sidekiq::Queue.new(queue).each do |job|
|
16
|
+
next unless active_job_job?(job)
|
17
|
+
jobs << wrap_job(job)
|
18
|
+
end
|
19
|
+
Sidekiq::RetrySet.new.each do |job|
|
20
|
+
next unless active_job_job?(job)
|
21
|
+
next unless job.queue == queue
|
22
|
+
jobs << wrap_job(job)
|
23
|
+
end
|
24
|
+
jobs
|
25
|
+
end
|
26
|
+
|
27
|
+
def scheduled_jobs(queue)
|
28
|
+
jobs = []
|
29
|
+
Sidekiq::ScheduledSet.new.each do |job|
|
30
|
+
next unless active_job_job?(job)
|
31
|
+
next unless job.queue == queue
|
32
|
+
jobs << wrap_job(job)
|
33
|
+
end
|
34
|
+
jobs
|
35
|
+
end
|
36
|
+
|
37
|
+
def failed_jobs(queue)
|
38
|
+
jobs = []
|
39
|
+
Sidekiq::DeadSet.new.each do |job|
|
40
|
+
next unless active_job_job?(job)
|
41
|
+
next unless job.queue == queue
|
42
|
+
jobs << wrap_job(job)
|
43
|
+
end
|
44
|
+
jobs
|
45
|
+
end
|
46
|
+
|
47
|
+
def delete(job)
|
48
|
+
sidekiq_job = job.provider_job || find_job(job.provider_job_id)
|
49
|
+
sidekiq_job.delete if sidekiq_job.present?
|
50
|
+
end
|
51
|
+
|
52
|
+
protected
|
53
|
+
def find_job(jid)
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
def wrap_job(job)
|
58
|
+
aj = ActiveJob::Base.deserialize(job["args"].first)
|
59
|
+
aj.send :deserialize_arguments_if_needed
|
60
|
+
provider_job_id = aj.respond_to?(:provider_job_id) ? (aj.provider_job_id || job["jid"]) : job["jid"]
|
61
|
+
Job.new(klass: aj.class, args: aj.arguments, job_id: aj.job_id, provider_job_id: provider_job_id, provider_job: self)
|
62
|
+
end
|
63
|
+
|
64
|
+
def active_job_job?(job)
|
65
|
+
job.klass == "ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module ActiveJob
|
2
|
+
module Query
|
3
|
+
# = ActiveJob Job
|
4
|
+
#
|
5
|
+
# Hold the details of a job.
|
6
|
+
#
|
7
|
+
# Usage:
|
8
|
+
#
|
9
|
+
# queue = ActiveJob::Query::Queue.new
|
10
|
+
# job = queue.jobs.first
|
11
|
+
# job.delete
|
12
|
+
# job.active_job.perform_now
|
13
|
+
class Job
|
14
|
+
attr_accessor :queue, :adapter, :klass, :args, :job_id, :provider_job_id, :provider_job
|
15
|
+
|
16
|
+
def initialize(queue: nil, adapter: nil, klass:, args: [], job_id:, provider_job_id: nil, provider_job: nil) #:nodoc#
|
17
|
+
self.queue = queue
|
18
|
+
self.adapter = adapter || default_adapter
|
19
|
+
self.klass = klass
|
20
|
+
self.args = args
|
21
|
+
self.job_id = job_id
|
22
|
+
self.provider_job_id = provider_job_id
|
23
|
+
self.provider_job = provider_job
|
24
|
+
end
|
25
|
+
|
26
|
+
# Finds a job on a specified queue or on all queues of an adapter by job_id or provider_job_id
|
27
|
+
# WARINING: for big queues this will take a while
|
28
|
+
def find_job(queue: nil, adapter: nil, job_id: nil, provider_job_id: nil)
|
29
|
+
raise ArgumentError, "You must provide a queue or an adapter" unless queue.present? or adapter.present?
|
30
|
+
raise ArgumentError, "You must provide a job_id or a provider_job_id" unless job_id.present? or provider_job_id.present?
|
31
|
+
queues = if queue.present?
|
32
|
+
[queue]
|
33
|
+
else
|
34
|
+
ActiveJob::Query.queues(adapter)
|
35
|
+
end
|
36
|
+
queues.each do |q|
|
37
|
+
q.jobs.each do |job|
|
38
|
+
return job if job_id.present? and job.job_id == job_id
|
39
|
+
return job if provider_job_id.present? and job.provider_job_id == provider_job_id
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Permanently deletes the job from the queue
|
45
|
+
def delete
|
46
|
+
query_adapter.delete(self)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Returns an ActiveJob::Base subclass instnace
|
50
|
+
def active_job
|
51
|
+
job = klass.new
|
52
|
+
job.queue_name = queue.name
|
53
|
+
job.job_id = job_id
|
54
|
+
job.provider_job_id = provider_job_id if job.respond_to?(:provider_job_id=)
|
55
|
+
job.arguments = args
|
56
|
+
job
|
57
|
+
end
|
58
|
+
|
59
|
+
protected
|
60
|
+
def default_adapter #:nodoc:
|
61
|
+
defined?(ApplicationJob) ? ApplicationJob.queue_adapter : ActiveJob::Base.queue_adapter
|
62
|
+
end
|
63
|
+
|
64
|
+
def query_adapter #:nodoc:
|
65
|
+
@query_adapter ||= ActiveJob::Query.query_adapter(adapter)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
module ActiveJob
|
2
|
+
module Query
|
3
|
+
# = ActiveJob Jobs
|
4
|
+
#
|
5
|
+
# Holds a collection of ActiveJob jobs. Responds to all
|
6
|
+
# Enumerable methods.
|
7
|
+
#
|
8
|
+
# Usage:
|
9
|
+
#
|
10
|
+
# ActiveJob::Query::Jobs.new.each do |jobs|
|
11
|
+
# # job is an instance of ActiveJob::Query::Job
|
12
|
+
# end
|
13
|
+
class Jobs
|
14
|
+
attr_accessor :jobs, :queue, :adapter, :type, :klass
|
15
|
+
include Enumerable
|
16
|
+
delegate *Enumerable.public_instance_methods, to: :jobs
|
17
|
+
alias :size :count
|
18
|
+
|
19
|
+
# Returns a collection of jobs.
|
20
|
+
#
|
21
|
+
# ==== Options
|
22
|
+
# * <tt>:queue</tt> - An ActiveJob::Query::Queue instance
|
23
|
+
# * <tt>:queue_name</tt> - A queue name. You must specify this unless you
|
24
|
+
# provide the above queue
|
25
|
+
# * <tt>:adapter</tt> - An ActiveJob adapter. Default is the default
|
26
|
+
# ActiveJob adapter. You must specify this unless you privide the queue
|
27
|
+
# parameter
|
28
|
+
# * <tt>:type</tt> - The type of the job:
|
29
|
+
# - all - All jobs
|
30
|
+
# - enqueued - Enqueued jobs that will be run asap
|
31
|
+
# - scheduled - Jobs scheduled to run in the future
|
32
|
+
# - failed - Jobs that failed and that will never be executed again
|
33
|
+
# * <tt>:klass</tt> - Filter the result by the job Class
|
34
|
+
#
|
35
|
+
# ==== Returns
|
36
|
+
# * <tt>ActiveJob::Query::Jobs</tt> - A collection of jobs.
|
37
|
+
#
|
38
|
+
# ==== Examples
|
39
|
+
#
|
40
|
+
# # jobs on the default adapter on the 'default' queue
|
41
|
+
# ActiveJob::Query::Jobs.new
|
42
|
+
# # jobs on a named queue, on the default adapter
|
43
|
+
# ActiveJob::Query::Jobs.new(queue_name: 'urgent')
|
44
|
+
# # jobs on a named queue, on a specific adapter
|
45
|
+
# ActiveJob::Query::Jobs.new(queue_name: 'urgent', adapter: MyJob.queue_adapter)
|
46
|
+
# # jobs on a queue
|
47
|
+
# ActiveJob::Query::Jobs.new(queue: ActiveJob::Query::Queue.new(name: 'urgent', adapter: MyJob.queue_adapter))
|
48
|
+
def initialize(queue: nil, queue_name: nil, adapter: nil, type: :all, klass: nil)
|
49
|
+
if queue and queue.is_a?(Queue)
|
50
|
+
self.queue = queue
|
51
|
+
self.adapter = queue.adapter
|
52
|
+
elsif queue_name
|
53
|
+
self.adapter = adapter || default_adapter
|
54
|
+
self.queue = Queue.new(name: "default", adapter: self.adapter)
|
55
|
+
end
|
56
|
+
raise ArgumentError, "You must provide a queue or a queue_name" unless self.queue
|
57
|
+
self.type = type
|
58
|
+
self.klass = klass
|
59
|
+
end
|
60
|
+
|
61
|
+
# Deletes all jobs from this collection.
|
62
|
+
# WARNING: This will delete the jobs permanently
|
63
|
+
def delete_all
|
64
|
+
jobs.map(&:delete)
|
65
|
+
end
|
66
|
+
|
67
|
+
def jobs #:nodoc:
|
68
|
+
@jobs ||= begin
|
69
|
+
jobs = (fetch_jobs(:enqueued) + fetch_jobs(:scheduled) + fetch_jobs(:failed))
|
70
|
+
jobs.select! do |job|
|
71
|
+
job.klass == klass
|
72
|
+
end if klass.present?
|
73
|
+
jobs
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
protected
|
78
|
+
def includes_enqueued_jobs? #:nodoc:
|
79
|
+
type.to_s == 'all' or type.to_s == 'enqueued'
|
80
|
+
end
|
81
|
+
|
82
|
+
def includes_scheduled_jobs? #:nodoc:
|
83
|
+
type.to_s == 'all' or type.to_s == 'scheduled'
|
84
|
+
end
|
85
|
+
|
86
|
+
def includes_failed_jobs? #:nodoc:
|
87
|
+
type.to_s == 'all' or type.to_s == 'failed'
|
88
|
+
end
|
89
|
+
|
90
|
+
def fetch_jobs(job_type) #:nodoc:
|
91
|
+
return [] unless send(:"includes_#{job_type}_jobs?")
|
92
|
+
query_adapter.send(:"#{job_type}_jobs", queue.name).each do |job|
|
93
|
+
job.adapter = adapter
|
94
|
+
job.queue = queue
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def default_adapter #:nodoc:
|
99
|
+
defined?(ApplicationJob) ? ApplicationJob.queue_adapter : ActiveJob::Base.queue_adapter
|
100
|
+
end
|
101
|
+
|
102
|
+
def query_adapter #:nodoc:
|
103
|
+
@query_adapter ||= ActiveJob::Query.query_adapter(adapter)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module ActiveJob
|
2
|
+
module Query
|
3
|
+
# = ActiveJob Query
|
4
|
+
#
|
5
|
+
# This externs ActiveJob::Base with two methods: queues and jobs:
|
6
|
+
# queues: returns the queue the job's adapter is aware of
|
7
|
+
# jobs: returns all the enqueued jobs of this class
|
8
|
+
module Mixin
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
# Returns a list of queues the adapter is aware of.
|
13
|
+
#
|
14
|
+
# ==== Returns
|
15
|
+
# * <tt>ActiveJob::Query::Queues</tt> - A collection of queues.
|
16
|
+
def queues
|
17
|
+
ActiveJob::Query::Queues.new(adapter: queue_adapter)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Returns a list of jobs for this class.
|
21
|
+
#
|
22
|
+
# ==== Options
|
23
|
+
# * <tt>:queue_name</tt> - A queue name. Default is 'default'
|
24
|
+
# * <tt>:type</tt> - The type of the job:
|
25
|
+
# - all - All jobs
|
26
|
+
# - enqueued - Enqueued jobs that will be run asap
|
27
|
+
# - scheduled - Jobs scheduled to run in the future
|
28
|
+
# - failed - Jobs that failed and that will never be executed again
|
29
|
+
#
|
30
|
+
# ==== Returns
|
31
|
+
# * <tt>ActiveJob::Query::Jobs</tt> - A collection of jobs.
|
32
|
+
#
|
33
|
+
# ==== Examples
|
34
|
+
#
|
35
|
+
# # jobs enqueued
|
36
|
+
# MyJob.jobs(type: :enqueued)
|
37
|
+
# # all jobs on specified queue
|
38
|
+
# MyJob.jobs(queue_name: 'urgent')
|
39
|
+
def jobs(queue_name: 'default', type: :all)
|
40
|
+
ActiveJob::Query::Jobs.new(queue_name: queue_name, type: :all, klass: self)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module ActiveJob
|
2
|
+
module Query
|
3
|
+
# = ActiveJob Queue
|
4
|
+
#
|
5
|
+
# Hold the details of a queue. You can get statistics of a queue,
|
6
|
+
# the jobs enqueued on a queue or manipulate the jobs.
|
7
|
+
#
|
8
|
+
# Usage:
|
9
|
+
#
|
10
|
+
# queue = ActiveJob::Query::Queue.new()
|
11
|
+
# queue.size
|
12
|
+
# queue.jobs
|
13
|
+
class Queue
|
14
|
+
attr_accessor :name, :adapter
|
15
|
+
|
16
|
+
# Returns a queue of an adapter.
|
17
|
+
#
|
18
|
+
# ==== Options
|
19
|
+
# * <tt>:name</tt> - The queue name. Default is 'default'
|
20
|
+
# * <tt>:adapter</tt> - An ActiveJob adapter. Default is the default ActiveJob adapter
|
21
|
+
#
|
22
|
+
# ==== Examples
|
23
|
+
#
|
24
|
+
# # 'default' queue on the default adapter (ApplicationJob.queue_adapter or ActiveJob::Base.queue_adapter)
|
25
|
+
# ActiveJob::Query::Queue.new
|
26
|
+
# # queue for a specific adapter
|
27
|
+
# ActiveJob::Query::Queue.new(name: 'urgent', adapter: MyJob.queue_adapter)
|
28
|
+
def initialize(name: 'default', adapter: nil)
|
29
|
+
self.name = name
|
30
|
+
self.adapter = adapter || default_adapter
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns a list of jobs.
|
34
|
+
#
|
35
|
+
# ==== Options
|
36
|
+
# * <tt>:type</tt> - The type of the job:
|
37
|
+
# - all - All jobs
|
38
|
+
# - enqueued - Enqueued jobs that will be run asap
|
39
|
+
# - scheduled - Jobs scheduled to run in the future
|
40
|
+
# - failed - Jobs that failed and that will never be executed again
|
41
|
+
# * <tt>:klass</tt> - Filter the result by the job Class
|
42
|
+
#
|
43
|
+
# ==== Returns
|
44
|
+
# * <tt>ActiveJob::Query::Jobs</tt> - A collection of jobs.
|
45
|
+
#
|
46
|
+
# ==== Examples
|
47
|
+
#
|
48
|
+
# queue = ActiveJob::Query::Queue.new
|
49
|
+
# queue.jobs
|
50
|
+
# queue.jobs(type: :scheduled)
|
51
|
+
# queue.jobs(type: :failed)
|
52
|
+
# queue.jobs(klass: PaymentsJob)
|
53
|
+
# queue.jobs(type: :failed, klass: PaymentsJob)
|
54
|
+
def jobs(type: :all, klass: nil)
|
55
|
+
ActiveJob::Query.jobs(queue: self, type: type, klass: klass)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Returns the number of jobs on the queue with the type and klass filters applied.
|
59
|
+
def size(type: :all, klass: nil)
|
60
|
+
jobs(type: type, klass: klass).size
|
61
|
+
end
|
62
|
+
|
63
|
+
protected
|
64
|
+
def default_adapter #:nodoc:
|
65
|
+
defined?(ApplicationJob) ? ApplicationJob.queue_adapter : ActiveJob::Base.queue_adapter
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module ActiveJob
|
2
|
+
module Query
|
3
|
+
# = ActiveJob Queues
|
4
|
+
#
|
5
|
+
# Holds a collection of ActiveJob queues. Responds to all
|
6
|
+
# Enumerable methods.
|
7
|
+
#
|
8
|
+
# Usage:
|
9
|
+
#
|
10
|
+
# ActiveJob::Query::Queues.new.each do |queue|
|
11
|
+
# # queue is an instance of ActiveJob::Query::Queue
|
12
|
+
# end
|
13
|
+
class Queues
|
14
|
+
attr_accessor :queues, :adapter
|
15
|
+
include Enumerable
|
16
|
+
delegate *Enumerable.public_instance_methods, to: :queues
|
17
|
+
|
18
|
+
# Returns a collection of queues an adapter is aware of.
|
19
|
+
#
|
20
|
+
# ==== Options
|
21
|
+
# * <tt>:adapter</tt> - An ActiveJob adapter. Default is the default ActiveJob adapter
|
22
|
+
#
|
23
|
+
# ==== Examples
|
24
|
+
#
|
25
|
+
# # queues for the default adapter (ApplicationJob.queue_adapter or ActiveJob::Base.queue_adapter)
|
26
|
+
# ActiveJob::Query::Queues.new
|
27
|
+
# # queues for a specific adapter
|
28
|
+
# ActiveJob::Query::Queues.new(adapter: MyJob.queue_adapter)
|
29
|
+
def initialize(adapter: nil)
|
30
|
+
self.adapter = adapter || default_adapter
|
31
|
+
end
|
32
|
+
|
33
|
+
def queues #:nodoc:
|
34
|
+
@queues ||= query_adapter.queues.map do |name|
|
35
|
+
Queue.new(name: name, adapter: adapter)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
protected
|
40
|
+
def default_adapter #:nodoc:
|
41
|
+
defined?(ApplicationJob) ? ApplicationJob.queue_adapter : ActiveJob::Base.queue_adapter
|
42
|
+
end
|
43
|
+
|
44
|
+
def query_adapter #:nodoc:
|
45
|
+
@query_adapter ||= ActiveJob::Query.query_adapter(adapter)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
metadata
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: active_job-query
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0.alpha1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Cristian Bica
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-08-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activejob
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.10'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.10'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
description: Write a longer description or delete this line.
|
56
|
+
email:
|
57
|
+
- cristian.bica@gmail.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- ".gitignore"
|
63
|
+
- ".travis.yml"
|
64
|
+
- Gemfile
|
65
|
+
- README.md
|
66
|
+
- Rakefile
|
67
|
+
- active_job-query.gemspec
|
68
|
+
- lib/active_job/query.rb
|
69
|
+
- lib/active_job/query/adapters.rb
|
70
|
+
- lib/active_job/query/adapters/sidekiq_adapter.rb
|
71
|
+
- lib/active_job/query/job.rb
|
72
|
+
- lib/active_job/query/jobs.rb
|
73
|
+
- lib/active_job/query/mixin.rb
|
74
|
+
- lib/active_job/query/queue.rb
|
75
|
+
- lib/active_job/query/queues.rb
|
76
|
+
- lib/active_job/query/railtie.rb
|
77
|
+
- lib/active_job/query/version.rb
|
78
|
+
homepage: http://github.com
|
79
|
+
licenses: []
|
80
|
+
metadata: {}
|
81
|
+
post_install_message:
|
82
|
+
rdoc_options: []
|
83
|
+
require_paths:
|
84
|
+
- lib
|
85
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ">"
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: 1.3.1
|
95
|
+
requirements: []
|
96
|
+
rubyforge_project:
|
97
|
+
rubygems_version: 2.4.5
|
98
|
+
signing_key:
|
99
|
+
specification_version: 4
|
100
|
+
summary: Write a short summary, because Rubygems requires one.
|
101
|
+
test_files: []
|