hirefire-resource 0.7.0 → 0.7.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e583f65c0c003cc4543482e3730952319ddc0069d97332f4f40b85701f61eebd
4
- data.tar.gz: efdc10ea1bf9f75333e4605a4ffbc7dd63e40d3e198a552badfb1a79bad21697
3
+ metadata.gz: 2c7c314af60ca51b3e19880d4f676a5e07ecb5625d8078b7200827a9b2c9338b
4
+ data.tar.gz: 486392f48c5986bdf100c03a2047496a840c788ffc2af2e27712d41ce6c6cc0b
5
5
  SHA512:
6
- metadata.gz: 03fe9362bc04329ad02fccb8cc2836176bfbd1d06cef683a24dffa12f399386b592efcc1e8271b854c766a3c495a7d9abeda9e0736d59c86cda38723379c5690
7
- data.tar.gz: b80ca0e325253750e54771f9dcf03e60e88c99b999b2dff0f7b596186c23356095dad90fd5ddc0bde1c2ec57fd6cf2475f3d8452c260467f9ef9f7730aaffeef
6
+ metadata.gz: c10d31c05160fcd258c804e9e7e1ca9d4e608d71ef0a579255f03cac37c2f50b5a81e4c8ea9c24abf57179c3e0e86c5616a0855cee52561eb793d2957608edd2
7
+ data.tar.gz: b44fd34a1ec5395d2734745e1f72b6a189f37aa285d67177e19764619de1c4770d6a6f40d133cc02e6e3285cc781761df03b9cfb63916974731d2de02325d023
@@ -0,0 +1,28 @@
1
+ ## v0.7.5/Master
2
+
3
+ * Fix compatibility issue with Que 1.x (backwards-compatible with Que 0.x).
4
+
5
+ ## v0.7.4
6
+
7
+ * Attempt to fix an issue where the STDOUT IO Stream has been closed for an unknown reason.
8
+ * This resulted in errors in an application with `log_queue_metrics` enabled after a random period of time.
9
+
10
+ ## v0.7.3
11
+
12
+ * Added priority queue support for bunny message count.
13
+ * Allows for passing in the `x-max-priority` option when opening up a queue to check the messages remaining.
14
+ * Usage: `HireFire::Macro::Bunny.queue(queue, amqp_url: url, "x-max-priority": 10 )`
15
+
16
+ ## v0.7.2
17
+
18
+ * Changed Que macro to query take into account scheduled jobs.
19
+
20
+ ## v0.7.1
21
+
22
+ * Made entire library threadsafe.
23
+
24
+ ## v0.7.0
25
+
26
+ * Made `HireFire::Resource.log_queue_metrics` optional. This is now disabled by default.
27
+ * Enable by setting `log_queue_metrics = true`.
28
+ * Required when using the `Manager::Web::Logplex::QueueTime` autoscaling strategy.
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |gem|
4
4
  gem.name = "hirefire-resource"
5
- gem.version = "0.7.0"
5
+ gem.version = "0.7.5"
6
6
  gem.platform = Gem::Platform::RUBY
7
7
  gem.authors = "Michael van Rooijen"
8
8
  gem.email = "michael@hirefire.io"
@@ -10,6 +10,12 @@ Gem::Specification.new do |gem|
10
10
  gem.summary = "Autoscaling for your Heroku dynos"
11
11
  gem.description = "Load- and schedule-based scaling for web- and worker dynos"
12
12
  gem.licenses = ["Apache License"]
13
+ gem.metadata = {
14
+ "homepage_uri" => "https://www.hirefire.io",
15
+ "changelog_uri" => "https://github.com/hirefire/hirefire-resource/blob/master/CHANGELOG.md",
16
+ "source_code_uri" => "https://github.com/hirefire/hirefire-resource/",
17
+ "bug_tracker_uri" => "https://github.com/hirefire/hirefire-resource/issues",
18
+ }
13
19
 
14
20
  gem.files = %x[git ls-files].split("\n")
15
21
  gem.executables = ["hirefire", "hirefireapp"]
@@ -70,11 +70,15 @@ module HireFire
70
70
 
71
71
  def count_messages(channel, queue_names, options)
72
72
  queue_names.inject(0) do |sum, queue_name|
73
- queue = channel.queue(queue_name, :durable => options[:durable])
73
+ if options.key?(:'x-max-priority')
74
+ queue = channel.queue(queue_name, :durable => options[:durable],
75
+ :arguments => {"x-max-priority" => options[:'x-max-priority']})
76
+ else
77
+ queue = channel.queue(queue_name, :durable => options[:durable])
78
+ end
74
79
  sum + queue.message_count
75
80
  end
76
81
  end
77
82
  end
78
83
  end
79
84
  end
80
-
@@ -4,14 +4,8 @@ module HireFire
4
4
  module Macro
5
5
  module Que
6
6
  QUERY = %{
7
- SELECT count(*) AS total,
8
- count(locks.job_id) AS running,
9
- coalesce(sum((error_count > 0 AND locks.job_id IS NULL)::int), 0) AS failing,
10
- coalesce(sum((error_count = 0 AND locks.job_id IS NULL)::int), 0) AS scheduled
11
- FROM que_jobs LEFT JOIN (
12
- SELECT (classid::bigint << 32) + objid::bigint AS job_id
13
- FROM pg_locks WHERE locktype = 'advisory'
14
- ) locks USING (job_id) }.freeze
7
+ SELECT count(*) AS total
8
+ FROM que_jobs WHERE run_at < now() }.freeze
15
9
 
16
10
  extend self
17
11
 
@@ -25,10 +19,17 @@ FROM que_jobs LEFT JOIN (
25
19
  # @param [String] queue the queue name to count. (default: nil # gets all queues)
26
20
  # @return [Integer] the number of jobs in the queue(s).
27
21
  #
28
- def queue(queue = nil)
29
- query = queue ? "#{QUERY} WHERE queue = '#{queue}'" : QUERY
22
+ def queue(*queues)
23
+ query = case
24
+ when queues.none? then QUERY
25
+ when queues.one? then "#{QUERY} AND queue = '#{queues.first}'"
26
+ else
27
+ queue_names = queues.map { |queue| "'#{queue}'" }.join(', ')
28
+ %Q{#{QUERY} AND queue IN (#{queue_names})}
29
+ end
30
+
30
31
  results = ::Que.execute(query).first
31
- results["total"].to_i - results["failing"].to_i
32
+ (results[:total] || results["total"]).to_i
32
33
  end
33
34
  end
34
35
  end
@@ -3,107 +3,107 @@
3
3
  module HireFire
4
4
  class Middleware
5
5
 
6
- INFO_HEADERS = {
7
- "Content-Type" => "application/json",
8
- "Cache-Control" => "must-revalidate, private, max-age=0"
9
- }
10
-
11
- TEST_HEADERS = {
12
- "Content-Type" => "text/html"
13
- }
14
-
15
- # Initialize the HireFire::Middleware and store the `app` in `@app`
16
- # and `ENV["HIREFIRE_TOKEN"]` in `@token` for convenience.
6
+ # Initializes HireFire::Middleware.
17
7
  #
18
- # @param [ActionDispatch::Routing::RouteSet] app.
8
+ # @param [Proc] app call with `env` to continue down the middleware stack.
19
9
  #
20
10
  def initialize(app)
21
- @app = app
22
- @token = ENV["HIREFIRE_TOKEN"]
23
- if defined?(Rails) && Rails.application.config.relative_url_root
24
- @path_prefix = Regexp.new("^" + Regexp.escape(Rails.application.config.relative_url_root))
25
- end
11
+ @app = app
12
+ @token = ENV["HIREFIRE_TOKEN"]
13
+ @path_prefix = get_path_prefix
26
14
  end
27
15
 
28
- # Will respond to the request here if either the `test` or the `info` url was requested.
29
- # Otherwise, fall through to the rest of the middleware below HireFire::Middleware.
16
+ # Intercepts and handles the /hirefire/test, /hirefire/development/info,
17
+ # and /hirefire/HIREFIRE_TOKEN/info paths. If none of these paths match,
18
+ # then then request will continue down the middleware stack.
19
+ #
20
+ # When HireFire::Resource.log_queue_metrics is enabled, and the HTTP_X_REQUEST_START
21
+ # header has been injected at the Heroku Router layer, queue time information will be
22
+ # logged to $stdout. This data can be used by the HireFire Logdrain with the
23
+ # Web.Logplex.QueueTime autoscaling strategy.
24
+ #
25
+ # Important: Don't set/update instance variables within this- or any underlying methods.
26
+ # Doing so may result in race conditions when using threaded application servers.
30
27
  #
31
28
  # @param [Hash] env containing request information.
32
29
  #
33
30
  def call(env)
34
- @env = env
35
-
36
31
  handle_queue(env["HTTP_X_REQUEST_START"])
37
32
 
38
- if test?
39
- [ 200, TEST_HEADERS, self ]
40
- elsif info?
41
- [ 200, INFO_HEADERS, self ]
33
+ if test_path?(env["PATH_INFO"])
34
+ build_test_response
35
+ elsif info_path?(env["PATH_INFO"])
36
+ build_info_response
42
37
  else
43
38
  @app.call(env)
44
39
  end
45
40
  end
46
41
 
47
- # Returns text/html when the `test` url is requested.
48
- # This is purely to see whether the URL works through the HireFire command-line utility.
49
- #
50
- # Returns a JSON String when the `info` url is requested.
51
- # This url will be requested every minute by HireFire in order to fetch dyno data.
42
+ private
43
+
44
+ # Determines whether or not the test path has been requested.
52
45
  #
53
- # @return [text/html, application/json] based on whether the `test` or `info` url was requested.
46
+ # @param [String] path_info the requested path.
47
+ # @return [Boolean] true if the requested path matches the test path.
54
48
  #
55
- def each(&block)
56
- if test?
57
- block.call "HireFire Middleware Found!"
58
- elsif info?
59
- block.call(dynos)
60
- end
49
+ def test_path?(path_info)
50
+ get_path(path_info) == "/hirefire/test"
61
51
  end
62
52
 
63
- private
64
-
65
- # Generates a JSON string based on the dyno data.
53
+ # Determines whether or not the info path has been requested.
66
54
  #
67
- # @return [String] in JSON format.
55
+ # @param [String] path_info the requested path.
56
+ # @return [Boolean] true if the requested path matches the info path.
68
57
  #
69
- def dynos
70
- dyno_data = HireFire::Resource.dynos.inject(String.new) do |json, dyno|
71
- json << %(,{"name":"#{dyno[:name]}","quantity":#{dyno[:quantity].call || "null"}})
72
- json
73
- end
74
-
75
- "[#{dyno_data.sub(",","")}]"
58
+ def info_path?(path_info)
59
+ get_path(path_info) == "/hirefire/#{@token || "development"}/info"
76
60
  end
77
61
 
78
- # Rack PATH_INFO with any RAILS_RELATIVE_URL_ROOT stripped off
62
+ # The provided path with @path_prefix stripped off.
79
63
  #
80
- # @return [String]
64
+ # @param [String] path_info the requested path.
65
+ # @return [String] the path without the @path_prefix.
81
66
  #
82
- def path
67
+ def get_path(path_info)
83
68
  if @path_prefix
84
- @env["PATH_INFO"].gsub(@path_prefix, "")
69
+ path_info.gsub(@path_prefix, "")
85
70
  else
86
- @env["PATH_INFO"]
71
+ path_info
87
72
  end
88
73
  end
89
74
 
90
- # Returns true if the PATH_INFO matches the test url.
75
+ # Builds the response for the test path.
91
76
  #
92
- # @return [Boolean] true if the requested url matches the test url.
77
+ # @return [String] in text/html format.
93
78
  #
94
- def test?
95
- path == "/hirefire/test"
79
+ def build_test_response
80
+ status = 200
81
+ headers = {"Content-Type" => "text/html"}
82
+ body = "HireFire Middleware Found!"
83
+
84
+ [status, headers, [body]]
96
85
  end
97
86
 
98
- # Returns true if the PATH_INFO matches the info url.
87
+ # Builds the response for the info path containing the configured
88
+ # queues and their sizes based on the HireFire::Resource configuration.
99
89
  #
100
- # @return [Boolean] true if the requested url matches the info url.
90
+ # @return [String] in application/json format.
101
91
  #
102
- def info?
103
- path == "/hirefire/#{@token || "development"}/info"
92
+ def build_info_response
93
+ entries = HireFire::Resource.dynos.map do |config|
94
+ %({"name":"#{config[:name]}","quantity":#{config[:quantity].call || "null"}})
95
+ end
96
+
97
+ status = 200
98
+ headers = Hash.new
99
+ headers["Content-Type"] = "application/json"
100
+ headers["Cache-Control"] = "must-revalidate, private, max-age=0"
101
+ body = "[" + entries.join(",") + "]"
102
+
103
+ [status, headers, [body]]
104
104
  end
105
105
 
106
- # Writes the Heroku Router queue time to STDOUT if a String was provided.
106
+ # Writes the Heroku Router queue time to $stdout if a String was provided.
107
107
  #
108
108
  # @param [String] the timestamp from HTTP_X_REQUEST_START.
109
109
  #
@@ -111,12 +111,12 @@ module HireFire
111
111
  HireFire::Resource.log_queue_metrics && value && log_queue(value)
112
112
  end
113
113
 
114
- # Writes the Heroku Router queue time to STDOUT.
114
+ # Writes the Heroku Router queue time to $stdout.
115
115
  #
116
116
  # @param [String] the timestamp from HTTP_X_REQUEST_START.
117
117
  #
118
118
  def log_queue(value)
119
- STDOUT.puts("[hirefire:router] queue=#{get_queue(value)}ms")
119
+ puts("[hirefire:router] queue=#{get_queue(value)}ms")
120
120
  end
121
121
 
122
122
  # Calculates the difference, in milliseconds, between the
@@ -129,5 +129,14 @@ module HireFire
129
129
  ms = (Time.now.to_f * 1000).to_i - value.to_i
130
130
  ms < 0 ? 0 : ms
131
131
  end
132
+
133
+ # Configures the @path_prefix in order to handle apps
134
+ # mounted under RAILS_RELATIVE_URL_ROOT.
135
+ #
136
+ def get_path_prefix
137
+ if defined?(Rails) && Rails.application.config.relative_url_root
138
+ Regexp.new("^" + Regexp.escape(Rails.application.config.relative_url_root))
139
+ end
140
+ end
132
141
  end
133
142
  end
@@ -4,7 +4,7 @@ module HireFire
4
4
  module Resource
5
5
  extend self
6
6
 
7
- # This option, when enabled, will write queue metrics to STDOUT,
7
+ # This option, when enabled, will write queue metrics to $stdout,
8
8
  # and is only required when using the Web.Logplex.QueueTime strategy.
9
9
  #
10
10
  # @param [Boolean] Whether or not the queue metrics should be logged.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hirefire-resource
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.7.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael van Rooijen
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-11-06 00:00:00.000000000 Z
11
+ date: 2020-08-30 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Load- and schedule-based scaling for web- and worker dynos
14
14
  email: michael@hirefire.io
@@ -19,6 +19,7 @@ extensions: []
19
19
  extra_rdoc_files: []
20
20
  files:
21
21
  - ".gitignore"
22
+ - CHANGELOG.md
22
23
  - LICENSE
23
24
  - README.md
24
25
  - Rakefile
@@ -40,8 +41,12 @@ files:
40
41
  homepage: https://www.hirefire.io
41
42
  licenses:
42
43
  - Apache License
43
- metadata: {}
44
- post_install_message:
44
+ metadata:
45
+ homepage_uri: https://www.hirefire.io
46
+ changelog_uri: https://github.com/hirefire/hirefire-resource/blob/master/CHANGELOG.md
47
+ source_code_uri: https://github.com/hirefire/hirefire-resource/
48
+ bug_tracker_uri: https://github.com/hirefire/hirefire-resource/issues
49
+ post_install_message:
45
50
  rdoc_options: []
46
51
  require_paths:
47
52
  - lib
@@ -56,9 +61,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
56
61
  - !ruby/object:Gem::Version
57
62
  version: '0'
58
63
  requirements: []
59
- rubyforge_project:
60
- rubygems_version: 2.7.7
61
- signing_key:
64
+ rubygems_version: 3.1.2
65
+ signing_key:
62
66
  specification_version: 4
63
67
  summary: Autoscaling for your Heroku dynos
64
68
  test_files: []