delayed_job_progress 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.
Files changed (70) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.travis.yml +2 -0
  4. data/Gemfile +15 -0
  5. data/Gemfile.lock +113 -0
  6. data/MIT-LICENSE +20 -0
  7. data/README.md +87 -0
  8. data/Rakefile +24 -0
  9. data/app/controllers/delayed_job_progress/jobs_controller.rb +49 -0
  10. data/bin/rails +12 -0
  11. data/config/routes.rb +5 -0
  12. data/delayed_job_progress.gemspec +25 -0
  13. data/lib/delayed_job_progress.rb +7 -0
  14. data/lib/delayed_job_progress/engine.rb +13 -0
  15. data/lib/delayed_job_progress/error.rb +4 -0
  16. data/lib/delayed_job_progress/extensions/job.rb +42 -0
  17. data/lib/delayed_job_progress/extensions/worker.rb +5 -0
  18. data/lib/delayed_job_progress/generators/delayed_job/progress_generator.rb +17 -0
  19. data/lib/delayed_job_progress/generators/delayed_job/templates/progress_migration.rb +29 -0
  20. data/lib/delayed_job_progress/version.rb +3 -0
  21. data/lib/tasks/delayed_job_progress_tasks.rake +4 -0
  22. data/test/delayed_job_progress_test.rb +7 -0
  23. data/test/dummy/README.rdoc +28 -0
  24. data/test/dummy/Rakefile +6 -0
  25. data/test/dummy/app/assets/images/.keep +0 -0
  26. data/test/dummy/app/assets/javascripts/application.js +13 -0
  27. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  28. data/test/dummy/app/controllers/application_controller.rb +5 -0
  29. data/test/dummy/app/controllers/concerns/.keep +0 -0
  30. data/test/dummy/app/helpers/application_helper.rb +2 -0
  31. data/test/dummy/app/mailers/.keep +0 -0
  32. data/test/dummy/app/models/.keep +0 -0
  33. data/test/dummy/app/models/concerns/.keep +0 -0
  34. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  35. data/test/dummy/bin/bundle +3 -0
  36. data/test/dummy/bin/rails +4 -0
  37. data/test/dummy/bin/rake +4 -0
  38. data/test/dummy/bin/setup +29 -0
  39. data/test/dummy/config.ru +4 -0
  40. data/test/dummy/config/application.rb +26 -0
  41. data/test/dummy/config/boot.rb +5 -0
  42. data/test/dummy/config/database.yml +25 -0
  43. data/test/dummy/config/environment.rb +5 -0
  44. data/test/dummy/config/environments/development.rb +41 -0
  45. data/test/dummy/config/environments/production.rb +79 -0
  46. data/test/dummy/config/environments/test.rb +42 -0
  47. data/test/dummy/config/initializers/assets.rb +11 -0
  48. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  49. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  50. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  51. data/test/dummy/config/initializers/inflections.rb +16 -0
  52. data/test/dummy/config/initializers/mime_types.rb +4 -0
  53. data/test/dummy/config/initializers/session_store.rb +3 -0
  54. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  55. data/test/dummy/config/locales/en.yml +23 -0
  56. data/test/dummy/config/routes.rb +4 -0
  57. data/test/dummy/config/secrets.yml +22 -0
  58. data/test/dummy/db/schema.rb +16 -0
  59. data/test/dummy/lib/assets/.keep +0 -0
  60. data/test/dummy/log/.keep +0 -0
  61. data/test/dummy/public/404.html +67 -0
  62. data/test/dummy/public/422.html +67 -0
  63. data/test/dummy/public/500.html +66 -0
  64. data/test/dummy/public/favicon.ico +0 -0
  65. data/test/extensions/job_test.rb +74 -0
  66. data/test/extensions/worker_test.rb +40 -0
  67. data/test/generator_test.rb +14 -0
  68. data/test/jobs_controller_test.rb +71 -0
  69. data/test/test_helper.rb +71 -0
  70. metadata +223 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e03469840f266c87523e59b5c4232263b804b3b9
4
+ data.tar.gz: ba20030273160732952acb77144983b63dee21b2
5
+ SHA512:
6
+ metadata.gz: 7e1b6d70e4f6e11c4d05cf2883c2433b9e5254843c72ae49bd6877d3eaed719504a8956e6e9990cd0cb02957359861ec0efa2a25dc9ed79c970308d424cbd903
7
+ data.tar.gz: f54c79cf7c973d2678e9c386c6696b814c6a64204e4b19eb2ec98f6031c79fe6d3f76c5fa137c6c2be2f0dccc353c8e97ab395ae91670bbf2696098a787621c8
@@ -0,0 +1,9 @@
1
+ .bundle/
2
+ log/*.log
3
+ pkg/
4
+ test/dummy/db/*.sqlite3
5
+ test/dummy/db/*.sqlite3-journal
6
+ test/dummy/log/*.log
7
+ test/dummy/tmp/
8
+ test/dummy/.sass-cache
9
+ tmp/
@@ -0,0 +1,2 @@
1
+ language: ruby
2
+ rvm: 2.2.1
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Declare your gem's dependencies in delayed_job_progress.gemspec.
4
+ # Bundler will treat runtime dependencies like base dependencies, and
5
+ # development dependencies will be added by default to the :development group.
6
+ gemspec
7
+
8
+ # Declare any dependencies that are still in development here instead of in
9
+ # your gemspec. These might include edge Rails or gems from your path or
10
+ # Git. Remember to move these dependencies to your gemspec before releasing
11
+ # your gem to rubygems.org.
12
+
13
+ # To use a debugger
14
+ # gem 'byebug', group: [:development, :test]
15
+
@@ -0,0 +1,113 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ delayed_job_progress (0.0.0)
5
+ delayed_job (>= 4.0)
6
+ delayed_job_active_record (>= 4.0)
7
+ rails (>= 4.0.0, < 5)
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ actionmailer (4.2.4)
13
+ actionpack (= 4.2.4)
14
+ actionview (= 4.2.4)
15
+ activejob (= 4.2.4)
16
+ mail (~> 2.5, >= 2.5.4)
17
+ rails-dom-testing (~> 1.0, >= 1.0.5)
18
+ actionpack (4.2.4)
19
+ actionview (= 4.2.4)
20
+ activesupport (= 4.2.4)
21
+ rack (~> 1.6)
22
+ rack-test (~> 0.6.2)
23
+ rails-dom-testing (~> 1.0, >= 1.0.5)
24
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
25
+ actionview (4.2.4)
26
+ activesupport (= 4.2.4)
27
+ builder (~> 3.1)
28
+ erubis (~> 2.7.0)
29
+ rails-dom-testing (~> 1.0, >= 1.0.5)
30
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
31
+ activejob (4.2.4)
32
+ activesupport (= 4.2.4)
33
+ globalid (>= 0.3.0)
34
+ activemodel (4.2.4)
35
+ activesupport (= 4.2.4)
36
+ builder (~> 3.1)
37
+ activerecord (4.2.4)
38
+ activemodel (= 4.2.4)
39
+ activesupport (= 4.2.4)
40
+ arel (~> 6.0)
41
+ activesupport (4.2.4)
42
+ i18n (~> 0.7)
43
+ json (~> 1.7, >= 1.7.7)
44
+ minitest (~> 5.1)
45
+ thread_safe (~> 0.3, >= 0.3.4)
46
+ tzinfo (~> 1.1)
47
+ arel (6.0.3)
48
+ builder (3.2.2)
49
+ delayed_job (4.0.6)
50
+ activesupport (>= 3.0, < 5.0)
51
+ delayed_job_active_record (4.0.3)
52
+ activerecord (>= 3.0, < 5.0)
53
+ delayed_job (>= 3.0, < 4.1)
54
+ erubis (2.7.0)
55
+ globalid (0.3.6)
56
+ activesupport (>= 4.1.0)
57
+ i18n (0.7.0)
58
+ json (1.8.3)
59
+ loofah (2.0.3)
60
+ nokogiri (>= 1.5.9)
61
+ mail (2.6.3)
62
+ mime-types (>= 1.16, < 3)
63
+ mime-types (2.6.1)
64
+ mini_portile (0.6.2)
65
+ minitest (5.8.0)
66
+ nokogiri (1.6.6.2)
67
+ mini_portile (~> 0.6.0)
68
+ rack (1.6.4)
69
+ rack-test (0.6.3)
70
+ rack (>= 1.0)
71
+ rails (4.2.4)
72
+ actionmailer (= 4.2.4)
73
+ actionpack (= 4.2.4)
74
+ actionview (= 4.2.4)
75
+ activejob (= 4.2.4)
76
+ activemodel (= 4.2.4)
77
+ activerecord (= 4.2.4)
78
+ activesupport (= 4.2.4)
79
+ bundler (>= 1.3.0, < 2.0)
80
+ railties (= 4.2.4)
81
+ sprockets-rails
82
+ rails-deprecated_sanitizer (1.0.3)
83
+ activesupport (>= 4.2.0.alpha)
84
+ rails-dom-testing (1.0.7)
85
+ activesupport (>= 4.2.0.beta, < 5.0)
86
+ nokogiri (~> 1.6.0)
87
+ rails-deprecated_sanitizer (>= 1.0.1)
88
+ rails-html-sanitizer (1.0.2)
89
+ loofah (~> 2.0)
90
+ railties (4.2.4)
91
+ actionpack (= 4.2.4)
92
+ activesupport (= 4.2.4)
93
+ rake (>= 0.8.7)
94
+ thor (>= 0.18.1, < 2.0)
95
+ rake (10.4.2)
96
+ sprockets (3.3.3)
97
+ rack (~> 1.0)
98
+ sprockets-rails (2.3.2)
99
+ actionpack (>= 3.0)
100
+ activesupport (>= 3.0)
101
+ sprockets (>= 2.8, < 4.0)
102
+ sqlite3 (1.3.10)
103
+ thor (0.19.1)
104
+ thread_safe (0.3.5)
105
+ tzinfo (1.2.2)
106
+ thread_safe (~> 0.1)
107
+
108
+ PLATFORMS
109
+ ruby
110
+
111
+ DEPENDENCIES
112
+ delayed_job_progress!
113
+ sqlite3
@@ -0,0 +1,20 @@
1
+ Copyright 2015 Oleg
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,87 @@
1
+ # DelayedJobProgress
2
+ [![Gem Version](https://img.shields.io/gem/v/delayed_job_progress.svg?style=flat)](http://rubygems.org/gems/delayed_job_progress) [![Gem Downloads](https://img.shields.io/gem/dt/delayed_job_progress.svg?style=flat)](http://rubygems.org/gems/delayed_job_progress) [![Build Status](https://img.shields.io/travis/GBH/delayed_job_progress.svg?style=flat)](https://travis-ci.org/GBH/delayed_job_progress)
3
+
4
+ Extension for `Delayed::Job` that allows better tracking of jobs!
5
+
6
+ ## Setup
7
+
8
+ * add to Gemfile: `gem 'delayed_job_progress'`
9
+ * `bundle install`
10
+ * `rails g delayed_job:progress`
11
+ * `rake db:migrate`
12
+
13
+ ## Configuration and Usage
14
+
15
+ Consider this:
16
+
17
+ ```ruby
18
+ class User < ActiveRecord::Base
19
+ # convenient relationship to grab associated jobs
20
+ has_many :jobs, :as => :record, :class_name => 'DelayedJob'
21
+ end
22
+ ```
23
+
24
+ Creating a delayed job:
25
+ ```ruby
26
+ user = User.find(123)
27
+ user.delay.do_things!
28
+ ```
29
+
30
+ If you're using custom jobs you'll need to do something like this:
31
+ ```ruby
32
+ class CustomUserJob < Struct.new(:user_id)
33
+ def enqueue(job)
34
+ job.record = User.find(user_id)
35
+ job.identifier = 'unique_identifier'
36
+ job.progress_max = 100
37
+ job.progress_current = 0
38
+ end
39
+
40
+ def before(job)
41
+ @job = job
42
+ @user = job.record
43
+ end
44
+
45
+ def perform
46
+ @job.update_column(:progress_state, 'working')
47
+ (0..100).each do |i|
48
+ @user.do_a_thing(i)
49
+ @job.update_column(:progress_current, i)
50
+ end
51
+ @job.update_column(:progress_state, 'complete')
52
+ end
53
+ end
54
+
55
+ Delayed::Job.enqueue CustomUserJob.new(123)
56
+ ```
57
+
58
+ This will create a Delayed::Job record:
59
+ ```ruby
60
+ -> user.jobs
61
+ => [#<Delayed::Job>]
62
+ ```
63
+
64
+ That job knows about object that spawned it:
65
+ ```ruby
66
+ -> Delayed::Job.last.record
67
+ => #<User>
68
+ ```
69
+
70
+ `Delayed::Job` records now have new attributes:
71
+ * `progress_max` - default is `100`. You can change it to whatever during `enqueue`.
72
+ * `progress_current` - default is `0`. You can manually increment it while job is running. Will be set to `process_max` when job completes.
73
+ * `progress_state` - default is `nil`. Optional informational string.
74
+ * `completed_at` - when job is done this timestamp is recorded.
75
+
76
+ This extension also introduces worker setting that keeps completed jobs around. This way you can keep list of completed jobs for a while. If you want to remove them, you need to `.destroy(:force)` them.
77
+ ```
78
+ Delayed::Worker.destroy_completed_jobs = false
79
+ ```
80
+
81
+ ## Jobs Controller
82
+
83
+ - `GET /jobs` - List all jobs. Can filter based on associated record via `record_type` and `record_id` parameters. `identifier` parameter can be used as well
84
+ - `GET /jobs/<id>` - Status of a job. Will see all the Delayed::Job attributes including things like progress
85
+ - `DELETE /jobs/<id>` - If job is stuck/failed, we can remove it
86
+ - `POST /jobs/<id>/reload` - Restart failed job
87
+
@@ -0,0 +1,24 @@
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
+ APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
8
+ load 'rails/tasks/engine.rake'
9
+
10
+ load 'rails/tasks/statistics.rake'
11
+
12
+ Bundler::GemHelper.install_tasks
13
+
14
+ require 'rake/testtask'
15
+
16
+ Rake::TestTask.new(:test) do |t|
17
+ t.libs << 'lib'
18
+ t.libs << 'test'
19
+ t.pattern = 'test/**/*_test.rb'
20
+ t.verbose = false
21
+ end
22
+
23
+
24
+ task default: :test
@@ -0,0 +1,49 @@
1
+ module DelayedJobProgress
2
+ class JobsController < ActionController::Base
3
+
4
+ before_action :load_job, :only => [:show, :destroy, :reload]
5
+
6
+ def index
7
+ jobs = Delayed::Job
8
+ if params[:record_type].present? && params[:record_id].present?
9
+ jobs = jobs.where(:record_type => params[:record_type], :record_id => params[:record_id])
10
+ end
11
+ if params[:identifier].present?
12
+ jobs = jobs.where(:identifier => params[:identifier])
13
+ end
14
+
15
+ render :json => jobs.all
16
+ end
17
+
18
+ def show
19
+ render :json => @job
20
+ end
21
+
22
+ def destroy
23
+ @job.destroy(:force)
24
+ head :no_content
25
+ end
26
+
27
+ def reload
28
+ @job.update_columns(
29
+ :run_at => Time.now,
30
+ :failed_at => nil,
31
+ :completed_at => nil,
32
+ :locked_by => nil,
33
+ :locked_at => nil,
34
+ :last_error => nil,
35
+ :attempts => 0
36
+ )
37
+ render :json => @job
38
+ end
39
+
40
+ protected
41
+
42
+ def load_job
43
+ @job = Delayed::Job.find(params[:id])
44
+ rescue ActiveRecord::RecordNotFound
45
+ render :json => {:error => 'Job not found'}, :status => :not_found
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails 4 gems installed from the root of your application.
3
+
4
+ ENGINE_ROOT = File.expand_path('../..', __FILE__)
5
+ ENGINE_PATH = File.expand_path('../../lib/delayed_job_progress/engine', __FILE__)
6
+
7
+ # Set up gems listed in the Gemfile.
8
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
9
+ require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
10
+
11
+ require 'rails/all'
12
+ require 'rails/engine/commands'
@@ -0,0 +1,5 @@
1
+ DelayedJobProgress::Engine.routes.draw do
2
+ resources :jobs do
3
+ post :reload, :on => :member
4
+ end
5
+ end
@@ -0,0 +1,25 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+
3
+ # Maintain your gem's version:
4
+ require "delayed_job_progress/version"
5
+
6
+ # Describe your gem and declare its dependencies:
7
+ Gem::Specification.new do |s|
8
+ s.name = 'delayed_job_progress'
9
+ s.version = DelayedJobProgress::VERSION
10
+ s.authors = ["Oleg Khabarov"]
11
+ s.email = ["oleg@khabarov.ca"]
12
+ s.homepage = "http://github.com/GBH/delayed_job_progress"
13
+ s.summary = "DelayedJob Progress extension"
14
+ s.description = "Ability to track jobs against ActiveRecord objects"
15
+ s.license = 'MIT'
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = Dir["test/**/*"]
19
+
20
+ s.add_dependency 'rails', '>= 4.0.0', '< 5'
21
+ s.add_dependency 'delayed_job', '>= 4.0'
22
+ s.add_dependency 'delayed_job_active_record', '>= 4.0'
23
+
24
+ s.add_development_dependency 'sqlite3'
25
+ end
@@ -0,0 +1,7 @@
1
+ require_relative 'delayed_job_progress/version'
2
+ require_relative 'delayed_job_progress/engine'
3
+ require_relative 'delayed_job_progress/error'
4
+
5
+ module DelayedJobProgress
6
+
7
+ end
@@ -0,0 +1,13 @@
1
+ require 'delayed_job'
2
+ require 'delayed_job_active_record'
3
+
4
+ module DelayedJobProgress
5
+ class Engine < ::Rails::Engine
6
+ isolate_namespace DelayedJobProgress
7
+
8
+ config.to_prepare do
9
+ require_relative 'extensions/job'
10
+ require_relative 'extensions/worker'
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,4 @@
1
+ module DelayedJobProgress
2
+ class DuplicateJobError < StandardError
3
+ end
4
+ end
@@ -0,0 +1,42 @@
1
+ Delayed::Backend::ActiveRecord::Job.class_eval do
2
+
3
+ belongs_to :record, :polymorphic => true
4
+
5
+ # When enqueue hook is executed, we need to look if there's an identifier provided
6
+ # If there's another Delayed::Job out there with same identifier we need to bail
7
+ def hook(name, *args)
8
+ super
9
+
10
+ if name == :enqueue && self.identifier.present?
11
+ if Delayed::Job.where(:identifier => self.identifier, :completed_at => nil, :failed_at => nil).any?
12
+ raise DelayedJobProgress::DuplicateJobError, "Delayed::Job with identifier: #{self.identifier} already present"
13
+ end
14
+ end
15
+ end
16
+
17
+ # Associating AR record with Delayed::Job. Generally when doing: `something.delay.method`
18
+ def payload_object=(object)
19
+ if object.respond_to?(:object) && object.object.is_a?(ActiveRecord::Base)
20
+ self.record = object.object
21
+ end
22
+
23
+ super
24
+ end
25
+
26
+ def destroy_completed_jobs?
27
+ payload_object.respond_to?(:destroy_completed_jobs?) ?
28
+ payload_object.destroy_completed_jobs? :
29
+ Delayed::Worker.destroy_completed_jobs
30
+ end
31
+
32
+ def destroy(force_destroy = false)
33
+ if destroy_completed_jobs? || force_destroy
34
+ super()
35
+ else
36
+ update_columns(
37
+ :completed_at => Time.zone.now,
38
+ :progress_current => self.progress_max
39
+ )
40
+ end
41
+ end
42
+ end