sidekiq-runner 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,3 @@
1
+ module SidekiqRunner
2
+ VERSION = '0.0.3'
3
+ 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: []