Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch to minitest and convert the server to a Rails engine to match new plugins structure for Resque-Web #464

Open
wants to merge 32 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
9d025a9
Converted syntax to Minitest spec. Lots of ordering failures.
mattgibson Jan 6, 2015
85a7a2a
Fix broken env test and add a missing call to require test_helper
mattgibson Jan 6, 2015
5ba39c4
Fixed some tests
mattgibson Jan 7, 2015
928d1de
Moved the resetting stuff into a function that is called before every…
mattgibson Jan 7, 2015
727340f
Remove TODOs
mattgibson Jan 7, 2015
4de9e14
Fix comment
mattgibson Jan 7, 2015
72c1aae
Dummy Rails app loads. Tests all pass.
mattgibson Jan 7, 2015
8a89518
Remove mintest-bisect
mattgibson Jan 7, 2015
8164d2d
DB for dummy app
mattgibson Jan 7, 2015
6b72766
Ignore logs in the dummy app
mattgibson Jan 7, 2015
2f1f93b
Directory path in .gitignore
mattgibson Jan 7, 2015
8c320aa
Failing test for the presence of the schedule tab
mattgibson Jan 8, 2015
59290e0
Basic transfer of server content to new engine
mattgibson Dec 28, 2014
27cbfc5
Scheduler page tests work
mattgibson Jan 9, 2015
846ff94
Add all routes to engine file and fix tabs
mattgibson Jan 10, 2015
6218011
Tests for the delayed page and the job class page
mattgibson Jan 10, 2015
d44cc20
Working delayed and delayed job class pages
mattgibson Jan 10, 2015
b9711fa
Added tests and code up to requeue_with_params
mattgibson Jan 23, 2015
0c973d6
Delayed search
mattgibson Jan 23, 2015
28fd1f7
Cancel now path
mattgibson Jan 23, 2015
4f8e39a
Clear path
mattgibson Jan 23, 2015
c9a734f
Queue now path
mattgibson Jan 23, 2015
fc22491
Timestamp path
mattgibson Jan 23, 2015
0db7b46
Delete schedule when dynamic
mattgibson Jan 23, 2015
aa9f6c8
Delete when static
mattgibson Jan 23, 2015
428936d
Fix tests
mattgibson Jan 23, 2015
e1d61eb
Remove hardcoded paths from views
mattgibson Jan 23, 2015
0c7db2e
Remove old server
mattgibson Jan 24, 2015
6cff910
Make Rubocop happy
mattgibson Jan 25, 2015
d46ed7d
Add classes to tables
mattgibson Jan 25, 2015
4265204
Styling
mattgibson Jan 26, 2015
c4f436f
Styling
mattgibson Jan 26, 2015
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@ nbproject

.env
.env.*

/test/dummy/log/
1 change: 1 addition & 0 deletions lib/resque-scheduler.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# vim:fileencoding=utf-8
require_relative 'resque/scheduler'
require 'resque/scheduler/engine'

Resque.extend Resque::Scheduler::Extension
48 changes: 48 additions & 0 deletions lib/resque/scheduler/engine.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
require 'resque_web'

module ResqueWeb
module Plugins
module ResqueScheduler
class Engine < Rails::Engine
isolate_namespace ResqueWeb::Plugins::ResqueScheduler
paths['app'] << 'lib/resque/scheduler/engine/app'
paths['app/helpers'] << 'lib/resque/scheduler/engine/app/helpers'
paths['app/views'] << 'lib/resque/scheduler/engine/app/views'
paths['app/controllers'] << 'lib/resque/scheduler/'\
'engine/app/controllers'
end

Engine.routes do

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How different is this from describing routes in a dedicated config/routes.rb file ?

get 'schedule', to: 'schedules#index', as: 'schedules'
post 'schedule/requeue', to: 'schedules#requeue', as: 'requeue'
post 'schedule/requeue_with_params',
to: 'schedules#requeue_with_params',
as: 'requeue_with_params'
delete 'schedule', to: 'schedules#destroy', as: 'schedule'

get 'delayed', to: 'delayed#index', as: 'delayed'
get 'delayed/jobs/:klass',
to: 'delayed#jobs_klass',
as: 'delayed_job_class'
post 'delayed/search', to: 'delayed#search', as: 'delayed_search'
get 'delayed/:timestamp', to: 'delayed#timestamp', as: 'timestamp'
post 'delayed/queue_now', to: 'delayed#queue_now', as: 'queue_now'
post 'delayed/cancel_now', to: 'delayed#cancel_now', as: 'cancel_now'
post '/delayed/clear', to: 'delayed#clear', as: 'clear'
end

def self.engine_path
'/scheduler'
end

def self.tabs
[
{
'schedule' => Engine.app.url_helpers.schedules_path,
'delayed' => Engine.app.url_helpers.delayed_path
}
]
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
module ResqueWeb
module Plugins
module ResqueScheduler
class DelayedController < ResqueWeb::ApplicationController
def index
end

def jobs_klass
klass = Resque::Scheduler::Util.constantize(params[:klass])
@args = JSON.load(URI.decode(params[:args]))
@timestamps = Resque.scheduled_at(klass, *@args)
rescue
@timestamps = []
end

def search
@jobs = find_job(params[:search])
end

def cancel_now
klass = Resque::Scheduler::Util.constantize(params['klass'])
timestamp = params['timestamp']
args = Resque.decode params['args']
Resque.remove_delayed_job_from_timestamp(timestamp, klass, *args)
redirect_to Engine.app.url_helpers.delayed_path
end

def clear
Resque.reset_delayed_queue
redirect_to Engine.app.url_helpers.delayed_path
end

def queue_now
timestamp = params['timestamp'].to_i
if timestamp > 0
Resque::Scheduler.enqueue_delayed_items_for_timestamp(timestamp)
end
redirect_to ResqueWeb::Engine.app.url_helpers.overview_path
end

def timestamp
@timestamp = params[:timestamp].to_i
end

protected

def find_job(worker)
worker = worker.downcase
results = working_jobs_for_worker(worker)

dels = delayed_jobs_for_worker(worker)
results += dels.select do |j|
j['class'].downcase.include?(worker) &&
j.merge!('where_at' => 'delayed')
end

Resque.queues.each do |queue|
queued = Resque.peek(queue, 0, Resque.size(queue))
queued = [queued] unless queued.is_a?(Array)
results += queued.select do |j|
j['class'].downcase.include?(worker) &&
j.merge!('queue' => queue, 'where_at' => 'queued')
end
end

results
end

def working_jobs_for_worker(worker)
[].tap do |results|
working = [*Resque.working]
work = working.select do |w|
w.job && w.job['payload'] &&
w.job['payload']['class'].downcase.include?(worker)
end
work.each do |w|
results += [
w.job['payload'].merge(
'queue' => w.job['queue'], 'where_at' => 'working'
)
]
end
end
end

def delayed_jobs_for_worker(_worker)
[].tap do |dels|
schedule_size = Resque.delayed_queue_schedule_size
Resque.delayed_queue_peek(0, schedule_size).each do |d|
Resque.delayed_timestamp_peek(
d, 0, Resque.delayed_timestamp_size(d)).each do |j|
dels << j.merge!('timestamp' => d)
end
end
end
end
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
module ResqueWeb
module Plugins
module ResqueScheduler
class SchedulesController < ResqueWeb::ApplicationController
def index
Resque.reload_schedule! if Resque::Scheduler.dynamic
end

def destroy
if Resque::Scheduler.dynamic
job_name = params['job_name'] || params[:job_name]
Resque.remove_schedule(job_name)
end
redirect_to Engine.app.url_helpers.schedules_path
end

def requeue
@job_name = params['job_name'] || params[:job_name]
config = Resque.schedule[@job_name]
@parameters = config['parameters'] || config[:parameters]
if @parameters
render 'requeue-params'
else
Resque::Scheduler.enqueue_from_config(config)
redirect_to ResqueWeb::Engine.app.url_helpers.overview_path
end
end

def requeue_with_params
job_name = params['job_name'] || params[:job_name]
config = Resque.schedule[job_name]
# Build args hash from post data (removing the job name)
submitted_args = params.reject do |key, _value|
%w(job_name action controller).include?(key)
end

# Merge constructed args hash with existing args hash for
# the job, if it exists
config_args = config['args'] || config[:args] || {}
config_args = config_args.merge(submitted_args)

# Insert the args hash into config and queue the resque job
config = config.merge('args' => config_args)
Resque::Scheduler.enqueue_from_config(config)
redirect_to ResqueWeb::Engine.app.url_helpers.overview_path
end
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module ResqueWeb
module Plugins
module ResqueScheduler
module DelayedHelper
def format_time(t)
t.strftime('%Y-%m-%d %H:%M:%S %z')
end
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
module ResqueWeb
module Plugins
module ResqueScheduler
module SchedulesHelper
def scheduled_in_this_env?(name)
return true if Resque.schedule[name]['rails_env'].nil?
rails_env(name).split(/[\s,]+/).include?(Resque::Scheduler.env)
end

def rails_env(name)
Resque.schedule[name]['rails_env']
end

def schedule_interval_every(every)
every = [*every]
s = 'every: ' << every.first

return s unless every.length > 1

s << ' ('
meta = every.last.map do |key, value|
"#{key.to_s.gsub(/_/, ' ')} #{value}"
end
s << meta.join(', ') << ')'
end

def schedule_interval(config)
if config['every']
schedule_interval_every(config['every'])
elsif config['cron']
'cron: ' + config['cron'].to_s
else
'Not currently scheduled'
end
end

def schedule_class(config)
if config['class'].nil? && !config['custom_job_class'].nil?
config['custom_job_class']
else
config['class']
end
end

def queue_from_class_name(class_name)
Resque.queue_from_class(
Resque::Scheduler::Util.constantize(class_name)
)
end
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<% # per_page was added in 1.23.1; gems which add to resque-server don't pass that variable along so it would crash %>
<% # without a default value %>
<% per_page ||= 20 %>
<% if start - per_page >= 0 || start + per_page <= size %>
<p class='pagination'>
<% if start + per_page <= size %>
<a href="<%= current_page %>?start=<%= start + per_page %>" class='more'>&laquo;
Next</a>
<% end %>

<% (size / per_page.to_f - 1).ceil.downto(0).each do |page_num| %>
<% if start == page_num * per_page %>
<%= page_num %>
<% else %>
<a href="<%= current_page %>?start=<%= page_num * per_page %>"> <%= page_num %></a>
<% end %>
<% end %>

<% if start - per_page >= 0 %>
<a href="<%= current_page %>?start=<%= start - per_page %>" class='less'>Previous &raquo;</a>
<% end %>
</p>
<% end %>
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<form method="POST" action="<%= u 'delayed/search' %>">
<form method="POST" action="<%= delayed_search_path %>">
<input type='input' name='search' value="<%= params[:search] %>"/>
<input type='submit' value='Search'/>
</form>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<h1>Delayed Jobs</h1>
<%- size = resque.delayed_queue_schedule_size %>
<%- size = Resque.delayed_queue_schedule_size %>

<%= scheduler_view :search_form, layout: false %>
<%= render partial: 'search_form' %>

<p class='intro'>
This list below contains the timestamps for scheduled delayed jobs.
Expand All @@ -12,7 +12,7 @@
Showing <%= start = params[:start].to_i %> to <%= start + 20 %> of <b><%= size %></b> timestamps
</p>

<table>
<table class="table table-bordered">
<tr>
<th></th>
<th>Timestamp</th>
Expand All @@ -21,28 +21,28 @@
<th>Args</th>
<th>All schedules</th>
</tr>
<% resque.delayed_queue_peek(start, 20).each do |timestamp| %>
<% Resque.delayed_queue_peek(start, 20).each do |timestamp| %>
<tr>
<td>
<form action="<%= u "/delayed/queue_now" %>" method="post">
<form action="<%= queue_now_path %>" method="post">
<input type="hidden" name="timestamp" value="<%= timestamp.to_i %>">
<input type="submit" value="Queue now">
<input type="submit" value="Queue now" class="btn btn-default">
</form>
</td>
<td><a href="<%= u "delayed/#{timestamp}" %>"><%= format_time(Time.at(timestamp)) %></a></td>
<td><%= delayed_timestamp_size = resque.delayed_timestamp_size(timestamp) %></td>
<% job = resque.delayed_timestamp_peek(timestamp, 0, 1).first %>
<td><a href="<%= delayed_path timestamp: timestamp %>"><%= format_time(Time.at(timestamp)) %></a></td>
<td><%= delayed_timestamp_size = Resque.delayed_timestamp_size(timestamp) %></td>
<% job = Resque.delayed_timestamp_peek(timestamp, 0, 1).first %>
<td>
<% if job && delayed_timestamp_size == 1 %>
<%= h(job['class']) %>
<% else %>
<a href="<%= u "delayed/#{timestamp}" %>">see details</a>
<a href="<%= delayed_path timestamp: timestamp %>">see details</a>
<% end %>
</td>
<td><%= h(job['args'].inspect) if job && delayed_timestamp_size == 1 %></td>
<td>
<% if job %>
<a href="<%=u URI("/delayed/jobs/#{job['class']}?args=" + URI.encode(job['args'].to_json)) %>">All schedules</a>
<a href="<%= delayed_job_class_path klass: job['class'], args: URI.encode(job['args'].to_json) %>">All schedules</a>
<% end %>
</td>
</tr>
Expand All @@ -51,9 +51,10 @@

<% if size > 0 %>
<br>
<form method="POST" action="<%=u 'delayed/clear'%>" class='clear-delayed'>
<form method="POST" action="<%= clear_path %>" class='clear-delayed'>
<input type='submit' name='' value='Clear Delayed Jobs' />
</form>
<% end %>

<%= partial :next_more, :start => start, :size => size %>
<%= render partial: 'next_more', locals: { :start => start, :size => size } %>

Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<h1>Delayed jobs scheduled for <%= params[:klass] %> (<%= @args %>)</h1>

<table class='jobs'>
<tr>
<th>Timestamp</th>
</tr>

<% @timestamps.each do |t| %>
<tr>
<td>
<%= Time.at(t) %>
</td>
</tr>
<% end %>
<% if @timestamps.empty? %>
<tr>
<td class='no-data'>There are no such jobs scheduled.</td>
</tr>
<% end %>
</table>
Loading