sidekiq-nag 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,7 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ .DS_Store
6
+
7
+ vendor/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in sidekiq-nag.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Gary Greyling
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,48 @@
1
+ # Sidekiq::Nag
2
+
3
+ A Sidekiq extention that posts messages in Campfire when queues move slowly. A great way to prempt support calls and keep things flowing :)
4
+
5
+ ## How it works
6
+
7
+ Sidekiq-nag adds middleware to Sidekiq that timestamps jobs as they enter the queue. When the nag rake task is run it inspects the oldest job in the queue and checks whether its been waiting in the queue for longer than the number of minutes you've configured as the timeout.
8
+ If the job has been in the queue for longer than the timeout then Sidekiq-nag posts a message in Campfire letting you know that things aren't as great as you'd like them to be :)
9
+
10
+ ## Installation
11
+
12
+ Add this line to your application's Gemfile:
13
+
14
+ gem 'sidekiq-nag'
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install sidekiq-nag
23
+
24
+ ## Configuration
25
+
26
+ Add a `sidekiq-nag.yml` file to the `config/` directory that looks like this:
27
+
28
+ queues:
29
+ foo_app_critical_queue: 10
30
+ foo_app_low_priority_queue: 30
31
+
32
+ campfire:
33
+ token: NoaTOEX23...
34
+ subdomain: foo3
35
+ room: TheZone
36
+
37
+ The timeout entered next to each queue name is specified in minutes.
38
+
39
+ Nag provides you with a rake task that runs the queue checking and Campfire notification.
40
+ The final step in getting it to work is to setup a cron that runs `rake sidekiq-nag:nag` at intervals smaller than the timeouts you've specified in the config file. We run it once every 2 minutes :)
41
+
42
+ ## Contributing
43
+
44
+ 1. Fork it
45
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
46
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
47
+ 4. Push to the branch (`git push origin my-new-feature`)
48
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,27 @@
1
+ module Sidekiq::Nag
2
+ class Config
3
+ attr_reader :queues, :campfire
4
+
5
+ def initialize
6
+ @queues = raw_yaml['queues']
7
+ @campfire = raw_yaml['campfire']
8
+ end
9
+
10
+ def room
11
+ campfire['room']
12
+ end
13
+
14
+ def token
15
+ campfire['token']
16
+ end
17
+
18
+ def subdomain
19
+ campfire['subdomain']
20
+ end
21
+
22
+ private
23
+ def raw_yaml
24
+ @raw_yaml ||= YAML::load_file(Rails.root + 'config/sidekiq-nag.yml')
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,12 @@
1
+ module Sidekiq
2
+ module Nag
3
+ module Middleware
4
+ class Timestamper
5
+ def call(worker, msg, queue)
6
+ msg.merge!('enqueued_at' => Time.now.to_f.to_s)
7
+ yield
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,42 @@
1
+ class Sidekiq::Nag::Nagger
2
+ def nag
3
+ Sidekiq.redis do |conn|
4
+ Sidekiq::Nag::Config.new.queues.each do |queue_name, timeout|
5
+ queue = NaggableQueue.new(conn, queue_name)
6
+
7
+ next unless queue.exists?
8
+ next unless queue.oldest_job_has_timestamp?
9
+
10
+ if queue.oldest_job_timestamp.to_f < (Time.now - timeout.to_i.minutes).to_f
11
+ Sidekiq::Nag::Notifier.new.nag_about_queue(queue_name, timeout)
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ class NaggableQueue
18
+ def initialize(connection, queue_name)
19
+ @conn = connection
20
+ @queue = queue_name
21
+ end
22
+
23
+ def exists?
24
+ conn.exists("queue:#{queue}")
25
+ end
26
+
27
+ def oldest_job_timestamp
28
+ oldest_job['enqueued_at']
29
+ end
30
+
31
+ def oldest_job_has_timestamp?
32
+ oldest_job.has_key? 'enqueued_at'
33
+ end
34
+
35
+ def oldest_job
36
+ @oldest_job ||= JSON.parse(conn.lindex("queue:#{queue}", conn.llen("queue:#{queue}") - 1))
37
+ end
38
+
39
+ private
40
+ attr_reader :conn, :queue
41
+ end
42
+ end
@@ -0,0 +1,17 @@
1
+ class Sidekiq::Nag::Notifier
2
+ def initialize
3
+ campfire = Tinder::Campfire.new(config.subdomain, :token => config.token)
4
+ @room = campfire.find_room_by_name(config.room)
5
+ end
6
+
7
+ def nag_about_queue(queue, timeout)
8
+ room.speak(":no_good: excuse me, the '#{queue}' queue has been chilling for at least #{timeout} minutes...")
9
+ end
10
+
11
+ private
12
+ attr_reader :room
13
+
14
+ def config
15
+ @config ||= Sidekiq::Nag::Config.new
16
+ end
17
+ end
@@ -0,0 +1,21 @@
1
+ class Sidekiq::Nag::Railtie < Rails::Railtie
2
+ require 'sidekiq-nag/middleware/timestamper'
3
+
4
+ initializer :after do
5
+ Sidekiq.configure_server do |config|
6
+ config.server_middleware do |chain|
7
+ chain.add Sidekiq::Nag::Middleware::Timestamper
8
+ end
9
+ end
10
+
11
+ Sidekiq.configure_client do |config|
12
+ config.client_middleware do |chain|
13
+ chain.add Sidekiq::Nag::Middleware::Timestamper
14
+ end
15
+ end
16
+ end
17
+
18
+ rake_tasks do
19
+ load "tasks/nag.rake"
20
+ end
21
+ end
@@ -0,0 +1,5 @@
1
+ module Sidekiq
2
+ module Nag
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
@@ -0,0 +1,9 @@
1
+ module Sidekiq
2
+ module Nag
3
+ require "sidekiq-nag/version"
4
+ require "sidekiq-nag/config"
5
+ require "sidekiq-nag/notifier"
6
+ require "sidekiq-nag/nagger"
7
+ require "sidekiq-nag/railtie" if defined?(Rails)
8
+ end
9
+ end
@@ -0,0 +1,6 @@
1
+ namespace :'sidekiq-nag' do
2
+ desc "Nags Sidekiq and lets you know when things aren't moving as fast you'd like"
3
+ task :nag => :environment do
4
+ Sidekiq::Nag::Nagger.new.nag
5
+ end
6
+ end
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'sidekiq-nag/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "sidekiq-nag"
8
+ gem.version = Sidekiq::Nag::VERSION
9
+ gem.authors = ["Gary Greyling"]
10
+ gem.email = ["greyling.gary@gmail.com"]
11
+ gem.description = %q{A Sidekiq extension that will notify you of queues that take too long to process}
12
+ gem.summary = %q{Campfire notification of stationary Sidekiq queues}
13
+ gem.homepage = ""
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_dependency('rails')
21
+ gem.add_dependency('whenever')
22
+
23
+ gem.add_development_dependency('rspec')
24
+ end
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sidekiq-nag
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.1
6
+ platform: ruby
7
+ authors:
8
+ - Gary Greyling
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-02-12 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ version_requirements: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ none: false
21
+ name: rails
22
+ type: :runtime
23
+ prerelease: false
24
+ requirement: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ! '>='
27
+ - !ruby/object:Gem::Version
28
+ version: '0'
29
+ none: false
30
+ - !ruby/object:Gem::Dependency
31
+ version_requirements: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ! '>='
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ none: false
37
+ name: whenever
38
+ type: :runtime
39
+ prerelease: false
40
+ requirement: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ none: false
46
+ - !ruby/object:Gem::Dependency
47
+ version_requirements: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ! '>='
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ none: false
53
+ name: rspec
54
+ type: :development
55
+ prerelease: false
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ! '>='
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ none: false
62
+ description: A Sidekiq extension that will notify you of queues that take too long
63
+ to process
64
+ email:
65
+ - greyling.gary@gmail.com
66
+ executables: []
67
+ extensions: []
68
+ extra_rdoc_files: []
69
+ files:
70
+ - .gitignore
71
+ - Gemfile
72
+ - LICENSE.txt
73
+ - README.md
74
+ - Rakefile
75
+ - lib/sidekiq-nag.rb
76
+ - lib/sidekiq-nag/config.rb
77
+ - lib/sidekiq-nag/middleware/timestamper.rb
78
+ - lib/sidekiq-nag/nagger.rb
79
+ - lib/sidekiq-nag/notifier.rb
80
+ - lib/sidekiq-nag/railtie.rb
81
+ - lib/sidekiq-nag/version.rb
82
+ - lib/tasks/nag.rake
83
+ - sidekiq-nag.gemspec
84
+ homepage: ''
85
+ licenses: []
86
+ post_install_message:
87
+ rdoc_options: []
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ! '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ none: false
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ! '>='
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ none: false
102
+ requirements: []
103
+ rubyforge_project:
104
+ rubygems_version: 1.8.23
105
+ signing_key:
106
+ specification_version: 3
107
+ summary: Campfire notification of stationary Sidekiq queues
108
+ test_files: []