sidekiq-runner 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/sidekiq-runner.rb +98 -0
- data/lib/sidekiq-runner/common_configuration.rb +46 -0
- data/lib/sidekiq-runner/god_configuration.rb +39 -0
- data/lib/sidekiq-runner/sidekiq_command_builder.rb +31 -0
- data/lib/sidekiq-runner/sidekiq_configuration.rb +115 -0
- data/lib/sidekiq-runner/sidekiq_instance.rb +48 -0
- data/lib/sidekiq-runner/tasks.rb +20 -0
- data/lib/sidekiq-runner/version.rb +3 -0
- metadata +80 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ca0010af09c70a83fb3d9a7e19bb1fab9ab8c2d7
|
4
|
+
data.tar.gz: 2a56f515a2abc4174eca0e222161facc262d45bc
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 30074809519b45508efeaa338146c1e601065f1e77c4d7df375d19e1ef67dfc4af440475f2643eb53146b3185092bd0ea361b944aa1683717471cfa2fa03c23f
|
7
|
+
data.tar.gz: c03238275cb23d3a27628abca14a087a22a0a9a519355525103392e05aed0f4039e87a3f7078fe8fdbb26d6c09e5057a434f1eae3d02d73ef0f5ea6d1c441eb8
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'sidekiq-runner/sidekiq_configuration'
|
2
|
+
require 'sidekiq-runner/god_configuration'
|
3
|
+
require 'sidekiq-runner/sidekiq_instance'
|
4
|
+
require 'sidekiq-runner/version'
|
5
|
+
|
6
|
+
module SidekiqRunner
|
7
|
+
def self.configure
|
8
|
+
yield SidekiqConfiguration.default if block_given?
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.configure_god
|
12
|
+
yield GodConfiguration.default if block_given?
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.start
|
16
|
+
sidekiq_config, god_config = get_all_settings
|
17
|
+
|
18
|
+
fail 'No sidekiq instances defined. There is nothing to run.' if sidekiq_config.empty?
|
19
|
+
|
20
|
+
abort 'God is running. I found an instance of a running god process. Please stop it manually and try again.' if god_alive?(god_config)
|
21
|
+
|
22
|
+
run(:start, sidekiq_config) do
|
23
|
+
puts 'Starting god.'
|
24
|
+
God::CLI::Run.new(god_config.options)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.stop
|
29
|
+
sidekiq_config, god_config = get_all_settings
|
30
|
+
|
31
|
+
run(:stop, sidekiq_config) do
|
32
|
+
God::EventHandler.load
|
33
|
+
|
34
|
+
if god_alive?(god_config)
|
35
|
+
puts "Stopping process #{god_config.process_name}."
|
36
|
+
|
37
|
+
# Stop all the processes
|
38
|
+
sidekiq_config.each_key do |name|
|
39
|
+
God::CLI::Command.new('stop', god_config.options, ['', name])
|
40
|
+
end
|
41
|
+
|
42
|
+
puts 'Terminating god.'
|
43
|
+
God::CLI::Command.new('terminate', god_config.options, [])
|
44
|
+
else
|
45
|
+
puts 'God is not running, so no need to stop it.'
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.settings
|
51
|
+
SidekiqConfiguration.get.to_hash
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def self.get_all_settings
|
57
|
+
[SidekiqConfiguration.get, GodConfiguration.get]
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.god_alive?(god_config)
|
61
|
+
puts 'Checking whether god is alive...'
|
62
|
+
|
63
|
+
require 'drb'
|
64
|
+
require 'god/socket'
|
65
|
+
DRb.start_service('druby://127.0.0.1:0')
|
66
|
+
server = DRbObject.new(nil, God::Socket.socket(god_config.port))
|
67
|
+
|
68
|
+
# ping server to ensure that it is responsive
|
69
|
+
begin
|
70
|
+
server.ping
|
71
|
+
rescue DRb::DRbConnError
|
72
|
+
return false
|
73
|
+
end
|
74
|
+
true
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.run(action, sidekiq_config)
|
78
|
+
begin
|
79
|
+
# Use this flag to actually load all of the god infrastructure
|
80
|
+
$load_god = true
|
81
|
+
require 'god'
|
82
|
+
require 'god/cli/run'
|
83
|
+
|
84
|
+
# Peform the action
|
85
|
+
yield if block_given?
|
86
|
+
cb = nil
|
87
|
+
rescue SystemExit => e
|
88
|
+
cb = e.success? ? "#{action}_success_cb" : "#{action}_error_cb"
|
89
|
+
ensure
|
90
|
+
if [:start, :stop].include? action
|
91
|
+
cb = "#{action}_success_cb" unless cb
|
92
|
+
cb = sidekiq_config.send(cb.to_sym)
|
93
|
+
cb.call if cb
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module SidekiqRunner
|
4
|
+
|
5
|
+
# common functions for GodConfiguration and Configuration classes
|
6
|
+
class CommonConfiguration
|
7
|
+
# this method MUST be reimplemented
|
8
|
+
def self.default
|
9
|
+
fail(NotImplementedError, "Method \"#{__method__}\" is not implemented in \"#{name}\" class. Please DO implement this method to be able to derive from CommonConfiguration class.")
|
10
|
+
end
|
11
|
+
|
12
|
+
RUNNER_ATTRIBUTES = []
|
13
|
+
CONFIG_FILE_ATTRIBUTES = []
|
14
|
+
|
15
|
+
@config_file = ''
|
16
|
+
|
17
|
+
def to_hash
|
18
|
+
Hash[CONFIG_FILE_ATTRIBUTES.map { |att| [att, send(att)] }]
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.get
|
22
|
+
config = default.dup
|
23
|
+
config.send :merge_config_file!
|
24
|
+
config.send :sane?
|
25
|
+
config
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def merge_config_file!
|
31
|
+
if File.exist?(config_file)
|
32
|
+
yml = YAML.load_file(config_file)
|
33
|
+
CONFIG_FILE_ATTRIBUTES.each do |k|
|
34
|
+
v = yml[k] || yml[k.to_s]
|
35
|
+
send("#{k}=", v) unless v.nil?
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
self
|
40
|
+
end
|
41
|
+
|
42
|
+
def sane?
|
43
|
+
end
|
44
|
+
|
45
|
+
end # class
|
46
|
+
end # module
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'sidekiq-runner/common_configuration'
|
2
|
+
|
3
|
+
module SidekiqRunner
|
4
|
+
class GodConfiguration < CommonConfiguration
|
5
|
+
def self.default
|
6
|
+
@default ||= GodConfiguration.new
|
7
|
+
end
|
8
|
+
|
9
|
+
RUNNER_ATTRIBUTES = [:config_file, :daemonize, :port, :syslog, :events, :options]
|
10
|
+
RUNNER_ATTRIBUTES.each { |att| attr_accessor att }
|
11
|
+
|
12
|
+
CONFIG_FILE_ATTRIBUTES = [:process_name, :interval, :stop_timeout, :log_file]
|
13
|
+
CONFIG_FILE_ATTRIBUTES.each { |att| attr_accessor att }
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@process_name = 'sidekiq'
|
17
|
+
@interval = 30
|
18
|
+
@stop_timeout = 30
|
19
|
+
@log_file = File.join(Dir.pwd, 'log', 'god.log')
|
20
|
+
|
21
|
+
@config_file = File.join(Dir.pwd, 'config', 'god.yml')
|
22
|
+
@daemonize = true
|
23
|
+
# This is going to be a part of the .sock file name e.g. "/tmp/god.17165.sock"
|
24
|
+
# Change this in the configuration file to be able to run multiple instances of god
|
25
|
+
@port = 17165
|
26
|
+
@syslog = true
|
27
|
+
@events = true
|
28
|
+
@options = {
|
29
|
+
daemonize: @daemonize,
|
30
|
+
port: @port,
|
31
|
+
syslog: @syslog,
|
32
|
+
events: @events,
|
33
|
+
config: File.expand_path("../#{@process_name}.god", __FILE__),
|
34
|
+
log: @log_file
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module SidekiqCommandBuilder
|
2
|
+
|
3
|
+
def self.build_start_command(sidekiq_config, skiq)
|
4
|
+
cmd = []
|
5
|
+
cmd << (skiq.bundle_env ? 'bundle exec sidekiq' : 'sidekiq')
|
6
|
+
cmd << '-d' if sidekiq_config.daemonize
|
7
|
+
cmd << "-c #{skiq.concurrency}"
|
8
|
+
cmd << "-e #{Rails.env}" if defined?(Rails)
|
9
|
+
cmd << '-v' if skiq.verbose
|
10
|
+
cmd << "-L #{skiq.logfile}"
|
11
|
+
cmd << "-P #{skiq.pidfile}"
|
12
|
+
cmd << "-r #{skiq.requirefile}" if skiq.requirefile
|
13
|
+
|
14
|
+
skiq.queues.each do |q, w|
|
15
|
+
cmd << "-q #{q},#{w.to_s}"
|
16
|
+
end
|
17
|
+
|
18
|
+
cmd.join(' ')
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.build_stop_command(skiq, timeout)
|
22
|
+
cmd = []
|
23
|
+
cmd << (skiq.bundle_env ? 'bundle exec sidekiqctl' : 'sidekiqctl')
|
24
|
+
cmd << 'stop'
|
25
|
+
cmd << skiq.pidfile
|
26
|
+
cmd << timeout
|
27
|
+
|
28
|
+
cmd.join(' ')
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'sidekiq-runner/common_configuration'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module SidekiqRunner
|
5
|
+
class SidekiqConfiguration < CommonConfiguration
|
6
|
+
include Enumerable
|
7
|
+
|
8
|
+
RUNNER_ATTRIBUTES = [:config_file, :daemonize]
|
9
|
+
RUNNER_ATTRIBUTES.each { |att| attr_accessor att }
|
10
|
+
|
11
|
+
attr_reader :sidekiqs
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@config_file = File.join(Dir.pwd, 'config', 'sidekiq.yml')
|
15
|
+
@daemonize = true
|
16
|
+
|
17
|
+
@sidekiqs = {}
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.default
|
21
|
+
@default ||= SidekiqConfiguration.new
|
22
|
+
end
|
23
|
+
|
24
|
+
def each(&block)
|
25
|
+
@sidekiqs.each(&block)
|
26
|
+
end
|
27
|
+
|
28
|
+
def each_key(&block)
|
29
|
+
@sidekiqs.each_key(&block)
|
30
|
+
end
|
31
|
+
|
32
|
+
def empty?
|
33
|
+
@sidekiqs.empty?
|
34
|
+
end
|
35
|
+
|
36
|
+
# DELETEME in the future
|
37
|
+
# Redefined and kept for bakward compatibility
|
38
|
+
def queue(name, weight = 1)
|
39
|
+
# Create a default sidekiq instance when no instances were created
|
40
|
+
fail 'Sidekiq instances hash does not seem to be empty.
|
41
|
+
It means you are using the newer syntax in the initializer to create at least one instance.
|
42
|
+
Therefore you should not be using the old queue() function.' unless @sidekiqs.empty?
|
43
|
+
|
44
|
+
add_instance('sidekiq_default') do |skiq|
|
45
|
+
skiq.add_queue('default')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def add_instance(name)
|
50
|
+
skiq = SidekiqInstance.new(name)
|
51
|
+
yield skiq if block_given?
|
52
|
+
|
53
|
+
fail "Sidekick instance with the name of #{name} already exists! No duplicates please." if @sidekiqs.has_key?(name)
|
54
|
+
|
55
|
+
FileUtils.mkdir_p(File.dirname(skiq.pidfile))
|
56
|
+
FileUtils.mkdir_p(File.dirname(skiq.logfile))
|
57
|
+
|
58
|
+
@sidekiqs[name] = skiq
|
59
|
+
|
60
|
+
skiq
|
61
|
+
end
|
62
|
+
|
63
|
+
%w(start stop).each do |action|
|
64
|
+
%w(success error).each do |state|
|
65
|
+
attr_reader "#{action}_#{state}_cb".to_sym
|
66
|
+
|
67
|
+
define_method("on_#{action}_#{state}") do |&block|
|
68
|
+
instance_variable_set("@#{action}_#{state}_cb".to_sym, block)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def merge_config_file!
|
76
|
+
sidekiqs_common_config = {}
|
77
|
+
yml = {}
|
78
|
+
|
79
|
+
if File.exist?(config_file)
|
80
|
+
yml = YAML.load_file(config_file)
|
81
|
+
# Get sidekiq config common for all instances
|
82
|
+
SidekiqInstance::CONFIG_FILE_ATTRIBUTES.each do |k|
|
83
|
+
v = yml[k] || yml[k.to_s]
|
84
|
+
sidekiqs_common_config[k] = v if v
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# Backwards compatibility
|
89
|
+
# Get sidekiq pidfile and logfile if no sidekiq instance was specified
|
90
|
+
SidekiqInstance::INDIVIDUAL_FILE_ATTRIBUTES.each do |k|
|
91
|
+
v = yml[k] || yml[k.to_s]
|
92
|
+
sidekiqs_common_config[k] = v if v
|
93
|
+
end
|
94
|
+
|
95
|
+
@sidekiqs.each do |name, skiq|
|
96
|
+
# Symbolize keys in yml hash
|
97
|
+
if yml[name] && yml[name].is_a?(Hash)
|
98
|
+
yml_config = Hash[yml[name].map { |k, v| [k.to_sym, v] }]
|
99
|
+
end
|
100
|
+
# Merge common and specific sidekiq instance configs
|
101
|
+
# Sidekiq instances not defined in the initializer but present in yml will be ignored
|
102
|
+
final_skiq_config = yml_config ? sidekiqs_common_config.merge(yml_config) : sidekiqs_common_config
|
103
|
+
skiq.merge_config!(final_skiq_config)
|
104
|
+
skiq.sane?
|
105
|
+
end
|
106
|
+
|
107
|
+
self
|
108
|
+
end
|
109
|
+
|
110
|
+
def sane?
|
111
|
+
fail 'No requirefile given and not in Rails env.' if !defined?(Rails) && !requirefile
|
112
|
+
fail 'No sidekiq instances defined. Nothing to run.' if @sidekiqs.empty?
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module SidekiqRunner
|
2
|
+
class SidekiqInstance
|
3
|
+
|
4
|
+
CONFIG_FILE_ATTRIBUTES = [:bundle_env, :chdir, :requirefile, :concurrency, :verbose]
|
5
|
+
INDIVIDUAL_FILE_ATTRIBUTES = [:pidfile, :logfile]
|
6
|
+
CONFIG_FILE_ATTRIBUTES.concat(INDIVIDUAL_FILE_ATTRIBUTES).each { |att| attr_accessor att }
|
7
|
+
|
8
|
+
attr_reader :name, :queues
|
9
|
+
|
10
|
+
def initialize(name)
|
11
|
+
fail "No sidekiq instance name given!" if name.empty?
|
12
|
+
|
13
|
+
@name = name
|
14
|
+
@queues = []
|
15
|
+
|
16
|
+
@bundle_env = true
|
17
|
+
@daemonize = true
|
18
|
+
@chdir = nil
|
19
|
+
@requirefile = nil
|
20
|
+
@pidfile = File.join(Dir.pwd, 'tmp', 'pids', "#{@name}.pid")
|
21
|
+
@logfile = File.join(Dir.pwd, 'log', "#{@name}.log")
|
22
|
+
@concurrency = 4
|
23
|
+
@verbose = false
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
def add_queue(queue_name, weight = 1)
|
28
|
+
fail "Cannot add the queue. The name is empty!" if queue_name.empty?
|
29
|
+
fail "Cannot add the queue. The weight is not an integer!" unless weight.is_a? Integer
|
30
|
+
fail "Cannot add the queue. The queue with \"#{queue_name}\" name already exist" if @queues.any?{|arr| arr.first == queue_name}
|
31
|
+
@queues << [queue_name, weight]
|
32
|
+
end
|
33
|
+
|
34
|
+
def sane?
|
35
|
+
fail "No queues given for #{@name}!" if @queues.empty?
|
36
|
+
end
|
37
|
+
|
38
|
+
def merge_config!(skiq)
|
39
|
+
CONFIG_FILE_ATTRIBUTES.each do |k|
|
40
|
+
v = nil || skiq[k]
|
41
|
+
send("#{k}=", v) unless v.nil?
|
42
|
+
end
|
43
|
+
|
44
|
+
self
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'sidekiq-runner'
|
2
|
+
|
3
|
+
rails_env = Rake::Task.task_defined?(:environment) ? [:environment] : []
|
4
|
+
|
5
|
+
namespace :sidekiqrunner do
|
6
|
+
desc 'Start sidekiq-runner instances'
|
7
|
+
task start: rails_env do
|
8
|
+
puts 'Starting sidekiq instances...'
|
9
|
+
SidekiqRunner.start
|
10
|
+
end
|
11
|
+
|
12
|
+
desc 'Stop sidekiq-runner instances'
|
13
|
+
task stop: rails_env do
|
14
|
+
puts 'Gracefully shutting down sidekiq instances...'
|
15
|
+
SidekiqRunner.stop
|
16
|
+
end
|
17
|
+
|
18
|
+
desc 'Restart sidekiq-runner instances'
|
19
|
+
task restart: ['sidekiq:stop', 'sidekiq:start']
|
20
|
+
end
|
metadata
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sidekiq-runner
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- FlavourSys Technology GmbH
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-07-29 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '10.3'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '10.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: god
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.13'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.13'
|
41
|
+
description: A little collection of Sidekiq start/stop rake tasks and configuration
|
42
|
+
framework
|
43
|
+
email: technology@flavoursys.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- lib/sidekiq-runner.rb
|
49
|
+
- lib/sidekiq-runner/common_configuration.rb
|
50
|
+
- lib/sidekiq-runner/god_configuration.rb
|
51
|
+
- lib/sidekiq-runner/sidekiq_command_builder.rb
|
52
|
+
- lib/sidekiq-runner/sidekiq_configuration.rb
|
53
|
+
- lib/sidekiq-runner/sidekiq_instance.rb
|
54
|
+
- lib/sidekiq-runner/tasks.rb
|
55
|
+
- lib/sidekiq-runner/version.rb
|
56
|
+
homepage: http://flavoursys.com
|
57
|
+
licenses:
|
58
|
+
- MIT
|
59
|
+
metadata: {}
|
60
|
+
post_install_message:
|
61
|
+
rdoc_options: []
|
62
|
+
require_paths:
|
63
|
+
- lib
|
64
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
requirements: []
|
75
|
+
rubyforge_project:
|
76
|
+
rubygems_version: 2.2.2
|
77
|
+
signing_key:
|
78
|
+
specification_version: 4
|
79
|
+
summary: Sidekiq rake task collection
|
80
|
+
test_files: []
|