delayed_job_mongoid_web 1.1.3

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 (29) hide show
  1. data/.document +5 -0
  2. data/Gemfile +15 -0
  3. data/LICENSE.txt +20 -0
  4. data/README.markdown +61 -0
  5. data/Rakefile +53 -0
  6. data/VERSION +1 -0
  7. data/bin/delayed_job_mongoid_web +10 -0
  8. data/delayed_job_mongoid_web.gemspec +95 -0
  9. data/lib/delayed_job_mongoid_web/application/app.rb +156 -0
  10. data/lib/delayed_job_mongoid_web/application/public/images/poll.png +0 -0
  11. data/lib/delayed_job_mongoid_web/application/public/javascripts/application.js +64 -0
  12. data/lib/delayed_job_mongoid_web/application/public/javascripts/jquery-1.7.1.min.js +4 -0
  13. data/lib/delayed_job_mongoid_web/application/public/javascripts/jquery.relatize_date.js +117 -0
  14. data/lib/delayed_job_mongoid_web/application/public/stylesheets/reset.css +44 -0
  15. data/lib/delayed_job_mongoid_web/application/public/stylesheets/style.css +89 -0
  16. data/lib/delayed_job_mongoid_web/application/views/enqueued.haml +10 -0
  17. data/lib/delayed_job_mongoid_web/application/views/error.haml +2 -0
  18. data/lib/delayed_job_mongoid_web/application/views/failed.haml +14 -0
  19. data/lib/delayed_job_mongoid_web/application/views/job.haml +42 -0
  20. data/lib/delayed_job_mongoid_web/application/views/layout.haml +23 -0
  21. data/lib/delayed_job_mongoid_web/application/views/next_more.haml +6 -0
  22. data/lib/delayed_job_mongoid_web/application/views/overview.haml +25 -0
  23. data/lib/delayed_job_mongoid_web/application/views/pending.haml +12 -0
  24. data/lib/delayed_job_mongoid_web/application/views/stats.haml +20 -0
  25. data/lib/delayed_job_mongoid_web/application/views/working.haml +9 -0
  26. data/lib/delayed_job_mongoid_web.rb +1 -0
  27. data/test/helper.rb +18 -0
  28. data/test/test_delayed_job_mongoid_web.rb +30 -0
  29. metadata +238 -0
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source "http://rubygems.org"
2
+ gem "sinatra", '>= 0.9.2'
3
+ gem "haml", '~> 3.1.3'
4
+ gem 'activerecord', '> 3.0.0'
5
+ gem 'mongoid', '> 3.0.0'
6
+ gem 'delayed_job_mongoid', '~> 2.0.0'
7
+ gem 'rdoc'
8
+
9
+ group :development do
10
+ gem "shoulda", ">= 0"
11
+ gem "bundler", "> 1.0.0"
12
+ gem "jeweler", "~> 1.6.4"
13
+ gem "simplecov", "~> 0.7.1"
14
+ gem "rack-test", ">= 0"
15
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Erick Schmitt
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.
data/README.markdown ADDED
@@ -0,0 +1,61 @@
1
+ delayed_job_web
2
+ ===============
3
+
4
+ A [resque][0] inspired (read: stolen) interface for delayed_job.
5
+ This gem is written to work with rails 3 applications using
6
+ activerecord.
7
+
8
+ Some features:
9
+
10
+ * Easily view jobs enqueued, working, pending, and failed.
11
+ * Queue any single job. or all pending jobs, to run immediately.
12
+ * Remove a failed job, or easily remove all failed jobs.
13
+ * Watch delayed_job operation with live ajax polling.
14
+
15
+ Quick Start For Rails 3 Applications
16
+ ------------------------------------
17
+
18
+ Add the dependency to your Gemfile
19
+
20
+ ```ruby
21
+ gem "delayed_job_mongoid_web"
22
+ ```
23
+
24
+ Install it...
25
+
26
+ ```ruby
27
+ bundle
28
+ ```
29
+
30
+ Add a route to your application for accessing the interface
31
+
32
+ ```ruby
33
+ match "/delayed_job" => DelayedJobMongoidWeb, :anchor => false
34
+ ```
35
+
36
+ You probably want to password protect the interface, an easy way is to add something like this your config.ru file
37
+
38
+ ```ruby
39
+ if Rails.env.production?
40
+ DelayedJobMongoidWeb.use Rack::Auth::Basic do |username, password|
41
+ username == 'username' && password == 'password'
42
+ end
43
+ end
44
+ ```
45
+
46
+ The Interface - Yea, a ripoff of resque-web
47
+ ------------------------------------
48
+
49
+ ![Screen shot](http://dl.dropbox.com/u/1506097/Screenshots/delayed_job_web_1.png)
50
+
51
+ ![Screen shot](http://dl.dropbox.com/u/1506097/Screenshots/delayed_job_web_2.png)
52
+
53
+
54
+ Author
55
+ ------
56
+
57
+ Erick Schmitt - [@ejschmitt][1]
58
+
59
+
60
+ [0]: https://github.com/defunkt/resque
61
+ [1]: http://twitter.com/ejschmitt
data/Rakefile ADDED
@@ -0,0 +1,53 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "delayed_job_web"
18
+ gem.homepage = "http://github.com/ejschmitt/delayed_job_web"
19
+ gem.license = "MIT"
20
+ gem.summary = "Web interface for delayed_job"
21
+ gem.description = "Web interface for delayed_job inspired by resque"
22
+ gem.email = "ejschmitt@gmail.com"
23
+ gem.authors = ["Erick Schmitt"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rake/testtask'
29
+ Rake::TestTask.new(:test) do |test|
30
+ test.libs << 'lib' << 'test'
31
+ test.pattern = 'test/**/test_*.rb'
32
+ test.verbose = true
33
+ end
34
+
35
+ # require 'rcov/rcovtask'
36
+ # Rcov::RcovTask.new do |test|
37
+ # test.libs << 'test'
38
+ # test.pattern = 'test/**/test_*.rb'
39
+ # test.verbose = true
40
+ # test.rcov_opts << '--exclude "gems/*"'
41
+ # end
42
+
43
+ task :default => :test
44
+
45
+ require 'rdoc/task'
46
+ Rake::RDocTask.new do |rdoc|
47
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
48
+
49
+ rdoc.rdoc_dir = 'rdoc'
50
+ rdoc.title = "delayed_job_web #{version}"
51
+ rdoc.rdoc_files.include('README*')
52
+ rdoc.rdoc_files.include('lib/**/*.rb')
53
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.1.2
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ begin
4
+ require 'delayed_job_web/application/app.rb'
5
+ rescue LoadError => e
6
+ require 'rubygems'
7
+ path = File.expand_path '../../lib', __FILE__
8
+ $:.unshift(path) if File.directory?(path) && !$:.include?(path)
9
+ require 'delayed_job_web/application/app.rb'
10
+ end
@@ -0,0 +1,95 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "delayed_job_mongoid_web"
8
+ s.version = "1.1.3"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Erick Schmitt", "Rob Dingwell"]
12
+ s.date = "2012-05-18"
13
+ s.description = "Web interface for delayed_job inspired by resque"
14
+ s.email = "ejschmitt@gmail.com"
15
+ s.executables = ["delayed_job_mongoid_web"]
16
+ s.extra_rdoc_files = [
17
+ "LICENSE.txt",
18
+ "README.markdown"
19
+ ]
20
+ s.files = [
21
+ ".document",
22
+ "Gemfile",
23
+ "LICENSE.txt",
24
+ "README.markdown",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "bin/delayed_job_mongoid_web",
28
+ "delayed_job_mongoid_web.gemspec",
29
+ "lib/delayed_job_mongoid_web.rb",
30
+ "lib/delayed_job_mongoid_web/application/app.rb",
31
+ "lib/delayed_job_mongoid_web/application/public/images/poll.png",
32
+ "lib/delayed_job_mongoid_web/application/public/javascripts/application.js",
33
+ "lib/delayed_job_mongoid_web/application/public/javascripts/jquery-1.7.1.min.js",
34
+ "lib/delayed_job_mongoid_web/application/public/javascripts/jquery.relatize_date.js",
35
+ "lib/delayed_job_mongoid_web/application/public/stylesheets/reset.css",
36
+ "lib/delayed_job_mongoid_web/application/public/stylesheets/style.css",
37
+ "lib/delayed_job_mongoid_web/application/views/enqueued.haml",
38
+ "lib/delayed_job_mongoid_web/application/views/error.haml",
39
+ "lib/delayed_job_mongoid_web/application/views/failed.haml",
40
+ "lib/delayed_job_mongoid_web/application/views/job.haml",
41
+ "lib/delayed_job_mongoid_web/application/views/layout.haml",
42
+ "lib/delayed_job_mongoid_web/application/views/next_more.haml",
43
+ "lib/delayed_job_mongoid_web/application/views/overview.haml",
44
+ "lib/delayed_job_mongoid_web/application/views/pending.haml",
45
+ "lib/delayed_job_mongoid_web/application/views/stats.haml",
46
+ "lib/delayed_job_mongoid_web/application/views/working.haml",
47
+ "test/helper.rb",
48
+ "test/test_delayed_job_mongoid_web.rb"
49
+ ]
50
+ s.homepage = "http://github.com/rdingwell/delayed_job_mongoid_web"
51
+ s.licenses = ["MIT"]
52
+ s.require_paths = ["lib"]
53
+ s.rubygems_version = "1.8.22"
54
+ s.summary = "Web interface for delayed_job"
55
+
56
+ if s.respond_to? :specification_version then
57
+ s.specification_version = 3
58
+
59
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
60
+ s.add_runtime_dependency(%q<sinatra>, [">= 0.9.2"])
61
+ s.add_runtime_dependency(%q<haml>, ["~> 3.1.3"])
62
+ s.add_runtime_dependency(%q<activerecord>, ["> 3.0.0"])
63
+ s.add_runtime_dependency(%q<delayed_job>, ["> 2.0.3"])
64
+ s.add_runtime_dependency(%q<rdoc>, [">= 0"])
65
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
66
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
67
+ s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
68
+ s.add_development_dependency(%q<rcov>, [">= 0"])
69
+ s.add_development_dependency(%q<rack-test>, [">= 0"])
70
+ else
71
+ s.add_dependency(%q<sinatra>, [">= 0.9.2"])
72
+ s.add_dependency(%q<haml>, ["~> 3.1.3"])
73
+ s.add_dependency(%q<activerecord>, ["> 3.0.0"])
74
+ s.add_dependency(%q<delayed_job>, ["> 2.0.3"])
75
+ s.add_dependency(%q<rdoc>, [">= 0"])
76
+ s.add_dependency(%q<shoulda>, [">= 0"])
77
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
78
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
79
+ s.add_dependency(%q<rcov>, [">= 0"])
80
+ s.add_dependency(%q<rack-test>, [">= 0"])
81
+ end
82
+ else
83
+ s.add_dependency(%q<sinatra>, [">= 0.9.2"])
84
+ s.add_dependency(%q<haml>, ["~> 3.1.3"])
85
+ s.add_dependency(%q<activerecord>, ["> 3.0.0"])
86
+ s.add_dependency(%q<delayed_job>, ["> 2.0.3"])
87
+ s.add_dependency(%q<rdoc>, [">= 0"])
88
+ s.add_dependency(%q<shoulda>, [">= 0"])
89
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
90
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
91
+ s.add_dependency(%q<rcov>, [">= 0"])
92
+ s.add_dependency(%q<rack-test>, [">= 0"])
93
+ end
94
+ end
95
+
@@ -0,0 +1,156 @@
1
+ require 'sinatra/base'
2
+ require 'active_support'
3
+ require 'active_record'
4
+ require 'delayed_job'
5
+ require 'haml'
6
+
7
+ class DelayedJobMongoidWeb < Sinatra::Base
8
+ set :root, File.dirname(__FILE__)
9
+ set :static, true
10
+ set :public_folder, File.expand_path('../public', __FILE__)
11
+ set :views, File.expand_path('../views', __FILE__)
12
+ set :haml, { :format => :html5 }
13
+
14
+ def current_page
15
+ url_path request.path_info.sub('/','')
16
+ end
17
+
18
+ def start
19
+ params[:start].to_i
20
+ end
21
+
22
+ def per_page
23
+ 20
24
+ end
25
+
26
+ def url_path(*path_parts)
27
+ [ path_prefix, path_parts ].join("/").squeeze('/')
28
+ end
29
+ alias_method :u, :url_path
30
+
31
+ def path_prefix
32
+ request.env['SCRIPT_NAME']
33
+ end
34
+
35
+ def tabs
36
+ [
37
+ {:name => 'Overview', :path => '/overview'},
38
+ {:name => 'Enqueued', :path => '/enqueued'},
39
+ {:name => 'Working', :path => '/working'},
40
+ {:name => 'Pending', :path => '/pending'},
41
+ {:name => 'Failed', :path => '/failed'},
42
+ {:name => 'Stats', :path => '/stats'}
43
+ ]
44
+ end
45
+
46
+ def delayed_job
47
+ begin
48
+ Delayed::Job
49
+ rescue
50
+ false
51
+ end
52
+ end
53
+
54
+ get '/overview' do
55
+ if delayed_job
56
+ haml :overview
57
+ else
58
+ @message = "Unable to connected to Delayed::Job database"
59
+ haml :error
60
+ end
61
+ end
62
+
63
+ get '/stats' do
64
+ haml :stats
65
+ end
66
+
67
+ %w(enqueued working pending failed).each do |page|
68
+ get "/#{page}" do
69
+ @jobs = delayed_jobs(page.to_sym).order_by([:created_at, :desc]).skip(start).limit(per_page)
70
+ @all_jobs = delayed_jobs(page.to_sym)
71
+ haml page.to_sym
72
+ end
73
+ end
74
+
75
+ get "/remove/:id" do
76
+ delayed_job.find(params[:id]).delete
77
+ redirect back
78
+ end
79
+
80
+ get "/requeue/:id" do
81
+ job = delayed_job.find(params[:id])
82
+ job.update_attributes(:run_at => Time.now, :failed_at => nil)
83
+ redirect back
84
+ end
85
+
86
+ post "/failed/clear" do
87
+ delayed_job.destroy_all(delayed_job_sql(:failed))
88
+ redirect u('failed')
89
+ end
90
+
91
+ post "/requeue/all" do
92
+ delayed_jobs(:failed).update_all(:run_at => Time.now, :failed_at => nil)
93
+ redirect back
94
+ end
95
+
96
+ def delayed_jobs(type)
97
+ delayed_job_filter(delayed_job,type)
98
+ end
99
+
100
+ def delayed_job_filter(crit, type)
101
+ case type
102
+ when :enqueued
103
+ crit.where({})
104
+ when :working
105
+ crit.where({:locked_at.ne =>nil }) #'locked_at is not null'
106
+ when :failed
107
+ crit.where({:last_error.ne => nil }) # 'last_error is not null'
108
+ when :pending
109
+ crit.where({attempts: 0})
110
+ end
111
+ end
112
+
113
+ get "/?" do
114
+ redirect u(:overview)
115
+ end
116
+
117
+ def partial(template, local_vars = {})
118
+ @partial = true
119
+ haml(template.to_sym, {:layout => false}, local_vars)
120
+ ensure
121
+ @partial = false
122
+ end
123
+
124
+ %w(overview enqueued working pending failed stats) .each do |page|
125
+ get "/#{page}.poll" do
126
+ show_for_polling(page)
127
+ end
128
+
129
+ get "/#{page}/:id.poll" do
130
+ show_for_polling(page)
131
+ end
132
+ end
133
+
134
+ def poll
135
+ if @polling
136
+ text = "Last Updated: #{Time.now.strftime("%H:%M:%S")}"
137
+ else
138
+ text = "<a href='#{u(request.path_info)}.poll' rel='poll'>Live Poll</a>"
139
+ end
140
+ "<p class='poll'>#{text}</p>"
141
+ end
142
+
143
+ def show_for_polling(page)
144
+ content_type "text/html"
145
+ @polling = true
146
+ # show(page.to_sym, false).gsub(/\s{1,}/, ' ')
147
+ @jobs = delayed_jobs(page.to_sym)
148
+ haml(page.to_sym, {:layout => false})
149
+ end
150
+
151
+ end
152
+
153
+ # Run the app!
154
+ #
155
+ # puts "Hello, you're running delayed_job_web"
156
+ # DelayedJobWeb.run!
@@ -0,0 +1,64 @@
1
+ $(function() {
2
+ var poll_interval = 3;
3
+
4
+ var relatizer = function(){
5
+ var dt = $(this).text(), relatized = $.relatizeDate(this)
6
+ if ($(this).parents("a").length > 0 || $(this).is("a")) {
7
+ $(this).relatizeDate()
8
+ if (!$(this).attr('title')) {
9
+ $(this).attr('title', dt)
10
+ }
11
+ } else {
12
+ $(this)
13
+ .text('')
14
+ .append( $('<a href="#" class="toggle_format" title="' + dt + '" />')
15
+ .append('<span class="date_time">' + dt +
16
+ '</span><span class="relatized_time">' +
17
+ relatized + '</span>') )
18
+ }
19
+ };
20
+
21
+ $('.time').each(relatizer);
22
+
23
+ $('.time a.toggle_format .date_time').hide();
24
+
25
+ var format_toggler = function(){
26
+ $('.time a.toggle_format span').toggle();
27
+ $(this).attr('title', $('span:hidden',this).text());
28
+ return false;
29
+ };
30
+
31
+ $('.time a.toggle_format').click(format_toggler);
32
+
33
+ $('ul li.job').hover(function() {
34
+ $(this).addClass('hover');
35
+ }, function() {
36
+ $(this).removeClass('hover');
37
+ })
38
+
39
+ $('a.backtrace').click(function (e) {
40
+ e.preventDefault();
41
+ if($(this).prev('div.backtrace:visible').length > 0) {
42
+ $(this).next('div.backtrace').show();
43
+ $(this).prev('div.backtrace').hide();
44
+ } else {
45
+ $(this).next('div.backtrace').hide();
46
+ $(this).prev('div.backtrace').show();
47
+ }
48
+ });
49
+
50
+ $('a[rel=poll]').click(function(e) {
51
+ e.preventDefault();
52
+ var href = $(this).attr('href')
53
+ $(this).parent().text('Starting...')
54
+ $("#main").addClass('polling')
55
+
56
+ setInterval(function() {
57
+ $.ajax({dataType: 'text', type: 'get', url: href, success: function(data) {
58
+ $('#main').html(data);
59
+ }})
60
+ }, poll_interval * 1000)
61
+
62
+ return false
63
+ })
64
+ })