sidekiq-web_custom 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +109 -0
  3. data/.gitignore +18 -0
  4. data/.rspec +3 -0
  5. data/CHANGELOG.md +5 -0
  6. data/CODE_OF_CONDUCT.md +84 -0
  7. data/Dockerfile +18 -0
  8. data/Gemfile +14 -0
  9. data/Gemfile.lock +182 -0
  10. data/LICENSE.txt +21 -0
  11. data/Makefile +40 -0
  12. data/README.md +92 -0
  13. data/Rakefile +8 -0
  14. data/bin/all_workers +69 -0
  15. data/bin/bundle +114 -0
  16. data/bin/publish +40 -0
  17. data/bin/publish_git +38 -0
  18. data/bin/publish_ruby_gems +22 -0
  19. data/bin/rails +18 -0
  20. data/bin/sidekiq +29 -0
  21. data/bin/sidekiqmon +29 -0
  22. data/docker-compose.yml +43 -0
  23. data/dummy_rails/.rspec +4 -0
  24. data/dummy_rails/app/assets/config/manifest.js +0 -0
  25. data/dummy_rails/app/controllers/application_controller.rb +2 -0
  26. data/dummy_rails/app/helpers/application_helper.rb +2 -0
  27. data/dummy_rails/app/views/layouts/application.html.erb +15 -0
  28. data/dummy_rails/app/views/layouts/mailer.html.erb +13 -0
  29. data/dummy_rails/app/workers/exclude_hard_worker.rb +15 -0
  30. data/dummy_rails/app/workers/exclude_lazy_worker.rb +11 -0
  31. data/dummy_rails/app/workers/exclude_random_raise_worker.rb +11 -0
  32. data/dummy_rails/app/workers/hard_worker.rb +15 -0
  33. data/dummy_rails/app/workers/lazy_worker.rb +10 -0
  34. data/dummy_rails/app/workers/random_raise_worker.rb +12 -0
  35. data/dummy_rails/app/workers/taco_worker.rb +12 -0
  36. data/dummy_rails/app/workers/tostada_worker.rb +11 -0
  37. data/dummy_rails/bin/rspec +5 -0
  38. data/dummy_rails/config.ru +5 -0
  39. data/dummy_rails/config/application.rb +20 -0
  40. data/dummy_rails/config/boot.rb +5 -0
  41. data/dummy_rails/config/environment.rb +5 -0
  42. data/dummy_rails/config/environments/development.rb +52 -0
  43. data/dummy_rails/config/environments/production.rb +88 -0
  44. data/dummy_rails/config/environments/test.rb +40 -0
  45. data/dummy_rails/config/initializers/assets.rb +14 -0
  46. data/dummy_rails/config/initializers/cookies_serializer.rb +5 -0
  47. data/dummy_rails/config/initializers/filter_parameter_logging.rb +4 -0
  48. data/dummy_rails/config/initializers/sidekiq-web_custom.rb +3 -0
  49. data/dummy_rails/config/initializers/wrap_parameters.rb +14 -0
  50. data/dummy_rails/config/locales/en.yml +33 -0
  51. data/dummy_rails/config/puma.rb +37 -0
  52. data/dummy_rails/config/routes.rb +5 -0
  53. data/dummy_rails/config/secrets.yml +5 -0
  54. data/dummy_rails/config/spring.rb +5 -0
  55. data/dummy_rails/config/storage.yml +34 -0
  56. data/dummy_rails/package.json +5 -0
  57. data/dummy_rails/spec/spec_helper.rb +50 -0
  58. data/lib/load_random_workers.rb +25 -0
  59. data/lib/sidekiq/views/actions/queues/delete.erb +12 -0
  60. data/lib/sidekiq/views/actions/queues/drain_queue.erb +4 -0
  61. data/lib/sidekiq/views/actions/queues/pause.erb +13 -0
  62. data/lib/sidekiq/views/actions/retries/delete.erb +5 -0
  63. data/lib/sidekiq/views/actions/retries/execute.erb +7 -0
  64. data/lib/sidekiq/views/actions/scheduled/delete.erb +5 -0
  65. data/lib/sidekiq/views/actions/scheduled/execute.erb +7 -0
  66. data/lib/sidekiq/views/queues.erb +64 -0
  67. data/lib/sidekiq/views/retries.erb +123 -0
  68. data/lib/sidekiq/views/scheduled.erb +97 -0
  69. data/lib/sidekiq/web_custom.rb +95 -0
  70. data/lib/sidekiq/web_custom/configuration.rb +112 -0
  71. data/lib/sidekiq/web_custom/job.rb +11 -0
  72. data/lib/sidekiq/web_custom/processor.rb +82 -0
  73. data/lib/sidekiq/web_custom/queue.rb +12 -0
  74. data/lib/sidekiq/web_custom/timeout.rb +64 -0
  75. data/lib/sidekiq/web_custom/version.rb +14 -0
  76. data/lib/sidekiq/web_custom/web_action.rb +38 -0
  77. data/lib/sidekiq/web_custom/web_app.rb +46 -0
  78. data/sidekiq-web_custom.gemspec +37 -0
  79. metadata +151 -0
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2021 Matt Taylor
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/Makefile ADDED
@@ -0,0 +1,40 @@
1
+ .PHONY: bash build bundle rspec
2
+
3
+ APP_NAME?=app
4
+ SIDEKIQ_NAME?=sidekiq
5
+
6
+ build: #: Build the containers that we'll need
7
+ docker-compose build --pull
8
+
9
+ bash: #: Get a bash prompt on the core container
10
+ docker-compose run --rm -e RAILS_ENV=development $(APP_NAME) bash
11
+
12
+ bash_test: #: Get a test bash prompt on the core container
13
+ docker-compose run --rm -e RAILS_ENV=test $(APP_NAME) bash
14
+
15
+ s develop server start: clear_pid kill_sidekiq #: Start the web app server and restart the sidekiq session
16
+ docker-compose -f docker-compose.yml run --rm --service-ports $(APP_NAME)
17
+
18
+ c: #: Get a bash prompt on the core container
19
+ docker-compose run --rm -e RAILS_ENV=development $(APP_NAME) bin/rails c
20
+
21
+ clear_pid: #: clear pid in the event of a crash
22
+ rm -f dummy_rails/tmp/pids/server.pid
23
+
24
+ kill_sidekiq:
25
+ docker-compose stop $(SIDEKIQ_NAME)
26
+
27
+ sidekiq: kill_sidekiq # start a detached version of sidekiq
28
+ docker-compose -f docker-compose.yml run -d --rm $(SIDEKIQ_NAME)
29
+
30
+ down: #: Bring down the service -- Destroys everything in redis and all containers
31
+ docker-compose down
32
+
33
+ clean: #: Clean up stopped/exited containers
34
+ docker-compose rm -f
35
+
36
+ add_jobs: #: Randomly add jobs to every queue defined in dummy app
37
+ docker-compose run --rm $(APP_NAME) bin/rails runner 'lib/load_random_workers.rb'
38
+
39
+ bundle: #: install gems for Dummy App with
40
+ docker-compose run --rm $(APP_NAME) bundle install
data/README.md ADDED
@@ -0,0 +1,92 @@
1
+ # Sidekiq::WebCustom
2
+
3
+ Sidekiq::WebCustom adds additional flexibility to your Sidekiq UI.
4
+ - What happens if you do not have a Sidekiq Server?
5
+ - What happens if your Sidekiq Server does not bind to a queue that is ever growing?
6
+
7
+ This Custom add on to the Sidekiq Web framework allows you to continue to drain your queue's even when Sidekiq is not bound to them
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ Working on Adding a gem source. For now directly pull it from git
14
+ ```ruby
15
+ gem 'sidekiq-web_custom', source: 'https://github.com/matt-taylor/sidekiq-web_custom'
16
+ ```
17
+
18
+ And then execute:
19
+
20
+ $ bundle install
21
+
22
+ Or install it yourself as:
23
+
24
+ $ gem install sidekiq-web_custom
25
+
26
+ ## Usage
27
+
28
+ ### Configuration
29
+ #### Initializer
30
+ Add an intilizer file to boot SidekiqUI with the expected plugins `config/initializers/sidekiq-web_custom.rb`. When not providing a block, this will use the default configuration values.
31
+ ```ruby
32
+ # config/initializers/sidekiq-web_custom.rb
33
+
34
+ require 'sidekiq/web_custom'
35
+ Sidekiq::WebCustom.configure
36
+ ```
37
+
38
+ #### Options
39
+ ```ruby
40
+ require 'sidekiq/web_custom'
41
+ Sidekiq::WebCustom.configure do |config|
42
+ # Max number to attempt to drain from a queue at a time
43
+ # Warning: A high number or long runnnig job will potentially block the process for longer
44
+ config.drain_rate = 10 # default is 10 seconds
45
+
46
+ # Max time to allow for execution of draining
47
+ # If time exceeds this number, the process will violently quit.
48
+ # Set warning time wisely
49
+ config.max_execution_time = 6 # default is 6 second
50
+
51
+ # Max time before we attempt to send warning to halt execution.
52
+ # This will prevent the process from trying to attempt work on another job
53
+ # If a long running job is occuring, this will not stop the job. It will meet a violent end
54
+ config.warn_execution_time = 5 # default is 5 second
55
+
56
+
57
+ # To redefine a local erb like queues, retries, dead, add a new erb like this
58
+ params = { queues: "#{absolute_path}/queues.erb" }
59
+ config.merge(base: :local_erbs, params: params)
60
+
61
+ # To add additional actions to a specific local_erb
62
+ # Note Actions that are not attached to an ERB will raise an error
63
+ params = {
64
+ schedule_later: "#{absolute_path}/schedule_later.erb" ,
65
+ delete: "#{absolute_path}/delete.erb" ,
66
+ }
67
+ config.merge(base: :local_erbs, params: params, action_type: :queues)
68
+ end
69
+ ```
70
+
71
+ ## Development
72
+
73
+ After checking out the repo, run `make build && make bundle` to install dependencies. Then, you can bash into a docker container by using `make bash`.
74
+
75
+ Similarly, a local dummy app is included with the gem. This allows running `make s` to load a local version of the gem in a isolated ENV.
76
+
77
+ Please note that changes to the code will require a restart of the server.
78
+ Consult the [Makefile](https://github.com/matt-taylor/sidekiq-web_custom/blob/main/Makefile) for additional commands.
79
+
80
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
81
+
82
+ ## Contributing
83
+
84
+ Bug reports and pull requests are welcome on GitHub at https://github.com/matt-taylor/sidekiq-web_custom. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/matt-taylor/sidekiq-web_custom/blob/main/CODE_OF_CONDUCT.md).
85
+
86
+ ## License
87
+
88
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
89
+
90
+ ## Code of Conduct
91
+
92
+ Everyone interacting in the Sidekiq::Web::Custom project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/matt-taylor/sidekiq-web_custom/blob/main/CODE_OF_CONDUCT.md).
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
data/bin/all_workers ADDED
@@ -0,0 +1,69 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails gems
3
+ # installed from the root of your application.
4
+
5
+ APP_PATH = File.expand_path('../dummy_rails', __dir__)
6
+ ENV['BUNDLE_GEMFILE'] = File.expand_path('../Gemfile', __dir__)
7
+
8
+
9
+ if File.exist?(ENV['BUNDLE_GEMFILE'])
10
+ require 'bundler/setup'
11
+ else
12
+ raise ArgumentError, "ENV['BUNDLE_GEMFILE'] not found at [#{ENV['BUNDLE_GEMFILE']}]"
13
+ end
14
+
15
+ require 'sidekiq'
16
+ require 'sidekiq/cli'
17
+
18
+ def assign_configs!
19
+ worker_files = Dir["#{APP_PATH}/app/workers/**/*_worker.rb"]
20
+ bind_queues = worker_files.map { |path| File.basename(path, '.rb') }
21
+ Sidekiq.configure_server do |config|
22
+ options = {
23
+ require: APP_PATH,
24
+ environment: ENV['RAILS_ENV'] || 'development',
25
+ queues: bind_queues.select { |c| !c.include?('exclude') },
26
+ strict: false,
27
+ concurrency: 10,
28
+ }
29
+ config.options = config.options.merge(options)
30
+ end
31
+ end
32
+
33
+ def integrate_with_systemd
34
+ return unless ENV["NOTIFY_SOCKET"]
35
+
36
+ Sidekiq.configure_server do |config|
37
+ Sidekiq.logger.info "Enabling systemd notification integration"
38
+ require "sidekiq/sd_notify"
39
+ config.on(:startup) do
40
+ Sidekiq::SdNotify.ready
41
+ end
42
+ config.on(:shutdown) do
43
+ Sidekiq::SdNotify.stopping
44
+ end
45
+ Sidekiq.start_watchdog if Sidekiq::SdNotify.watchdog?
46
+ end
47
+ end
48
+
49
+ begin
50
+ cli = Sidekiq::CLI.instance
51
+ assign_configs!
52
+ cli.parse
53
+ assign_configs!
54
+
55
+ integrate_with_systemd
56
+
57
+ cli.run
58
+ rescue => e
59
+ raise e if $DEBUG
60
+ if Sidekiq.error_handlers.length == 0
61
+ STDERR.puts e.message
62
+ STDERR.puts e.backtrace.join("\n")
63
+ else
64
+ cli.handle_exception e
65
+ end
66
+
67
+ exit 1
68
+ end
69
+
data/bin/bundle ADDED
@@ -0,0 +1,114 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'bundle' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "rubygems"
12
+
13
+ m = Module.new do
14
+ module_function
15
+
16
+ def invoked_as_script?
17
+ File.expand_path($0) == File.expand_path(__FILE__)
18
+ end
19
+
20
+ def env_var_version
21
+ ENV["BUNDLER_VERSION"]
22
+ end
23
+
24
+ def cli_arg_version
25
+ return unless invoked_as_script? # don't want to hijack other binstubs
26
+ return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update`
27
+ bundler_version = nil
28
+ update_index = nil
29
+ ARGV.each_with_index do |a, i|
30
+ if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN
31
+ bundler_version = a
32
+ end
33
+ next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/
34
+ bundler_version = $1
35
+ update_index = i
36
+ end
37
+ bundler_version
38
+ end
39
+
40
+ def gemfile
41
+ gemfile = ENV["BUNDLE_GEMFILE"]
42
+ return gemfile if gemfile && !gemfile.empty?
43
+
44
+ File.expand_path("../../Gemfile", __FILE__)
45
+ end
46
+
47
+ def lockfile
48
+ lockfile =
49
+ case File.basename(gemfile)
50
+ when "gems.rb" then gemfile.sub(/\.rb$/, gemfile)
51
+ else "#{gemfile}.lock"
52
+ end
53
+ File.expand_path(lockfile)
54
+ end
55
+
56
+ def lockfile_version
57
+ return unless File.file?(lockfile)
58
+ lockfile_contents = File.read(lockfile)
59
+ return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/
60
+ Regexp.last_match(1)
61
+ end
62
+
63
+ def bundler_version
64
+ @bundler_version ||=
65
+ env_var_version || cli_arg_version ||
66
+ lockfile_version
67
+ end
68
+
69
+ def bundler_requirement
70
+ return "#{Gem::Requirement.default}.a" unless bundler_version
71
+
72
+ bundler_gem_version = Gem::Version.new(bundler_version)
73
+
74
+ requirement = bundler_gem_version.approximate_recommendation
75
+
76
+ return requirement unless Gem::Version.new(Gem::VERSION) < Gem::Version.new("2.7.0")
77
+
78
+ requirement += ".a" if bundler_gem_version.prerelease?
79
+
80
+ requirement
81
+ end
82
+
83
+ def load_bundler!
84
+ ENV["BUNDLE_GEMFILE"] ||= gemfile
85
+
86
+ activate_bundler
87
+ end
88
+
89
+ def activate_bundler
90
+ gem_error = activation_error_handling do
91
+ gem "bundler", bundler_requirement
92
+ end
93
+ return if gem_error.nil?
94
+ require_error = activation_error_handling do
95
+ require "bundler/version"
96
+ end
97
+ return if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION))
98
+ warn "Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`"
99
+ exit 42
100
+ end
101
+
102
+ def activation_error_handling
103
+ yield
104
+ nil
105
+ rescue StandardError, LoadError => e
106
+ e
107
+ end
108
+ end
109
+
110
+ m.load_bundler!
111
+
112
+ if m.invoked_as_script?
113
+ load Gem.bin_path("bundler", "bundle")
114
+ end
data/bin/publish ADDED
@@ -0,0 +1,40 @@
1
+ #!/bin/bash -e
2
+
3
+ if [ -z "$GEMFURY_TOKEN" ]; then
4
+ echo 'Environment variable GEMFURY_TOKEN is not present'
5
+ exit 1
6
+ fi
7
+
8
+
9
+ VERSION=$(bin/rails runner 'Sidekiq::WebCustom.get_version')
10
+ PACKAGE=sidekiq-web_custom-${VERSION}.gem
11
+
12
+ if [ $(git tag -l "$VERSION") ]; then
13
+ echo "Pre existing version $VERSION, not tagging."
14
+ echo "Pre existing version $VERSION, not pushing to gemfury."
15
+ exit 0
16
+ fi
17
+
18
+ # Build and publish to Gemfury
19
+ gem build sidekiq-web_custom.gemspec
20
+ FILE=$(pwd)/${PACKAGE}
21
+ echo "Finished building $FILE"
22
+
23
+ # push to gemfury
24
+ curl --fail -F package=@${FILE} https://${GEMFURY_TOKEN}@push.fury.io/${GEMFURY_USER}/
25
+ echo "Finished Pushing to Gemfury"
26
+
27
+ # create tag in repo
28
+ git tag -a $VERSION -m "$VERSION"
29
+ git push https://${GITHUB_TOKEN}@github.com/${GITHUB_USER}/sidekiq-web_custom.git $VERSION
30
+ echo "Finished Tagging to git"
31
+
32
+
33
+ # send artifacts to git
34
+ SHA=$(git rev-parse HEAD)
35
+ ./$GHRLOCATION -soft -t ${GITHUB_TOKEN} -u ${GITHUB_USER} -r sidekiq-web_custom -c ${SHA} ${VERSION} *.gem
36
+
37
+ echo "Finished Pushing artificat to Git"
38
+
39
+ # start fresh
40
+ rm sidekiq-web_custom.gemspec
data/bin/publish_git ADDED
@@ -0,0 +1,38 @@
1
+ #!/bin/bash -e
2
+
3
+ GEM_NAME="sidekiq-web_custom"
4
+ if [ -z "$GITHUB_TOKEN" ]; then
5
+ echo 'Environment variable GITHUB_TOKEN is not present'
6
+ exit 1
7
+ fi
8
+
9
+ if [ -z "$GITHUB_USER" ]; then
10
+ echo 'Environment variable GITHUB_USER is not present'
11
+ exit 1
12
+ fi
13
+
14
+
15
+ VERSION=$(bin/rails runner 'Sidekiq::WebCustom.get_version')
16
+ PACKAGE=${GEM_NAME}-${VERSION}.gem
17
+
18
+ if [ $(git tag -l "$VERSION") ]; then
19
+ echo "Pre existing version $VERSION, not tagging."
20
+ exit 0
21
+ fi
22
+
23
+ gem build ${GEM_NAME}.gemspec
24
+ FILE=$(pwd)/${PACKAGE}
25
+ echo "Finished building $FILE"
26
+
27
+ # create tag in repo
28
+ git tag -a $VERSION -m "$VERSION"
29
+ git push https://${GITHUB_TOKEN}@github.com/${GITHUB_USER}/${GEM_NAME}.git $VERSION
30
+ echo "Finished Tagging to git"
31
+
32
+
33
+ # send artifacts to git
34
+ SHA=$(git rev-parse HEAD)
35
+ ./$GHRLOCATION -soft -t ${GITHUB_TOKEN} -u ${GITHUB_USER} -r timeoutable -c ${SHA} ${VERSION} *.gem
36
+ echo "Finished Pushing artificat to Git"
37
+
38
+ rm $
@@ -0,0 +1,22 @@
1
+ #!/bin/bash -e
2
+
3
+ BASE="sidekiq-web_custom"
4
+ if [ -z "$GEM_HOST_API_KEY" ]; then
5
+ echo 'Environment variable GEM_HOST_API_KEY is not present'
6
+ exit 1
7
+ fi
8
+
9
+ VERSION=$(bin/rails runner 'Sidekiq::WebCustom.get_version')
10
+ PACKAGE=${BASE}-${VERSION}.gem
11
+
12
+ # Build Gem
13
+ gem build ${BASE}.gemspec
14
+ FILE=$(pwd)/${PACKAGE}
15
+ echo "Finished building $FILE"
16
+
17
+ # push to Ruby Gems
18
+ gem push ${FILE}
19
+
20
+ echo "Finished pushing to Gemfury"
21
+
22
+ rm ${FILE}