autoscale-agent 0.1.0 → 0.2.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fc5fb7bd79bb436a7f36d9c95b3f27f8a1437cc269da86c275cc00b434784ed2
4
- data.tar.gz: 69057429ec9c74443d3b23a8fbe5ef2fd7b716fe414393d4e59eef5944b533d2
3
+ metadata.gz: 5e5fac211926fd32008d9b5a34821744f5641c8b8cb87d8eac252216120e4ff0
4
+ data.tar.gz: 4c18afc1684e781380dad1eefa25f1415b315659919138839d3e2b016042e5a9
5
5
  SHA512:
6
- metadata.gz: 5379183c0664bb43b528c11d229f607328a1ce99a88865f4da0d4e955751c083bed3b57884bc85b915ed902c877199c853cd112214661dcd58e6a6e86596f2a7
7
- data.tar.gz: 493b64a3a84714e14b840a24ccb0a3197c6f6d8adf17ca4802a49cd3692ec3448216a49047df321eba5b2e9b7e9148b3702378d1290817f53be55d2ae1ccd15f
6
+ metadata.gz: c907c30ca3ad52721dcc9d702c2f2afcea7c14ca3851c60f3983ad7256bca5068d98c24b92416263bbc83ed915a3d9be1377597c4f8d7070c09099c5ee9c9012
7
+ data.tar.gz: 28c7a7328a84a2e8c30a8b98fb21a873ae5702fd23733c87023a53b4d3ab0b149fa19e56ae89642ac0e194081ff0b52bfed4fce4883c6c065552ce04ba362b9a
data/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.2.1] - 2023-04-24
4
+
5
+ - Don't run WorkerDispatchers#run in a separate thread
6
+
7
+
8
+ ## [0.2.0] - 2023-04-24
9
+
10
+ - Change when and where dispatchers are run
11
+
12
+ The WebDispatcher now runs in either the primary (sole) process, and
13
+ otherwise one in each forked (worker) process.
14
+
15
+ The WorkerDispatchers no longer automatically run
16
+ post-configuration. Instead, they must be manually started.
17
+
18
+ Note: WebDispatchers has been removed in favor of a single
19
+ WebDispatcher.
20
+
3
21
  ## [0.1.0] - 2023-03-03
4
22
 
5
23
  - Initial release
data/README.md CHANGED
@@ -38,6 +38,14 @@ See Rake for relevant tasks:
38
38
 
39
39
  bin/rake -T
40
40
 
41
+ ## Release
42
+
43
+ 1. Finalize CHANGELOG.md
44
+ 2. Update version.rb
45
+ 3. Run `bundle install`
46
+ 4. Commit
47
+ 5. Create and push a new tag (`v1.2.3`)
48
+
41
49
  ## Contributing
42
50
 
43
51
  Bug reports and pull requests are welcome on GitHub at https://github.com/autoscale-app/ruby-agent
@@ -7,21 +7,8 @@ module Autoscale
7
7
 
8
8
  class InvalidPlatformError < StandardError; end
9
9
 
10
- class << self
11
- attr_writer :run
12
-
13
- def run?
14
- !defined?(@run) || @run == true
15
- end
16
- end
17
-
18
10
  def initialize(&block)
19
11
  instance_eval(&block)
20
-
21
- if Configuration.run?
22
- web_dispatchers.run
23
- worker_dispatchers.run
24
- end
25
12
  end
26
13
 
27
14
  def platform(value = nil)
@@ -32,9 +19,7 @@ module Autoscale
32
19
  end
33
20
  end
34
21
 
35
- def web_dispatchers
36
- @web_dispatchers ||= WebDispatchers.new
37
- end
22
+ attr_reader :web_dispatcher
38
23
 
39
24
  def worker_dispatchers
40
25
  @worker_dispatchers ||= WorkerDispatchers.new
@@ -60,7 +45,7 @@ module Autoscale
60
45
  private
61
46
 
62
47
  def dispatch_web(token)
63
- web_dispatchers.queue_time = WebDispatcher.new(token)
48
+ @web_dispatcher = WebDispatcher.new(token)
64
49
  end
65
50
 
66
51
  def dispatch_worker(token, &block)
@@ -28,12 +28,13 @@ module Autoscale
28
28
 
29
29
  def record_queue_time(env)
30
30
  return unless request_start_header(env)
31
- return unless (dispatcher = Autoscale::Agent.configuration.web_dispatchers.queue_time)
31
+ return unless (dispatcher = Autoscale::Agent.configuration.web_dispatcher)
32
32
  current_time = (Time.now.to_f * 1000).to_i
33
33
  request_start_time = to_ms(request_start_header(env))
34
34
  elapsed_ms = current_time - request_start_time
35
35
  elapsed = (elapsed_ms < 0) ? 0 : elapsed_ms
36
36
  dispatcher.add(elapsed)
37
+ dispatcher.run
37
38
  end
38
39
 
39
40
  def request_start_header(env)
@@ -0,0 +1,16 @@
1
+ module Autoscale
2
+ module Agent
3
+ module Util
4
+ module_function
5
+
6
+ def loop_with_interval(interval, &block)
7
+ loop do
8
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
9
+ block.call
10
+ duration = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
11
+ sleep [0, interval - duration].max
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -1,5 +1,5 @@
1
1
  module Autoscale
2
2
  module Agent
3
- VERSION = "0.1.0".freeze
3
+ VERSION = "0.2.1".freeze
4
4
  end
5
5
  end
@@ -1,6 +1,7 @@
1
1
  module Autoscale
2
2
  module Agent
3
3
  class WebDispatcher
4
+ DISPATCH_INTERVAL = 15
4
5
  TTL = 30
5
6
 
6
7
  attr_reader :token
@@ -10,49 +11,68 @@ module Autoscale
10
11
  @token = token
11
12
  @buffer = {}
12
13
  @mutex = Mutex.new
14
+ @running = false
15
+ @running_lock = Mutex.new
13
16
  end
14
17
 
15
18
  def add(value, timestamp: Time.now.to_i)
16
19
  @mutex.synchronize do
17
- @buffer[timestamp] ||= 0
18
- @buffer[timestamp] = value if value > @buffer[timestamp]
19
- end
20
- end
21
-
22
- def prune
23
- @mutex.synchronize do
24
- max_age = Time.now.to_i - TTL
25
- @buffer.delete_if { |timestamp, _| timestamp < max_age }
20
+ add_unsafe(value, timestamp: timestamp)
26
21
  end
27
22
  end
28
23
 
29
24
  def dispatch
30
- return unless (payload = build_payload)
25
+ payload = flush
26
+
27
+ return if payload.empty?
31
28
 
32
29
  body = MultiJson.dump(payload)
33
30
  response = Request.dispatch(body, token: token)
34
31
 
35
32
  unless response.is_a?(Net::HTTPOK)
36
- revert_payload(payload)
33
+ revert(payload)
37
34
  error "Failed to dispatch (#{response.code}) #{response.body}"
38
35
  end
36
+ rescue => err
37
+ puts "Autoscale::Agent/WebDispatcher: #{err}\n#{err.backtrace.join("\n")}"
38
+ end
39
+
40
+ def run
41
+ @running_lock.synchronize do
42
+ return if @running
43
+ @running = true
44
+ end
45
+
46
+ Thread.new do
47
+ loop do
48
+ dispatch
49
+ sleep DISPATCH_INTERVAL
50
+ end
51
+ end
39
52
  end
40
53
 
41
54
  private
42
55
 
43
- def build_payload
56
+ def add_unsafe(value, timestamp: Time.now.to_i)
57
+ if timestamp > Time.now.to_i - TTL
58
+ @buffer[timestamp] ||= 0
59
+ @buffer[timestamp] = value if value > @buffer[timestamp]
60
+ end
61
+ end
62
+
63
+ def flush
44
64
  @mutex.synchronize do
45
- now = Time.now.to_i
46
- keys = @buffer.each_key.select { |key| key < now }
47
- payload = @buffer.slice(*keys)
48
- keys.each { |key| @buffer.delete(key) }
49
- payload if payload.any?
65
+ buffer = @buffer
66
+ @buffer = {}
67
+ buffer
50
68
  end
51
69
  end
52
70
 
53
- def revert_payload(payload)
54
- payload.each do |timestamp, value|
55
- add(value, timestamp: timestamp)
71
+ def revert(payload)
72
+ @mutex.synchronize do
73
+ payload.each do |timestamp, value|
74
+ add_unsafe(value, timestamp: timestamp)
75
+ end
56
76
  end
57
77
  end
58
78
 
@@ -26,12 +26,7 @@ module Autoscale
26
26
  end
27
27
 
28
28
  def run
29
- Thread.new do
30
- loop do
31
- dispatch
32
- sleep DISPATCH_INTERVAL
33
- end
34
- end
29
+ Util.loop_with_interval(DISPATCH_INTERVAL) { dispatch }
35
30
  end
36
31
  end
37
32
  end
@@ -4,10 +4,11 @@ require "multi_json"
4
4
 
5
5
  require_relative "agent/configuration"
6
6
  require_relative "agent/middleware"
7
+ require_relative "agent/railtie" if defined?(Rails::Railtie)
7
8
  require_relative "agent/request"
9
+ require_relative "agent/util"
8
10
  require_relative "agent/version"
9
11
  require_relative "agent/web_dispatcher"
10
- require_relative "agent/web_dispatchers"
11
12
  require_relative "agent/worker_dispatcher"
12
13
  require_relative "agent/worker_dispatchers"
13
14
  require_relative "agent/worker_server"
@@ -26,5 +27,3 @@ module Autoscale
26
27
  end
27
28
  end
28
29
  end
29
-
30
- require_relative "agent/railtie" if defined?(Rails::Railtie)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: autoscale-agent
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael R. van Rooijen
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-03-03 00:00:00.000000000 Z
11
+ date: 2023-04-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: multi_json
@@ -24,7 +24,7 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1'
27
- description:
27
+ description:
28
28
  email:
29
29
  - support@autoscale.app
30
30
  executables: []
@@ -40,9 +40,9 @@ files:
40
40
  - lib/autoscale/agent/middleware.rb
41
41
  - lib/autoscale/agent/railtie.rb
42
42
  - lib/autoscale/agent/request.rb
43
+ - lib/autoscale/agent/util.rb
43
44
  - lib/autoscale/agent/version.rb
44
45
  - lib/autoscale/agent/web_dispatcher.rb
45
- - lib/autoscale/agent/web_dispatchers.rb
46
46
  - lib/autoscale/agent/worker_dispatcher.rb
47
47
  - lib/autoscale/agent/worker_dispatchers.rb
48
48
  - lib/autoscale/agent/worker_server.rb
@@ -57,7 +57,7 @@ metadata:
57
57
  changelog_uri: https://github.com/autoscale-app/ruby-agent/blob/master/CHANGELOG.md
58
58
  bug_tracker_uri: https://github.com/autoscale-app/ruby-agent/issues
59
59
  rubygems_mfa_required: 'true'
60
- post_install_message:
60
+ post_install_message:
61
61
  rdoc_options: []
62
62
  require_paths:
63
63
  - lib
@@ -72,8 +72,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
72
72
  - !ruby/object:Gem::Version
73
73
  version: '0'
74
74
  requirements: []
75
- rubygems_version: 3.4.6
76
- signing_key:
75
+ rubygems_version: 3.4.10
76
+ signing_key:
77
77
  specification_version: 4
78
78
  summary: Provides Autoscale.app with the necessary metrics for autoscaling web and
79
79
  worker processes
@@ -1,47 +0,0 @@
1
- module Autoscale
2
- module Agent
3
- class WebDispatchers
4
- class AlreadySetError < StandardError
5
- end
6
-
7
- include Enumerable
8
-
9
- DISPATCH_INTERVAL = 15
10
-
11
- attr_reader :queue_time
12
-
13
- def initialize
14
- @dispatchers = []
15
- end
16
-
17
- def queue_time=(dispatcher)
18
- raise AlreadySetError if defined?(@queue_time)
19
- @dispatchers << (@queue_time = dispatcher)
20
- end
21
-
22
- def each(&block)
23
- @dispatchers.each(&block)
24
- end
25
-
26
- def prune
27
- each(&:prune)
28
- end
29
-
30
- def dispatch
31
- each(&:dispatch)
32
- rescue => err
33
- puts "Autoscale::Agent/WebDispatcher: #{err}\n#{err.backtrace.join("\n")}"
34
- end
35
-
36
- def run
37
- Thread.new do
38
- loop do
39
- prune
40
- dispatch
41
- sleep DISPATCH_INTERVAL
42
- end
43
- end
44
- end
45
- end
46
- end
47
- end