sidekiq-runner 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []