├── .gitignore ├── Gemfile ├── README.md ├── app ├── controllers │ └── sidekiq_sandbox_controller.rb ├── helpers │ └── sidekiq_sandbox_helper.rb ├── views │ └── sidekiq_sandbox │ │ └── index.html.erb └── workers │ └── sandbox_worker.rb ├── config ├── locales │ ├── en.yml │ └── ja.yml ├── routes.rb └── sidekiq.yml.example ├── init.rb ├── lib └── redmine_sidekiq │ ├── admin_constraint.rb │ ├── configure.rb │ └── rails.rb └── test ├── functional └── sidekiq_sandbox_controller_test.rb └── test_helper.rb /.gitignore: -------------------------------------------------------------------------------- 1 | /config/*.yml 2 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | gem 'sidekiq' 2 | gem 'sinatra' 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Redmine Sidekiq 2 | =============== 3 | 4 | Background jobs will use the [Sidekiq](https://github.com/mperham/sidekiq) on Redmine. 5 | You can Monitoring easily used by [Sidekiq plugin](http://www.redmine.org/plugins/redmine_sidekiq). 6 | 7 | ## Features 8 | 9 | * Administrator can use the Sidekiq Web UI from the top menu. 10 | * Add to autoload_paths of the Plugin `/app/workers`. 11 | * IMPORTANT: Anyone trying to use the sidekiq `:delay` method, use `:sidekiq_delay` instead because for former has clashes with Redmine safe attributes. There is NO change for `:delay_for` and `:delay_until` methods. 12 | 13 | ## Installation 14 | 15 | ``` 16 | $ git clone https://github.com/ogom/redmine_sidekiq ./plugins/redmine_sidekiq 17 | $ bundle install 18 | ``` 19 | 20 | ## Usage 21 | 22 | ### Worker 23 | 24 | Add worker classes in `/plugins/[your plugin]/app/workers`. 25 | 26 | ``` 27 | class HardWorker 28 | include Sidekiq::Worker 29 | def perform(name, count) 30 | # do something 31 | end 32 | end 33 | ``` 34 | 35 | ### Sidekiq Web UI 36 | 37 | It appears in the top menu. 38 | 39 | ![top menu](https://f.cloud.github.com/assets/471923/491345/149e41a4-ba19-11e2-8374-cc3a7861e915.png) 40 | 41 | 42 | ## Example 43 | 44 | Example of Sidekiq worker. 45 | 46 | ``` 47 | ./plugins/redmine_sidekiq/app/workers/sandbox_worker.rb 48 | ``` 49 | 50 | ### Sandbox Web UI 51 | Enqueue from the Web UI. 52 | 53 | ``` 54 | http://[redmine]/sidekiq/sandbox 55 | ``` 56 | 57 | Enqueue, click the `perform_async(*args)` of the Jobs. 58 | 59 | ![sandbox](https://f.cloud.github.com/assets/471923/491347/24df23c6-ba19-11e2-9a31-1dadae4795c7.png) 60 | 61 | 62 | ### CLI 63 | 64 | Enqueue from the command line. 65 | 66 | ``` 67 | $ bin/rails runner 'SandboxWorker.perform_async' 68 | ``` 69 | 70 | ## License 71 | 72 | * MIT 73 | -------------------------------------------------------------------------------- /app/controllers/sidekiq_sandbox_controller.rb: -------------------------------------------------------------------------------- 1 | class SidekiqSandboxController < ApplicationController 2 | unloadable 3 | before_filter :require_admin 4 | 5 | def index 6 | @stats = Sidekiq::Stats.new 7 | end 8 | 9 | def perform_async 10 | name = params['name'] 11 | count = params['count'] 12 | jid = SandboxWorker.perform_async(name, count) 13 | flash[:notice] = "Enqueued job id: #{jid}" if jid 14 | redirect_to :action => 'index' 15 | end 16 | 17 | def perform_in 18 | interval = params['interval'].to_i ||= 2 19 | jid = SandboxWorker.perform_in(interval.minute) 20 | flash[:notice] = "Enqueued job id: #{jid}" if jid 21 | redirect_to :action => 'index' 22 | end 23 | 24 | def perform_at 25 | interval = params['interval'].to_i ||= 2 26 | jid = SandboxWorker.perform_at(interval.minute.from_now) 27 | flash[:notice] = "Enqueued job id: #{jid}" if jid 28 | redirect_to :action => 'index' 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /app/helpers/sidekiq_sandbox_helper.rb: -------------------------------------------------------------------------------- 1 | module SidekiqSandboxHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/views/sidekiq_sandbox/index.html.erb: -------------------------------------------------------------------------------- 1 |

<%= l :sidekiq %>

2 |

Sandbox

3 | 4 |
5 | 6 |

Stats

7 | 8 |
stats = Sidekiq::Stats.new
9 | 10 |

Gets the number of jobs that have been processed.

11 |
stats.processed # => <%= @stats.processed %>
12 | 13 |

The number of jobs that have failed.

14 |
stats.failed # => <%= @stats.failed %>
15 | 16 |

The queues with name and number enqueued.

17 |
stats.queues # => <%= @stats.queues %>
18 | 19 |

The number of jobs enqueued in all queues (does NOT include retries and scheduled jobs).

20 |
stats.enqueued # => <%= @stats.enqueued %>
21 | 22 |   23 | 24 |

Jobs

25 | 26 |

The standard.

27 |
<%= link_to('perform_async(*args)', sidekiq_sandbox_perform_async_path, method: :post) %>
28 | 29 |

The Scheduled Jobs by interval.

30 |
<%= link_to('perform_in(interval, *args)', sidekiq_sandbox_perform_in_path(interval: 1), method: :post) %>
31 | 32 |

The Scheduled Jobs by timestamp.

33 |
<%= link_to('perform_at(timestamp, *args)', sidekiq_sandbox_perform_at_path(interval: 1), method: :post) %>
34 | 35 |

The job will fail.

36 |
<%= link_to('perform_async()', sidekiq_sandbox_perform_async_path(name: :failed), method: :post) %>
37 | -------------------------------------------------------------------------------- /app/workers/sandbox_worker.rb: -------------------------------------------------------------------------------- 1 | class SandboxWorker 2 | include Sidekiq::Worker 3 | sidekiq_options retry: 2 4 | 5 | def perform(name=nil, count=nil) 6 | puts 'Doing sandbox work' 7 | raise 'Failed sandbox work' if name == 'failed' 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /config/locales/en.yml: -------------------------------------------------------------------------------- 1 | en: 2 | sidekiq: Sidekiq 3 | -------------------------------------------------------------------------------- /config/locales/ja.yml: -------------------------------------------------------------------------------- 1 | ja: 2 | sidekiq: Sidekiq 3 | -------------------------------------------------------------------------------- /config/routes.rb: -------------------------------------------------------------------------------- 1 | require 'sidekiq/web' 2 | require 'redmine_sidekiq/admin_constraint' 3 | 4 | RedmineApp::Application.routes.draw do 5 | mount Sidekiq::Web => '/sidekiq', :constraints => RedmineSidekiq::AdminConstraint.new 6 | 7 | match '/sidekiq/sandbox', to: 'sidekiq_sandbox#index', via: :get 8 | match '/sidekiq/sandbox/perform_async', to: 'sidekiq_sandbox#perform_async', via: :post 9 | match '/sidekiq/sandbox/perform_in', to: 'sidekiq_sandbox#perform_in', via: :post 10 | match '/sidekiq/sandbox/perform_at', to: 'sidekiq_sandbox#perform_at', via: :post 11 | end 12 | -------------------------------------------------------------------------------- /config/sidekiq.yml.example: -------------------------------------------------------------------------------- 1 | production: 2 | redis: 3 | url: redis://localhost:6379/8 4 | namespace: mynamespace 5 | -------------------------------------------------------------------------------- /init.rb: -------------------------------------------------------------------------------- 1 | $LOAD_PATH.unshift "#{File.dirname(__FILE__)}/lib" 2 | 3 | require 'redmine_sidekiq/configure' 4 | require 'redmine_sidekiq/rails' 5 | 6 | Redmine::Plugin.register :redmine_sidekiq do 7 | name 'Redmine Sidekiq plugin' 8 | description 'This is a Sidekiq plugin for Redmine' 9 | version '2.1.0' 10 | url 'https://github.com/ogom/redmine_sidekiq' 11 | author_url 'mailto:ogom@hotmail.co.jp' 12 | author 'ogom' 13 | 14 | menu :top_menu, :sidekiq, '/sidekiq', :if => Proc.new {User.current.admin} 15 | end 16 | -------------------------------------------------------------------------------- /lib/redmine_sidekiq/admin_constraint.rb: -------------------------------------------------------------------------------- 1 | module RedmineSidekiq 2 | class AdminConstraint 3 | def matches?(request) 4 | return false unless request.session[:user_id] 5 | user = User.find request.session[:user_id] 6 | user && user.admin? 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/redmine_sidekiq/configure.rb: -------------------------------------------------------------------------------- 1 | require 'sidekiq' 2 | 3 | # Enable extensions if sidekiq version > 4 4 | if Sidekiq::Extensions.respond_to?(:enable_delay!) 5 | Sidekiq::Extensions.enable_delay! 6 | end 7 | 8 | module RedmineSidekiq 9 | class Configure 10 | file = File.join(::Rails.root, 'plugins/redmine_sidekiq/config/sidekiq.yml') 11 | if File.exist?(file) 12 | config = YAML.load_file(file)[::Rails.env] 13 | redis_conf = config['redis'].symbolize_keys 14 | end 15 | 16 | Sidekiq.configure_server do |config| 17 | config.redis = redis_conf if redis_conf 18 | end 19 | 20 | Sidekiq.configure_client do |config| 21 | config.redis = redis_conf if redis_conf 22 | end 23 | 24 | Sidekiq::Extensions::ActiveRecord.module_eval do 25 | remove_method :delay if respond_to?(:delay) 26 | end 27 | 28 | Sidekiq::Extensions::ActionMailer.module_eval do 29 | remove_method :delay if respond_to?(:delay) 30 | end 31 | 32 | Sidekiq::Extensions::Klass.module_eval do 33 | remove_method :delay if respond_to?(:delay) 34 | end 35 | 36 | Sidekiq.remove_delay! if Sidekiq.methods.index(:remove_delay!) 37 | 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /lib/redmine_sidekiq/rails.rb: -------------------------------------------------------------------------------- 1 | module RedmineSidekiq 2 | class Rails 3 | Dir.glob(File.join(Redmine::Plugin.directory, '*')).sort.each do |directory| 4 | if File.directory?(directory) 5 | workers = File.join(directory, 'app', 'workers') 6 | if File.directory?(workers) 7 | ActiveSupport::Dependencies.autoload_paths += [workers] 8 | end 9 | end 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/functional/sidekiq_sandbox_controller_test.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../../test_helper', __FILE__) 2 | 3 | class SidekiqSandboxControllerTest < ActionController::TestCase 4 | # Replace this with your real tests. 5 | def test_truth 6 | assert true 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | # Load the Redmine helper 2 | require File.expand_path(File.dirname(__FILE__) + '/../../../test/test_helper') 3 | --------------------------------------------------------------------------------