autoscale-agent 0.1.0 → 0.2.1

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: 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