blue_green_workers 0.1.0

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: 763c209e7bb28f7c8e3753cc57d4f3e9d0b1c021
4
+ data.tar.gz: 1afcd620a1b05e054f56300f0dbdecd0d7509c50
5
+ SHA512:
6
+ metadata.gz: fc6b12114e9d32012f262e85fc34f87bb073edfad3ac36d7c846348b7c483db0a22300bdfc407b64c88a3ae74293caf106cac54860605f9800be86bb201cf620
7
+ data.tar.gz: fd9be9b4151d112db6af2eaffb8d4cacf25e1382f86c8c205dc77f0f2c7a1d77639a10ecca8762db659720ea6f72d80198e49b24c3fdfbad04d4ec622747765f
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ spec/examples.txt
10
+
11
+ Gemfile.lock
12
+
13
+ # rspec failure tracking
14
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,11 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.4
3
+
4
+ Metrics/BlockLength:
5
+ Exclude:
6
+ - 'spec/**/*.rb'
7
+ - '*.gemspec'
8
+
9
+ Metrics/ModuleLength:
10
+ Exclude:
11
+ - 'spec/**/*.rb'
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.4.2
5
+ before_install: gem install bundler -v 1.16.0
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
6
+
7
+ # Specify your gem's dependencies in blue_green_workers.gemspec
8
+ gemspec
data/README.md ADDED
@@ -0,0 +1,62 @@
1
+ # BlueGreenWorkers
2
+
3
+ This gem provides helpers to coordiante workers across multiple clusters that for which only one cluster should be active at a time. Think [blue green deployments](https://martinfowler.com/bliki/BlueGreenDeployment.html)
4
+
5
+ ## Installation
6
+
7
+ ```ruby
8
+ gem 'blue_green_workers'
9
+ ```
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install blue_green_workers
18
+
19
+ ## Usage
20
+
21
+ This gem doesn't attempt to provide an interface through which you specify which cluster is currently active, that's left as an exercise to the reader. One could very easily use ActiveRecord and a simple RESTFul interface to set the current active cluster.
22
+
23
+ ### Config
24
+ ```ruby
25
+ BlueGreenWorkers.configure do |config|
26
+ config.cluster_name = 'blue'
27
+ config.determine_active_cluster { ActiveCluster.first.value }
28
+ config.activate { QueueClient.listen! }
29
+ config.deactivate { QueueClient.shutdown! }
30
+ config.logger = Logger.new STDOUT
31
+ end
32
+ ```
33
+
34
+ * `cluster_name` - Defines the name for this cluster. Something like `ENV['CLUSTER_NAME']` probably makes sense
35
+ * `determine_active_cluster` - Takes a block that returns the name of the current active cluster
36
+ * `refresh_interval` (optional) - How often to cache the active cluster, `0` (the default) will call the block passed to `determine_active_cluster` every time a worker is executed.
37
+ * `activate` (optiona) - Block to call when this cluster goes active. Will be called during initialization. `refresh_interval` must be specified.
38
+ * `deactivate` (optiona) - Block to call when this cluster goes passive. This block will not be called if the cluster is started in passive mode. `refresh_interval` must be specified.
39
+ * `logger` (optiona) - Logger to use
40
+
41
+ ### Executing jobs
42
+
43
+ In addition to attaching event handles to `activate` and `deactivate` you can also do this:
44
+
45
+ ```ruby
46
+ loop do
47
+ BlueGreenWorkers.execute do
48
+ # Do some work, poll for stuff, etc
49
+ end
50
+ sleep 60
51
+ end
52
+ ```
53
+
54
+ ## Development
55
+
56
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
57
+
58
+ 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 tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
59
+
60
+ ## Contributing
61
+
62
+ Bug reports and pull requests are welcome on GitHub at https://github.com/hawknewton/blue_green_workers.
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+ require 'rubocop/rake_task'
6
+
7
+ RuboCop::RakeTask.new
8
+ RSpec::Core::RakeTask.new(:spec)
9
+ task default: %i[spec rubocop]
data/bin/console ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'blue_green_workers'
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ require 'pry'
12
+ Pry.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,37 @@
1
+
2
+ # frozen_string_literal: true
3
+
4
+ lib = File.expand_path('../lib', __FILE__)
5
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
6
+ require 'blue_green_workers/version'
7
+
8
+ Gem::Specification.new do |spec|
9
+ spec.name = 'blue_green_workers'
10
+ spec.version = BlueGreenWorkers::VERSION
11
+ spec.authors = ['hawknewton']
12
+ spec.email = ['hawk.newton@gmail.com']
13
+
14
+ spec.summary = "Deactivate background workers when we're the standby" \
15
+ 'cluster'
16
+ spec.description = '
17
+ Deactive any type of background worker when the cluster is standby. This is
18
+ useful when deploying apps that utilize timers or queues with a blue/green
19
+ deploy strategy.
20
+ '.strip
21
+ spec.homepage = 'https://github.com/hawknewton/blue_green_workers'
22
+
23
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
24
+ f.match(%r{^(test|spec|features)/})
25
+ end
26
+ spec.bindir = 'exe'
27
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
+ spec.require_paths = ['lib']
29
+
30
+ spec.add_development_dependency 'bundler', '~> 1.16'
31
+ spec.add_development_dependency 'null-logger', '~> 0.1'
32
+ spec.add_development_dependency 'pry', '~> 0.11'
33
+ spec.add_development_dependency 'rake', '~> 10.0'
34
+ spec.add_development_dependency 'rspec', '~> 3.0'
35
+ spec.add_development_dependency 'rspec-eventually', '~> 0.2'
36
+ spec.add_development_dependency 'rubocop', '~> 0.52'
37
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pry'
4
+
5
+ module BlueGreenWorkers
6
+ # Config for BlueGreenWorkers
7
+ class Config
8
+ attr_reader :active_cluster_block
9
+ attr_accessor :cluster_name, :refresh_interval, :activate_block,
10
+ :deactivate_block
11
+ attr_writer :logger
12
+
13
+ def activate(&block)
14
+ @activate_block = block
15
+ end
16
+
17
+ def deactivate(&block)
18
+ @deactivate_block = block
19
+ end
20
+
21
+ def determine_active_cluster(&block)
22
+ @active_cluster_block = block
23
+ end
24
+
25
+ def logger
26
+ @logger ||= Logger.new STDOUT
27
+ end
28
+
29
+ def validate
30
+ cluster_name || raise('No cluster_name defined')
31
+ active_cluster_block || raise('No determine_active_cluster block defined')
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BlueGreenWorkers
4
+ VERSION = '0.1.0'
5
+ end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'blue_green_workers/version'
4
+ require 'blue_green_workers/config'
5
+ require 'logger'
6
+
7
+ # Main module for blue_green_workers
8
+ module BlueGreenWorkers
9
+ def self.active_cluster
10
+ if config.refresh_interval.positive?
11
+ @active_cluster
12
+ else
13
+ determine_active_cluster
14
+ end
15
+ end
16
+
17
+ def self.configure
18
+ yield config
19
+ determine_active_cluster
20
+ (config.refresh_interval || 0).positive? && start_refresh_thread
21
+ config.validate
22
+ end
23
+
24
+ def self.execute
25
+ if config.active_cluster_block.call == config.cluster_name
26
+ yield
27
+ else
28
+ logger.debug 'Workers not active, skipping BlueGreenWorkers#execute'
29
+ end
30
+ end
31
+
32
+ def self.shutdown
33
+ logger.warn 'Shutting down BlueGreenWotkers!'
34
+ @refresh_thread&.kill
35
+ @active_cluster = nil
36
+ @refresh_thread = nil
37
+ @config = nil
38
+ end
39
+
40
+ # private
41
+ def self.activate
42
+ logger.info 'BlueGreenWorkers cluster activating!'
43
+ config.activate_block&.call
44
+ end
45
+
46
+ def self.deactivate
47
+ logger.info 'BlueGreenWorkers cluster deactivating!'
48
+ config.deactivate_block&.call
49
+ end
50
+
51
+ def self.active_cluster=(cluster)
52
+ if cluster != @active_cluster
53
+ if cluster == config.cluster_name
54
+ activate
55
+ elsif @active_cluster == config.cluster_name
56
+ deactivate
57
+ end
58
+ end
59
+ @active_cluster = cluster
60
+ end
61
+
62
+ def self.config
63
+ @config ||= Config.new
64
+ end
65
+
66
+ def self.determine_active_cluster
67
+ self.active_cluster = config.active_cluster_block.call
68
+ end
69
+
70
+ def self.logger
71
+ config.logger
72
+ end
73
+
74
+ def self.refresh_thread
75
+ logger.info "BlueGreenWorkers refreshing every #{config.refresh_interval}s"
76
+ @refresh_thread ||= Thread.new { refresh_loop }
77
+ end
78
+
79
+ def self.refresh_loop
80
+ loop do
81
+ begin
82
+ determine_active_cluster
83
+ sleep config.refresh_interval
84
+ rescue StandardError => err
85
+ Logger.error "Error during refresh: #{err} #{err.backtrace.join "\n"}"
86
+ end
87
+ end
88
+ end
89
+
90
+ def self.start_refresh_thread
91
+ refresh_thread
92
+ end
93
+
94
+ private_class_method :active_cluster=, :config, :determine_active_cluster,
95
+ :logger, :refresh_thread, :start_refresh_thread,
96
+ :refresh_loop
97
+ end
metadata ADDED
@@ -0,0 +1,157 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: blue_green_workers
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - hawknewton
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-12-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.16'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.16'
27
+ - !ruby/object:Gem::Dependency
28
+ name: null-logger
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.1'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.11'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.11'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec-eventually
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '0.2'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '0.2'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '0.52'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '0.52'
111
+ description: |-
112
+ Deactive any type of background worker when the cluster is standby. This is
113
+ useful when deploying apps that utilize timers or queues with a blue/green
114
+ deploy strategy.
115
+ email:
116
+ - hawk.newton@gmail.com
117
+ executables: []
118
+ extensions: []
119
+ extra_rdoc_files: []
120
+ files:
121
+ - ".gitignore"
122
+ - ".rspec"
123
+ - ".rubocop.yml"
124
+ - ".travis.yml"
125
+ - Gemfile
126
+ - README.md
127
+ - Rakefile
128
+ - bin/console
129
+ - bin/setup
130
+ - blue_green_workers.gemspec
131
+ - lib/blue_green_workers.rb
132
+ - lib/blue_green_workers/config.rb
133
+ - lib/blue_green_workers/version.rb
134
+ homepage: https://github.com/hawknewton/blue_green_workers
135
+ licenses: []
136
+ metadata: {}
137
+ post_install_message:
138
+ rdoc_options: []
139
+ require_paths:
140
+ - lib
141
+ required_ruby_version: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ required_rubygems_version: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - ">="
149
+ - !ruby/object:Gem::Version
150
+ version: '0'
151
+ requirements: []
152
+ rubyforge_project:
153
+ rubygems_version: 2.6.13
154
+ signing_key:
155
+ specification_version: 4
156
+ summary: Deactivate background workers when we're the standbycluster
157
+ test_files: []