afterparty 0.0.4 → 0.0.21

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
- metadata.gz: 31d453b1b76a1ae8297cbe7c139798a7351cd279
4
- data.tar.gz: 284c96ff3b0d214b8b28148be021e513cfe3126b
3
+ metadata.gz: 1746d9cd2e5dee4f459c02cf8a0bef335de1a05d
4
+ data.tar.gz: 86b2eb38f0c9113b8515fbe18ad8d3635a9dc0e9
5
5
  !binary "U0hBNTEy":
6
- metadata.gz: 1d0b960020c84b6b6e977f234c831b5599c6accecea974ad685309c1093ea9f86d44f79d14a7167a75aef6ab5d5f4615b9e2ba556efa8ba22abec453c74ee05f
7
- data.tar.gz: 1a528ba181430aa129c2507e401ab8da33305e1a4020751d4cdd475b5485491c246c3444a81c329c4c850fbeba0addba9167c7a4e11a2b7534353452e0590646
6
+ metadata.gz: 431465cc60c4fb3abbfc63f8f4294367baa94507c4ce04b9181d3afbd5ed4546d3b3d9a79a0178a37814fcbfe468def7fd8c36633baf47d7d55ce384c6929828
7
+ data.tar.gz: a8bcde980355c3a56a668450e274452d0ef10c0274e15bcc609a1a8ae3eb9d596c854ff60616e8b9e0648388c7f19974fdcfc6bb64dd8d806f0e37424355f093
@@ -3,6 +3,4 @@ rvm:
3
3
  - 1.9.3
4
4
  - 2.0.0
5
5
  services:
6
- - redis-server
7
- env:
8
- - AFTERPARTY_JOB_TIME=15 AFTERPARTY_SLOW_TIME=50
6
+ - redis-server
data/README.md CHANGED
@@ -1,8 +1,6 @@
1
1
  # Afterparty
2
2
 
3
- [![Build Status](https://travis-ci.org/hstove/afterparty.png?branch=master)](https://travis-ci.org/hstove/afterparty)
4
-
5
- A Rails 4 compatible queue with support for executing jobs in the future and persistence with Redis.
3
+ A Rails 4 compatible queue with support for executing jobs in the future and serialization with Redis.
6
4
 
7
5
  ## Installation
8
6
 
@@ -43,7 +41,7 @@ end
43
41
  Then add it to the queue at any time.
44
42
 
45
43
  ~~~Ruby
46
- Rails.configuration.queue << Job.new
44
+ Rails.queue << Job.new
47
45
  ~~~
48
46
 
49
47
  If your job responds to an `execute_at` method, the queue will wait to process that job until the specified time.
@@ -19,7 +19,6 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ["lib"]
20
20
 
21
21
  spec.add_dependency "redis"
22
- spec.add_dependency "iconv"
23
22
 
24
23
  spec.add_development_dependency "bundler", "~> 1.3"
25
24
  spec.add_development_dependency "rake"
@@ -14,50 +14,4 @@ module Afterparty
14
14
  def self.redis=(redis)
15
15
  @@redis = redis
16
16
  end
17
-
18
- def self.clear namespace=:default
19
- redis_call namespace, :del
20
- end
21
-
22
- def self.redis_call namespace, command, *args
23
- @@redis.send(command, redis_queue_name(namespace), *args)
24
- end
25
-
26
- def self.redis_queue_name namespace=:default
27
- "afterparty_#{namespace}_queue"
28
- end
29
-
30
- def self.queues
31
- @@redis.smembers "afterparty_queues"
32
- end
33
-
34
- def self.add_queue name
35
- @@redis.sadd "afterparty_queues", name
36
- end
37
-
38
- def self.next_job_id namespace=:default
39
- @@redis.incr "afterparty_#{namespace.to_s}_job_id"
40
- end
41
-
42
- def self.load(raw)
43
- begin
44
- begin
45
- job = Marshal.load(raw)
46
- job = Marshal.load(job) if String === job
47
- return job
48
- rescue NameError => e
49
- # lots of marshal load errors are because something that hasn't been
50
- # required. recursively require on these errors
51
- name = e.message.gsub("uninitialized constant ","").downcase
52
- begin
53
- require "#{name}"
54
- return load(raw)
55
- rescue LoadError
56
- end
57
- end
58
- rescue
59
- return nil
60
- end
61
- end
62
-
63
17
  end
@@ -4,9 +4,8 @@ module Afterparty
4
4
  @temp_namespace = namespace
5
5
  end
6
6
 
7
- def redis_queue_name
8
- puts (a = Afterparty.redis_queue_name(@temp_namespace || @options[:namespace]))
9
- a
7
+ def redis_queue_name
8
+ "afterparty_#{@temp_namespace || @options[:namespace]}_queue"
10
9
  end
11
10
 
12
11
  def clear
@@ -14,7 +13,7 @@ module Afterparty
14
13
  end
15
14
 
16
15
  def redis_call command, *args
17
- result = Afterparty.redis_call (@temp_namespace || @options[:namespace]), command, *args
16
+ result = Afterparty.redis.send(command, redis_queue_name, *args)
18
17
  @temp_namespace = nil
19
18
  result
20
19
  end
@@ -32,17 +31,13 @@ module Afterparty
32
31
  end
33
32
 
34
33
  def jobs_with_scores
35
- hash_from_scores(redis_call(:zrange, 0, -1, {withscores: true}))
34
+ redis_call :zrange, 0, -1, {withscores: true}
36
35
  end
37
36
 
38
37
  def valid_jobs
39
38
  redis_call :zrangebyscore, 0, Time.now.to_i
40
39
  end
41
40
 
42
- def next_valid_job
43
- valid_jobs.first
44
- end
45
-
46
41
  def jobs_empty?
47
42
  count = total_jobs_count
48
43
  # ap count
@@ -57,32 +52,8 @@ module Afterparty
57
52
  @@redis
58
53
  end
59
54
 
60
- def last_completed
61
- @temp_namespace = "completed"
62
- redis_call(:zrange, -1, -1).first
63
- end
64
-
65
- def completed
66
- @temp_namespace = "completed"
67
- redis_call(:zrange, -20, -1).reverse
68
- end
69
-
70
- def completed_with_scores
71
- @temp_namespace = "completed"
72
- hash_from_scores(redis_call(:zrange, -20, -1, withscores: true)).reverse
73
- end
74
-
75
-
76
55
  private
77
56
 
78
- def hash_from_scores raw
79
- arr = []
80
- raw.each do |group|
81
- arr << Afterparty::JobContainer.new(group[0], group[1])
82
- end
83
- arr
84
- end
85
-
86
57
  # returns true if job has an :execute_at value
87
58
  def job_valid? job
88
59
  job.respond_to?(:execute_at) && !job.execute_at.nil?
@@ -4,10 +4,9 @@ module Afterparty
4
4
  include Afterparty::QueueHelpers
5
5
 
6
6
  def initialize options={}, consumer_options={}
7
- # @consumer = ThreadedQueueConsumer.new(self, consumer_options).start
7
+ @consumer = ThreadedQueueConsumer.new(self, consumer_options).start
8
8
  @options = options
9
9
  @options[:namespace] ||= "default"
10
- Afterparty.add_queue @options[:namespace]
11
10
  @options[:sleep] ||= 5
12
11
  @mutex = Mutex.new
13
12
  end
@@ -15,13 +14,8 @@ module Afterparty
15
14
  def push job
16
15
  @mutex.synchronize do
17
16
  return nil if job.nil?
18
- job.class.module_eval do
19
- attr_accessor :afterparty_job_id, :afterparty_queue
20
- end
21
- queue_name = @temp_namespace || @options[:namespace]
22
- job.afterparty_queue = queue_name
23
- job.afterparty_job_id = Afterparty.next_job_id queue_name
24
17
  async_redis_call{ redis_call :zadd, queue_time(job), Marshal.dump(job) }
18
+ @consumer.start unless @consumer.thread.alive?
25
19
  @temp_namespace = nil
26
20
  end
27
21
  end
@@ -31,20 +25,16 @@ module Afterparty
31
25
  def pop
32
26
  @mutex.synchronize do
33
27
  while true do
34
- if !(_jobs = valid_jobs).empty?
28
+ if jobs_empty?
29
+ @consumer.shutdown
30
+ elsif !(_jobs = valid_jobs).empty?
35
31
  job_dump = _jobs[0]
36
32
  async_redis_call do
37
33
  redis_call :zrem, job_dump
38
34
  @temp_namespace = "completed"
39
35
  redis_call :zadd, Time.now.to_i, job_dump
40
36
  end
41
- begin
42
- return Marshal.load(job_dump)
43
- rescue ArgumentException => e
44
- puts "You encountered an argument exception while deserializing a job."
45
- puts "Message: #{e.message}"
46
- raise e
47
- end
37
+ return Marshal.load(job_dump)
48
38
  end
49
39
  sleep(@options[:sleep])
50
40
  end
@@ -1,3 +1,3 @@
1
1
  module Afterparty
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.21"
3
3
  end
@@ -8,16 +8,11 @@ describe Afterparty::RedisQueue do
8
8
  @q = Afterparty::TestRedisQueue.new({sleep: 0.5})
9
9
  end
10
10
 
11
- after do
12
- @worker.stop
13
- end
14
-
15
11
  before :each do
16
- @worker = Afterparty::Worker.new({sleep: 0.5})
17
- @worker.consume
12
+ @q.completed_jobs.clear
18
13
  @q.clear
19
- @job_time = (ENV['AFTERPARTY_JOB_TIME'] || 3).to_i
20
- @slow_job_time = (ENV['AFTERPARTY_SLOW_TIME'] || 10).to_i
14
+ Afterparty.redis.quit
15
+ @job_time = 10
21
16
  end
22
17
 
23
18
  it "pushes nil without errors" do
@@ -33,15 +28,15 @@ describe Afterparty::RedisQueue do
33
28
  it "executes the job" do
34
29
  job = TestJob.new
35
30
  @q.push(job)
36
- @q.jobs.size.should eq(1)
31
+ complete.size.should eq(0)
37
32
  chill(@job_time)
38
- @q.jobs.size.should eq(0)
33
+ complete.size.should eq(1)
39
34
  end
40
35
 
41
36
  it "removes items from the queue after running them" do
42
37
  @q.push TestJob.new
43
38
  chill(@job_time)
44
- @q.jobs.size.should == 0
39
+ @q.jobs.should_not include(@job)
45
40
  end
46
41
 
47
42
  it "doesn't execute jobs that execute in a while" do
@@ -49,19 +44,18 @@ describe Afterparty::RedisQueue do
49
44
  job.execute_at = Time.now + 200
50
45
  @q.push job
51
46
  chill(@job_time)
52
- @q.jobs.size.should eq(1)
47
+ complete.size.should eq(0)
53
48
  end
54
49
 
55
50
  it "waits the correct amount of time to execute a job" do
56
51
  job = TestJob.new
57
- job.execute_at = Time.now + 5
52
+ job.execute_at = Time.now + 2
58
53
  @q.push(job)
59
- @q.jobs.size.should eq(1)
60
- chill(@slow_job_time)
61
- @q.jobs.size.should eq(0)
54
+ chill(50)
55
+ complete.size.should eq(1)
62
56
  end
63
57
 
64
- it "doesn't wait and execute the job synchronously when added" do
58
+ it "doesn't execute the job synchronously when added" do
65
59
  job = test_job 100
66
60
  t = Time.now
67
61
  @q.push(job)
@@ -74,8 +68,8 @@ describe Afterparty::RedisQueue do
74
68
  @q.push(late_job)
75
69
  @q.push(early_job)
76
70
  chill(@job_time)
77
- (jobs = @q.jobs).size.should eq(1)
78
- jobs[0].execute_at.should_not be(nil)
71
+ complete.size.should eq(1)
72
+ complete[0].execute_at.should be(nil)
79
73
  end
80
74
 
81
75
  class ErrorJob
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: afterparty
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.21
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hank Stoever
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-05-17 00:00:00.000000000 Z
11
+ date: 2013-05-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis
@@ -24,20 +24,6 @@ dependencies:
24
24
  - - ! '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
- - !ruby/object:Gem::Dependency
28
- name: iconv
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ! '>='
32
- - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ! '>='
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
27
  - !ruby/object:Gem::Dependency
42
28
  name: bundler
43
29
  requirement: !ruby/object:Gem::Requirement
@@ -82,22 +68,12 @@ files:
82
68
  - README.md
83
69
  - Rakefile
84
70
  - afterparty.gemspec
85
- - app/assets/javascripts/afterparty.js.coffee
86
- - app/assets/stylesheets/afterparty.css.sass
87
- - app/controllers/afterparty/dashboard_controller.rb
88
- - app/views/afterparty/dashboard/index.html.haml
89
- - config/routes.rb
90
71
  - dump.rdb
91
72
  - lib/afterparty.rb
92
- - lib/afterparty/engine.rb
93
- - lib/afterparty/job_container.rb
94
- - lib/afterparty/jobs.rb
95
73
  - lib/afterparty/queue_helpers.rb
96
74
  - lib/afterparty/redis_queue.rb
97
75
  - lib/afterparty/threaded_queue_consumer.rb
98
76
  - lib/afterparty/version.rb
99
- - lib/afterparty/worker.rb
100
- - lib/tasks/tasks.rake
101
77
  - spec/helpers.rb
102
78
  - spec/redis_queue_spec.rb
103
79
  - spec/spec_helper.rb
@@ -1,14 +0,0 @@
1
- $(document).ready ->
2
- # $('.debug').click (e) ->
3
- # $el = $(e.target)
4
- # $tr = $el.parents('tr')
5
- # $tr.next().toggle()
6
- # $tr.toggleClass('debugged')
7
- # false
8
- $('.job-row').click (e) ->
9
- $el = $(e.target)
10
- return true if $el.hasClass('job-action')
11
- $tr = $el.parents('tr')
12
- $tr.next().toggle()
13
- $tr.toggleClass('debugged')
14
- false
@@ -1,85 +0,0 @@
1
- body
2
- :font-family helvetica
3
- :background-color whitesmoke
4
- :color lighten(black,30%)
5
- :margin 0 20px
6
-
7
- a:visited, a
8
- :color rgb(96, 89, 180)
9
- :text-decoration none
10
-
11
- span
12
- :font-size 12px
13
-
14
- .job-table
15
- :border-spacing 0
16
- :max-width 100%
17
- :margin 0px auto
18
- thead tr:first-child
19
- th
20
- :border-width 1px 1px 1px 0
21
- &:first-child
22
- :border-width 1px 1px 1px 1px
23
- th:first-child
24
- :border-top-left-radius 2px
25
- th:last-child
26
- :border-top-right-radius 2px
27
- tbody tr:last-child
28
- td:first-child
29
- :border-bottom-left-radius 2px
30
- td:last-child
31
- :border-bottom-right-radius 2px
32
- tr
33
- td, th
34
- :border 1px solid #ccc
35
- :border-width 0 1px 1px 0
36
- :background-color lighten(whitesmoke, 5%)
37
- :padding 12px 5px
38
- :text-align left
39
- :vertical-align middle
40
- :word-wrap break-word
41
- &:nth-child(2)
42
- :width 70%
43
- &:first-child
44
- :border-width 0 1px 1px 1px
45
- &:first-child, &:last-child
46
- :width 15% !important
47
- &.debugged
48
- td
49
- :background-color rgba(255,255,0,0.25)
50
- &.job-row
51
- :cursor pointer
52
- h3
53
- :margin 0
54
- &:hover
55
- td
56
- :background-color rgba(0,0,0,0.15)
57
- .description
58
- :color white
59
- .debug-row
60
- :display none
61
- :max-width 100%
62
- td pre
63
- :word-wrap break-word
64
- :white-space pre-wrap
65
-
66
- .distance-past, .distance-future
67
- :font-size 12px
68
- .distance-future
69
- :color darken(rgb(0,255,0), 20%)
70
- .distance-past
71
- :color rgba(255,0,0,0.6)
72
-
73
- .description
74
- :font-size 12px
75
- :color #bbb
76
- :margin-left 10px
77
-
78
- .job-action
79
- :text-decoration underline
80
- :font-size 12px
81
- :margin 0 2px
82
-
83
- .job_id
84
- :color #bbb
85
- :font-weight 700
@@ -1,20 +0,0 @@
1
- module Afterparty
2
- class DashboardController < ApplicationController
3
- layout false
4
- def index
5
- @queues = Afterparty.queues
6
- if params[:completed]
7
- @jobs = queue.completed_with_scores
8
- else
9
- @jobs = queue.jobs_with_scores
10
- end
11
- end
12
-
13
- def queue
14
- Rails.configuration.queue
15
- end
16
-
17
- def run
18
- end
19
- end
20
- end
@@ -1,67 +0,0 @@
1
- !!!
2
- %html
3
-
4
- %head
5
- %title== #{Rails.application.class.parent_name} Job Queue
6
- %meta{"http-equiv"=>"Content-Type", :content=>"text/html; charset=utf-8"}
7
- / %meta{name: "viewport", content: "width=device-width, initial-scale=1.0"}
8
- = stylesheet_link_tag "afterparty"
9
- = javascript_include_tag "jquery", "afterparty"
10
- = csrf_meta_tag
11
- = favicon_link_tag
12
- = yield(:head)
13
-
14
- %body
15
- %h1
16
- Viewing
17
- - if params[:completed]
18
- = pluralize @jobs.size, "completed job"
19
- %h3= link_to "View Job Queue", afterparty_engine.dashboard_path
20
- - else
21
- = pluralize @jobs.size, "job"
22
- %h3= link_to "View Completed Jobs", afterparty_engine.dashboard_path(completed: true)
23
- = @queues
24
- %table.job-table
25
- %thead
26
- %tr
27
- %th Execute At
28
- / %th Job
29
- / %th Actions
30
- %tbody
31
- - if @jobs.empty?
32
- %tr
33
- %td{colspan: 3}
34
- %em No jobs to show...
35
- - else
36
- - @jobs.each do |job_container|
37
- - job = job_container.job
38
- %tr.job-row
39
- %td
40
- %h3
41
- - if job_container.job
42
- = link_to job_container.job_class, "#", class: 'debug'
43
- - if job_container.job.respond_to? :description
44
- %span.description= job_container.job.description.html_safe
45
- - else
46
- %em Error marshaling job
47
- =# job_container.execute_at.strftime("%B %d, %Y at %l:%M %P")
48
- - distance = time_ago_in_words(job_container.execute_at)
49
- - if job_container.execute_at > Time.now
50
- %span.distance-future= "in #{distance}"
51
- - else
52
- %span.distance-past= "#{distance} ago"
53
- - if (_id = job_container.job_id) && (_queue = job_container.queue_name)
54
- %span.job_id== ##{_id} #{_queue}
55
- - unless params[:completed]
56
- = link_to "run", afterparty_engine.run_job_path(job_id: _id, queue: _queue), class: 'job-action'
57
- = link_to "delete", afterparty_engine.delete_job_path(job_id: _id, queue: _queue), class: 'job-action'
58
- %tr.debug-row
59
- %td
60
- - if job_container.job
61
- = debug job_container.job
62
- - else
63
- = job_container.raw_string
64
-
65
- %p
66
- Current Time:
67
- = Time.now.strftime("%B %d, %Y at %l:%M %P")
@@ -1,9 +0,0 @@
1
- Afterparty::Engine.routes.draw do
2
- get "/" => "afterparty/dashboard#index", as: :dashboard
3
- get "/run" => "afterparty/dashboard#run", as: :run_job
4
- get "/delete" => "afterparty/dashboard#run", as: :delete_job
5
- end
6
-
7
- Rails.application.routes.draw do
8
- mount Afterparty::Engine, at: "afterparty", as: "afterparty_engine"
9
- end
@@ -1,7 +0,0 @@
1
- require 'rails'
2
- module Afterparty
3
- class Engine < Rails::Engine
4
- engine_name :afterparty
5
-
6
- end
7
- end
@@ -1,36 +0,0 @@
1
- require 'iconv'
2
- require 'date'
3
-
4
- module Afterparty
5
- class JobContainer
6
- attr_accessor :job, :raw, :execute_at, :job_id, :queue_name
7
-
8
- #intialized from redis's WITHSCORES function
9
- def initialize _raw, timestamp
10
- @execute_at = Time.at(timestamp)
11
- begin
12
- @job = Afterparty.load(_raw)
13
- @job_id = job.afterparty_job_id if @job.respond_to? :afterparty_job_id
14
- @queue_name = job.afterparty_queue if @job.respond_to? :afterparty_queue
15
- rescue Exception => e
16
- ap "Error during load: #{e.message}"
17
- @job = nil
18
- end
19
- @raw = _raw
20
- self
21
- end
22
-
23
- def job_class
24
- if @job
25
- @job.class
26
- else
27
- nil
28
- end
29
- end
30
-
31
- def raw_string
32
- ic = Iconv.new('UTF-8//IGNORE', 'UTF-8')
33
- ic.iconv(@raw.dup + ' ')[0..-2]
34
- end
35
- end
36
- end
@@ -1,22 +0,0 @@
1
- module Afterparty
2
- class MailerJob
3
- attr_accessor :execute_at, :mail, :clazz, :method, :args
4
- def initialize clazz, method, *args
5
- # @mail = UserMailer.welcome_email(User.find(1))
6
- @clazz = UserMailer
7
- @method = method
8
- @args = args
9
- end
10
-
11
- def run
12
- @mail = @clazz.send @method, *@args
13
- @mail.deliver
14
- end
15
-
16
- def description
17
- desc = "Mailer: #{(@clazz || "nil")}."
18
- desc << "Method: #{(@method || nil)}."
19
- desc << "Args: #{(@args || nil)}"
20
- end
21
- end
22
- end
@@ -1,56 +0,0 @@
1
- module Afterparty
2
- class Worker
3
- include QueueHelpers
4
-
5
- def initialize options = {}
6
- @options = options
7
- @options[:adapter] ||= :redis
8
- @options[:namespace] ||= :default
9
- @options[:sleep] ||= 10
10
- @options[:logger] ||= Logger.new($stderr)
11
- self
12
- end
13
-
14
- def consume
15
- @stopped = false
16
- # puts "starting worker with namespace [#{@options[:namespace]}]."
17
- @thread = Thread.new {
18
- consume_sync
19
- }
20
- @thread
21
- end
22
-
23
- def consume_sync
24
- while !@stopped
25
- job = next_valid_job
26
- if job
27
- async_redis_call do
28
- @temp_namespace = "completed"
29
- redis_call :zadd, Time.now.to_i, Marshal.dump(job)
30
- redis_call :zrem, job
31
- end
32
- run job
33
- else
34
- sleep(@options[:sleep])
35
- end
36
- end
37
- end
38
-
39
- def stop
40
- @stopped = true
41
- @thread.join(0)
42
- end
43
-
44
- def run(job)
45
- fork do
46
- Marshal.load(job).run
47
- end
48
- rescue Exception => exception
49
- handle_exception job, exception
50
- end
51
-
52
- def handle_exception(job, exception)
53
- @options[:logger].error "Job Error: #{job.inspect}\n#{exception.message}\n#{exception.backtrace.join("\n")}"
54
- end
55
- end
56
- end
@@ -1,25 +0,0 @@
1
- namespace :jobs do
2
- require 'mail'
3
-
4
- desc "Start a new worker"
5
- task work: :environment do
6
- worker = Afterparty::Worker.new
7
- worker.consume_sync
8
- end
9
-
10
- desc "Clear all jobs"
11
- task clear: :environment do
12
- Rails.configuration.queue.clear
13
- end
14
-
15
- desc "List Jobs"
16
- task list: :environment do
17
- jobs = Rails.configuration.queue.jobs_with_scores
18
- puts "#{jobs.values.size} total jobs."
19
- jobs.each do |time, job|
20
- puts time
21
- puts job
22
- end
23
- end
24
- end
25
-