powerhome-resque-status 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,79 @@
1
+ <%= status_view :status_styles, :layout => false %>
2
+
3
+ <h1 class='wi'>Statuses</h1>
4
+
5
+ <%unless @statuses.empty?%>
6
+ <form method="POST" action="<%= u(:statuses) %>/clear" class='clear-failed'>
7
+ <input type='submit' name='' value='Clear Statuses' onclick='return confirm("Are you absolutely sure? This cannot be undone.");' />
8
+ </form>
9
+ <form method="POST" action="<%= u(:statuses) %>/clear/completed" class='clear-failed'>
10
+ <input type='submit' name='' value='Clear Completed Statuses' onclick='return confirm("Are you absolutely sure? This cannot be undone.");' />
11
+ </form>
12
+ <form method="POST" action="<%= u(:statuses) %>/clear/failed" class='clear-failed'>
13
+ <input type='submit' name='' value='Clear Failed Statuses' onclick='return confirm("Are you absolutely sure? This cannot be undone.");' />
14
+ </form>
15
+ <%end%>
16
+
17
+ <p class='intro'>These are recent jobs created with the Resque::Plugins::Status class</p>
18
+ <table class="vertically-top">
19
+ <tr>
20
+ <th>ID</th>
21
+ <th>Name</th>
22
+ <th>Status</th>
23
+ <th>Last Updated</th>
24
+ <th class="progress">% Complete</th>
25
+ <th>Message</th>
26
+ <th>Kill</th>
27
+ </tr>
28
+ <% unless @statuses.empty? %>
29
+ <% @statuses.each do |status| %>
30
+ <tr>
31
+ <td><a href="<%= u(:statuses) %>/<%= status.uuid %>"><%= status.uuid %></a></td>
32
+ <td><%= status.name %></td>
33
+ <td class="status status-<%= status.status %>"><%= status.status %></td>
34
+ <td class="time"><%= status.time.strftime("%Y/%m/%d %H:%M:%S %z") %></td>
35
+ <td class="progress">
36
+ <div class="progress-bar" style="width:<%= status.pct_complete %>%">&nbsp;</div>
37
+ <div class="progress-pct"><%= status.pct_complete ? "#{status.pct_complete}%" : '' %></div>
38
+ </td>
39
+ <td><%= status.message %></td>
40
+ <td><% if status.killable? %><a href="<%= u(:statuses) %>/<%= status.uuid %>/kill" class="kill">Kill</a><% end %></td>
41
+ </tr>
42
+ <% end %>
43
+ <% else %>
44
+ <tr>
45
+ <td colspan="7" class='no-data'>No Statuses right now...</td>
46
+ </tr>
47
+ <% end %>
48
+ </table>
49
+
50
+ <% unless @statuses.empty? %>
51
+ <%= partial :next_more, :start => @start, :size => @size, :per_page => per_page %>
52
+ <% end %>
53
+
54
+ <%= status_poll(@start) %>
55
+
56
+ <script type="text/javascript" charset="utf-8">
57
+ jQuery(function($) {
58
+
59
+ $('a.kill').click(function(e) {
60
+ e.preventDefault();
61
+ var $link = $(this),
62
+ url = $link.attr('href'),
63
+ confirmed = confirm("Are you sure you want to kill this job? There is no undo.");
64
+ if (confirmed) {
65
+ $link.animate({opacity: 0.5});
66
+ $.ajax({
67
+ url: url,
68
+ type: 'post',
69
+ success: function() {
70
+ $link.remove();
71
+ }
72
+ });
73
+ } else {
74
+ return false
75
+ }
76
+ });
77
+
78
+ });
79
+ </script>
@@ -0,0 +1,8 @@
1
+ require 'resque'
2
+
3
+ module Resque
4
+ autoload :JobWithStatus, "#{File.dirname(__FILE__)}/job_with_status"
5
+ module Plugins
6
+ autoload :Status, "#{File.dirname(__FILE__)}/plugins/status"
7
+ end
8
+ end
@@ -0,0 +1,88 @@
1
+ require 'resque/server'
2
+ require 'resque-status'
3
+
4
+ module Resque
5
+ module StatusServer
6
+
7
+ VIEW_PATH = File.join(File.dirname(__FILE__), 'server', 'views')
8
+ PER_PAGE = 50
9
+
10
+ def self.registered(app)
11
+
12
+ app.get '/statuses' do
13
+ @start = params[:start].to_i
14
+ @end = @start + (params[:per_page] || per_page) - 1
15
+ @statuses = Resque::Plugins::Status::Hash.statuses(@start, @end)
16
+ @size = Resque::Plugins::Status::Hash.count
17
+ status_view(:statuses)
18
+ end
19
+
20
+ app.get '/statuses/:id.js' do
21
+ @status = Resque::Plugins::Status::Hash.get(params[:id])
22
+ content_type :js
23
+ @status.json
24
+ end
25
+
26
+ app.get '/statuses/:id' do
27
+ @status = Resque::Plugins::Status::Hash.get(params[:id])
28
+ status_view(:status)
29
+ end
30
+
31
+ app.post '/statuses/:id/kill' do
32
+ Resque::Plugins::Status::Hash.kill(params[:id])
33
+ redirect u(:statuses)
34
+ end
35
+
36
+ app.post '/statuses/clear' do
37
+ Resque::Plugins::Status::Hash.clear
38
+ redirect u(:statuses)
39
+ end
40
+
41
+ app.post '/statuses/clear/completed' do
42
+ Resque::Plugins::Status::Hash.clear_completed
43
+ redirect u(:statuses)
44
+ end
45
+
46
+ app.post '/statuses/clear/failed' do
47
+ Resque::Plugins::Status::Hash.clear_failed
48
+ redirect u(:statuses)
49
+ end
50
+
51
+ app.get "/statuses.poll" do
52
+ content_type "text/plain"
53
+ @polling = true
54
+
55
+ @start = params[:start].to_i
56
+ @end = @start + (params[:per_page] || per_page) - 1
57
+ @statuses = Resque::Plugins::Status::Hash.statuses(@start, @end)
58
+ @size = Resque::Plugins::Status::Hash.count
59
+ status_view(:statuses, {:layout => false})
60
+ end
61
+
62
+ app.helpers do
63
+ def per_page
64
+ PER_PAGE
65
+ end
66
+
67
+ def status_view(filename, options = {}, locals = {})
68
+ erb(File.read(File.join(::Resque::StatusServer::VIEW_PATH, "#{filename}.erb")), options, locals)
69
+ end
70
+
71
+ def status_poll(start)
72
+ if @polling
73
+ text = "Last Updated: #{Time.now.strftime("%H:%M:%S")}"
74
+ else
75
+ text = "<a href='#{u(request.path_info)}.poll?start=#{start}' rel='poll'>Live Poll</a>"
76
+ end
77
+ "<p class='poll'>#{text}</p>"
78
+ end
79
+ end
80
+
81
+ app.tabs << "Statuses"
82
+
83
+ end
84
+
85
+ end
86
+ end
87
+
88
+ Resque::Server.register Resque::StatusServer
@@ -0,0 +1,62 @@
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
+ # stub: powerhome-resque-status 0.6.0 ruby lib
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "powerhome-resque-status".freeze
9
+ s.version = "0.6.0"
10
+
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
+ s.require_paths = ["lib".freeze]
13
+ s.authors = ["Aaron Quint".freeze]
14
+ s.date = "2020-08-25"
15
+ s.description = "resque-status is an extension to the resque queue system that provides simple trackable jobs. It provides a Resque::Plugins::Status::Hash class which can set/get the statuses of jobs and a Resque::Plugins::Status class that when included provides easily trackable/killable jobs.".freeze
16
+ s.email = "aaron@quirkey.com".freeze
17
+ s.extra_rdoc_files = [
18
+ "LICENSE",
19
+ "README.rdoc"
20
+ ]
21
+ s.files = [
22
+ ".document",
23
+ "Gemfile",
24
+ "Gemfile.lock",
25
+ "LICENSE",
26
+ "README.rdoc",
27
+ "Rakefile",
28
+ "examples/sleep_job.rb",
29
+ "init.rb",
30
+ "lib/resque-status.rb",
31
+ "lib/resque/job_with_status.rb",
32
+ "lib/resque/plugins/status.rb",
33
+ "lib/resque/plugins/status/hash.rb",
34
+ "lib/resque/server/views/status.erb",
35
+ "lib/resque/server/views/status_styles.erb",
36
+ "lib/resque/server/views/statuses.erb",
37
+ "lib/resque/status.rb",
38
+ "lib/resque/status_server.rb",
39
+ "powerhome-resque-status.gemspec",
40
+ "resque-status.gemspec",
41
+ "test/redis-test.conf",
42
+ "test/test_helper.rb",
43
+ "test/test_resque_plugins_status.rb",
44
+ "test/test_resque_plugins_status_hash.rb"
45
+ ]
46
+ s.homepage = "http://github.com/quirkey/resque-status".freeze
47
+ s.rubygems_version = "3.1.2".freeze
48
+ s.summary = "resque-status is an extension to the resque queue system that provides simple trackable jobs.".freeze
49
+
50
+ if s.respond_to? :specification_version then
51
+ s.specification_version = 4
52
+ end
53
+
54
+ if s.respond_to? :add_runtime_dependency then
55
+ s.add_runtime_dependency(%q<resque>.freeze, ["~> 1.19"])
56
+ s.add_development_dependency(%q<jeweler>.freeze, [">= 0"])
57
+ else
58
+ s.add_dependency(%q<resque>.freeze, ["~> 1.19"])
59
+ s.add_dependency(%q<jeweler>.freeze, [">= 0"])
60
+ end
61
+ end
62
+
@@ -0,0 +1,64 @@
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
+ # stub: resque-status 0.5.0 ruby lib
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "resque-status"
9
+ s.version = "0.5.0"
10
+
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
+ s.require_paths = ["lib"]
13
+ s.authors = ["Aaron Quint"]
14
+ s.date = "2015-03-18"
15
+ s.description = "resque-status is an extension to the resque queue system that provides simple trackable jobs. It provides a Resque::Plugins::Status::Hash class which can set/get the statuses of jobs and a Resque::Plugins::Status class that when included provides easily trackable/killable jobs."
16
+ s.email = "aaron@quirkey.com"
17
+ s.extra_rdoc_files = [
18
+ "LICENSE",
19
+ "README.rdoc"
20
+ ]
21
+ s.files = [
22
+ ".document",
23
+ "Gemfile",
24
+ "Gemfile.lock",
25
+ "LICENSE",
26
+ "README.rdoc",
27
+ "Rakefile",
28
+ "examples/sleep_job.rb",
29
+ "init.rb",
30
+ "lib/resque-status.rb",
31
+ "lib/resque/job_with_status.rb",
32
+ "lib/resque/plugins/status.rb",
33
+ "lib/resque/plugins/status/hash.rb",
34
+ "lib/resque/server/views/status.erb",
35
+ "lib/resque/server/views/status_styles.erb",
36
+ "lib/resque/server/views/statuses.erb",
37
+ "lib/resque/status.rb",
38
+ "lib/resque/status_server.rb",
39
+ "resque-status.gemspec",
40
+ "test/redis-test.conf",
41
+ "test/test_helper.rb",
42
+ "test/test_resque_plugins_status.rb",
43
+ "test/test_resque_plugins_status_hash.rb"
44
+ ]
45
+ s.homepage = "http://github.com/quirkey/resque-status"
46
+ s.rubyforge_project = "quirkey"
47
+ s.rubygems_version = "2.2.2"
48
+ s.summary = "resque-status is an extension to the resque queue system that provides simple trackable jobs."
49
+
50
+ if s.respond_to? :specification_version then
51
+ s.specification_version = 4
52
+
53
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
54
+ s.add_runtime_dependency(%q<resque>, [">= 1.19", "< 3"])
55
+ s.add_development_dependency(%q<jeweler>, [">= 0"])
56
+ else
57
+ s.add_dependency(%q<resque>, [">= 1.19", "< 3"])
58
+ s.add_dependency(%q<jeweler>, [">= 0"])
59
+ end
60
+ else
61
+ s.add_dependency(%q<resque>, [">= 1.19", "< 3"])
62
+ s.add_dependency(%q<jeweler>, [">= 0"])
63
+ end
64
+ end
@@ -0,0 +1,125 @@
1
+ # Redis configuration file example
2
+
3
+ # By default Redis does not run as a daemon. Use 'yes' if you need it.
4
+ # Note that Redis will write a pid file in /var/run/redis.pid when daemonized.
5
+ daemonize yes
6
+
7
+ # When run as a daemon, Redis write a pid file in /var/run/redis.pid by default.
8
+ # You can specify a custom pid file location here.
9
+ pidfile ./test/redis-test.pid
10
+
11
+ # Accept connections on the specified port, default is 6379
12
+ port 9736
13
+
14
+ # If you want you can bind a single interface, if the bind option is not
15
+ # specified all the interfaces will listen for connections.
16
+ #
17
+ # bind 127.0.0.1
18
+
19
+ # Close the connection after a client is idle for N seconds (0 to disable)
20
+ timeout 300
21
+
22
+ # Save the DB on disk:
23
+ #
24
+ # save <seconds> <changes>
25
+ #
26
+ # Will save the DB if both the given number of seconds and the given
27
+ # number of write operations against the DB occurred.
28
+ #
29
+ # In the example below the behaviour will be to save:
30
+ # after 900 sec (15 min) if at least 1 key changed
31
+ # after 300 sec (5 min) if at least 10 keys changed
32
+ # after 60 sec if at least 10000 keys changed
33
+ save 900 1
34
+ save 300 10
35
+ save 60 10000
36
+
37
+ # The filename where to dump the DB
38
+ dbfilename dump.rdb
39
+
40
+ # For default save/load DB in/from the working directory
41
+ # Note that you must specify a directory not a file name.
42
+ dir ./test/
43
+
44
+ # Set server verbosity to 'debug'
45
+ # it can be one of:
46
+ # debug (a lot of information, useful for development/testing)
47
+ # notice (moderately verbose, what you want in production probably)
48
+ # warning (only very important / critical messages are logged)
49
+ loglevel debug
50
+
51
+ # Specify the log file name. Also the empty string can be used to force
52
+ # Redis to log on the standard output. Note that if you use standard
53
+ # output for logging but daemonize, logs will be sent to /dev/null
54
+ logfile ""
55
+
56
+ # Set the number of databases. The default database is DB 0, you can select
57
+ # a different one on a per-connection basis using SELECT <dbid> where
58
+ # dbid is a number between 0 and 'databases'-1
59
+ databases 16
60
+
61
+ ################################# REPLICATION #################################
62
+
63
+ # Master-Slave replication. Use slaveof to make a Redis instance a copy of
64
+ # another Redis server. Note that the configuration is local to the slave
65
+ # so for example it is possible to configure the slave to save the DB with a
66
+ # different interval, or to listen to another port, and so on.
67
+
68
+ # slaveof <masterip> <masterport>
69
+
70
+ ################################## SECURITY ###################################
71
+
72
+ # Require clients to issue AUTH <PASSWORD> before processing any other
73
+ # commands. This might be useful in environments in which you do not trust
74
+ # others with access to the host running redis-server.
75
+ #
76
+ # This should stay commented out for backward compatibility and because most
77
+ # people do not need auth (e.g. they run their own servers).
78
+
79
+ # requirepass foobared
80
+
81
+ ################################### LIMITS ####################################
82
+
83
+ # Set the max number of connected clients at the same time. By default there
84
+ # is no limit, and it's up to the number of file descriptors the Redis process
85
+ # is able to open. The special value '0' means no limts.
86
+ # Once the limit is reached Redis will close all the new connections sending
87
+ # an error 'max number of clients reached'.
88
+
89
+ # maxclients 128
90
+
91
+ # Don't use more memory than the specified amount of bytes.
92
+ # When the memory limit is reached Redis will try to remove keys with an
93
+ # EXPIRE set. It will try to start freeing keys that are going to expire
94
+ # in little time and preserve keys with a longer time to live.
95
+ # Redis will also try to remove objects from free lists if possible.
96
+ #
97
+ # If all this fails, Redis will start to reply with errors to commands
98
+ # that will use more memory, like SET, LPUSH, and so on, and will continue
99
+ # to reply to most read-only commands like GET.
100
+ #
101
+ # WARNING: maxmemory can be a good idea mainly if you want to use Redis as a
102
+ # 'state' server or cache, not as a real DB. When Redis is used as a real
103
+ # database the memory usage will grow over the weeks, it will be obvious if
104
+ # it is going to use too much memory in the long run, and you'll have the time
105
+ # to upgrade. With maxmemory after the limit is reached you'll start to get
106
+ # errors for write operations, and this may even lead to DB inconsistency.
107
+
108
+ # maxmemory <bytes>
109
+
110
+ ############################### ADVANCED CONFIG ###############################
111
+
112
+ # Use object sharing. Can save a lot of memory if you have many common
113
+ # string in your dataset, but performs lookups against the shared objects
114
+ # pool so it uses more CPU and can be a bit slower. Usually it's a good
115
+ # idea.
116
+ #
117
+ # When object sharing is enabled (shareobjects yes) you can use
118
+ # shareobjectspoolsize to control the size of the pool used in order to try
119
+ # object sharing. A bigger pool size will lead to better sharing capabilities.
120
+ # In general you want this value to be at least the double of the number of
121
+ # very common strings you have in your dataset.
122
+ #
123
+ # WARNING: object sharing is experimental, don't enable this feature
124
+ # in production before of Redis 1.0-stable. Still please try this feature in
125
+ # your development environment so that we can test it better.
@@ -0,0 +1,98 @@
1
+ require 'bundler/setup'
2
+ require 'resque-status'
3
+
4
+ require 'minitest/autorun'
5
+ require 'mocha/setup'
6
+
7
+ #
8
+ # make sure we can run redis
9
+ #
10
+
11
+ if !system("which redis-server")
12
+ puts '', "** can't find `redis-server` in your path"
13
+ puts "** try running `sudo rake install`"
14
+ abort ''
15
+ end
16
+
17
+ #
18
+ # start our own redis when the tests start,
19
+ # kill it when they end
20
+ #
21
+
22
+
23
+ class << Minitest
24
+ def exit(*args)
25
+ pid = `ps -e -o pid,command | grep [r]edis.*9736`.split(" ")[0]
26
+ puts "Killing test redis server..."
27
+ Process.kill("KILL", pid.to_i)
28
+ super
29
+ end
30
+ end
31
+
32
+ dir = File.expand_path("../", __FILE__)
33
+ puts "Starting redis for testing at localhost:9736..."
34
+ result = `rm -f #{dir}/dump.rdb && redis-server #{dir}/redis-test.conf`
35
+ raise "Redis failed to start: #{result}" unless $?.success?
36
+ Resque.redis = 'localhost:9736/1'
37
+
38
+ #### Fixtures
39
+
40
+ class WorkingJob
41
+
42
+ include Resque::Plugins::Status
43
+
44
+ def perform
45
+ total = options['num']
46
+ (1..total).each do |num|
47
+ at(num, total, "At #{num}")
48
+ end
49
+ end
50
+
51
+ end
52
+
53
+ class ErrorJob
54
+
55
+ include Resque::Plugins::Status
56
+
57
+ def perform
58
+ raise "I'm a bad little job"
59
+ end
60
+
61
+ end
62
+
63
+ class KillableJob
64
+ include Resque::Plugins::Status
65
+
66
+ def perform
67
+ Resque.redis.set("#{uuid}:iterations", 0)
68
+ 100.times do |num|
69
+ Resque.redis.incr("#{uuid}:iterations")
70
+ at(num, 100, "At #{num} of 100")
71
+ end
72
+ end
73
+
74
+ end
75
+
76
+ class BasicJob
77
+ include Resque::Plugins::Status
78
+ end
79
+
80
+ class FailureJob
81
+ include Resque::Plugins::Status
82
+
83
+ def perform
84
+ failed("I'm such a failure")
85
+ end
86
+ end
87
+
88
+ class NeverQueuedJob
89
+ include Resque::Plugins::Status
90
+
91
+ def self.before_enqueue(*args)
92
+ false
93
+ end
94
+
95
+ def perform
96
+ # will never get called
97
+ end
98
+ end