async-container 0.23.2 → 0.25.0

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: e7d6beef9d67eb3befeb6df39c14194bef86cefa104924e7eaff052571efbf68
4
- data.tar.gz: d18ac658a4dac083de68527533e1f476dfe56085b4ba67a46fa9e3ba8e92fa45
3
+ metadata.gz: e2613c963c3efb08cf02c6a6299668b2b9ed83b583bbe84ebc973fa099b62e4a
4
+ data.tar.gz: 9cc9cd1ac55d85be9684e9a042be6ff3e93dd44e69c2ce212ec5f7441cbf7b1d
5
5
  SHA512:
6
- metadata.gz: 285a31c7314187bae1a4866e5865f817a33f1f4192dc6df0991d345b71f8ca148de56bc3cae8c2c36199cffafa281b20efec533d2ba636fa11b031afed287496
7
- data.tar.gz: c8d2458ee451774b353512e8eeab6351d85695775d9a3d09f326f83bb3b462a31830701b82e8867e177bcb9f58b4085b19ed1832c7ab8229afb63b718fb1ac05
6
+ metadata.gz: ca31eb9ecbdd3c343ec77621778bcf7cfba210b5a1b7ba05a02d0e590f3574c8e0e25a4bcb85be5a6af05a601874084a2fab94dd2c422073c588816c899c7f46
7
+ data.tar.gz: 6ade195ca0f67619dbffee9b6f4dd6d567ccd05b2dd069075a10403c897806c1f33c3f44b06ef91a5ea5212b85c4cbf4c3a8f1ca4e02988a9559781c991e884f
checksums.yaml.gz.sig CHANGED
Binary file
@@ -5,6 +5,7 @@
5
5
 
6
6
  module Async
7
7
  module Container
8
+ # Represents an error that occured during container execution.
8
9
  class Error < StandardError
9
10
  end
10
11
 
@@ -13,15 +14,18 @@ module Async
13
14
  # Similar to {Interrupt}, but represents `SIGTERM`.
14
15
  class Terminate < SignalException
15
16
  SIGTERM = Signal.list["TERM"]
16
-
17
+
18
+ # Create a new terminate error.
17
19
  def initialize
18
20
  super(SIGTERM)
19
21
  end
20
22
  end
21
23
 
24
+ # Similar to {Interrupt}, but represents `SIGHUP`.
22
25
  class Restart < SignalException
23
26
  SIGHUP = Signal.list["HUP"]
24
27
 
28
+ # Create a new restart error.
25
29
  def initialize
26
30
  super(SIGHUP)
27
31
  end
@@ -29,13 +33,16 @@ module Async
29
33
 
30
34
  # Represents the error which occured when a container failed to start up correctly.
31
35
  class SetupError < Error
36
+ # Create a new setup error.
37
+ #
38
+ # @parameter container [Generic] The container that failed.
32
39
  def initialize(container)
33
40
  super("Could not create container!")
34
41
 
35
42
  @container = container
36
43
  end
37
44
 
38
- # The container that failed.
45
+ # @attribute [Generic] The container that failed.
39
46
  attr :container
40
47
  end
41
48
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2017-2024, by Samuel Williams.
4
+ # Copyright, 2017-2025, by Samuel Williams.
5
5
 
6
6
  require_relative "error"
7
7
 
@@ -35,12 +35,18 @@ module Async
35
35
  return instance
36
36
  end
37
37
 
38
+ # Initialize the child process instance.
39
+ #
40
+ # @parameter io [IO] The IO object to use for communication.
38
41
  def initialize(io)
39
42
  super
40
43
 
41
44
  @name = nil
42
45
  end
43
46
 
47
+ # Generate a hash representation of the process.
48
+ #
49
+ # @returns [Hash] The process as a hash, including `process_id` and `name`.
44
50
  def as_json(...)
45
51
  {
46
52
  process_id: ::Process.pid,
@@ -48,11 +54,15 @@ module Async
48
54
  }
49
55
  end
50
56
 
57
+ # Generate a JSON representation of the process.
58
+ #
59
+ # @returns [String] The process as JSON.
51
60
  def to_json(...)
52
61
  as_json.to_json(...)
53
62
  end
54
63
 
55
64
  # Set the process title to the specified value.
65
+ #
56
66
  # @parameter value [String] The name of the process.
57
67
  def name= value
58
68
  @name = value
@@ -61,14 +71,17 @@ module Async
61
71
  ::Process.setproctitle(@name.to_s)
62
72
  end
63
73
 
64
- # The name of the process.
65
- # @returns [String]
74
+ # @returns [String] The name of the process.
66
75
  def name
67
76
  @name
68
77
  end
69
78
 
70
79
  # Replace the current child process with a different one. Forwards arguments and options to {::Process.exec}.
71
80
  # This method replaces the child process with the new executable, thus this method never returns.
81
+ #
82
+ # @parameter arguments [Array] The arguments to pass to the new process.
83
+ # @parameter ready [Boolean] If true, informs the parent process that the child is ready. Otherwise, the child process will need to use a notification protocol to inform the parent process that it is ready.
84
+ # @parameter options [Hash] Additional options to pass to {::Process.exec}.
72
85
  def exec(*arguments, ready: true, **options)
73
86
  if ready
74
87
  self.ready!(status: "(exec)")
@@ -81,6 +94,7 @@ module Async
81
94
  end
82
95
 
83
96
  # Fork a child process appropriate for a container.
97
+ #
84
98
  # @returns [Process]
85
99
  def self.fork(**options)
86
100
  # $stderr.puts fork: caller
@@ -105,6 +119,13 @@ module Async
105
119
  end
106
120
  end
107
121
 
122
+ # Spawn a child process using {::Process.spawn}.
123
+ #
124
+ # The child process will need to inform the parent process that it is ready using a notification protocol.
125
+ #
126
+ # @parameter arguments [Array] The arguments to pass to the new process.
127
+ # @parameter name [String] The name of the process.
128
+ # @parameter options [Hash] Additional options to pass to {::Process.spawn}.
108
129
  def self.spawn(*arguments, name: nil, **options)
109
130
  self.new(name: name) do |process|
110
131
  Notify::Pipe.new(process.out).before_spawn(arguments, options)
@@ -168,6 +189,7 @@ module Async
168
189
  "\#<#{self.class} name=#{@name.inspect} status=#{@status.inspect} pid=#{@pid.inspect}>"
169
190
  end
170
191
 
192
+ # @returns [String] A string representation of the process.
171
193
  alias to_s inspect
172
194
 
173
195
  # Invoke {#terminate!} and then {#wait} for the child process to exit.
@@ -215,7 +237,7 @@ module Async
215
237
  Console.debug(self, "Waiting for process to exit...", pid: @pid)
216
238
 
217
239
  _, @status = ::Process.wait2(@pid, ::Process::WNOHANG)
218
-
240
+
219
241
  while @status.nil?
220
242
  sleep(0.1)
221
243
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2019-2024, by Samuel Williams.
4
+ # Copyright, 2019-2025, by Samuel Williams.
5
5
 
6
6
  require "etc"
7
7
  require "async/clock"
@@ -32,12 +32,16 @@ module Async
32
32
 
33
33
  # A base class for implementing containers.
34
34
  class Generic
35
- def self.run(*arguments, **options, &block)
36
- self.new.run(*arguments, **options, &block)
35
+ # Run a new container.
36
+ def self.run(...)
37
+ self.new.run(...)
37
38
  end
38
39
 
39
40
  UNNAMED = "Unnamed"
40
41
 
42
+ # Initialize the container.
43
+ #
44
+ # @parameter options [Hash] Options passed to the {Group} instance.
41
45
  def initialize(**options)
42
46
  @group = Group.new(**options)
43
47
  @running = true
@@ -145,6 +149,13 @@ module Async
145
149
  @running = true
146
150
  end
147
151
 
152
+ protected def health_check_failed!(child, age_clock, health_check_timeout)
153
+ Console.warn(self, "Child failed health check!", child: child, age: age_clock.total, health_check_timeout: health_check_timeout)
154
+
155
+ # If the child has failed the health check, we assume the worst and kill it immediately:
156
+ child.kill!
157
+ end
158
+
148
159
  # Spawn a child instance into the container.
149
160
  # @parameter name [String] The name of the child instance.
150
161
  # @parameter restart [Boolean] Whether to restart the child instance if it fails.
@@ -176,9 +187,7 @@ module Async
176
187
  case message
177
188
  when :health_check!
178
189
  if health_check_timeout&.<(age_clock.total)
179
- Console.warn(self, "Child failed health check!", child: child, age: age_clock.total, health_check_timeout: health_check_timeout)
180
- # If the child has failed the health check, we assume the worst and kill it immediately:
181
- child.kill!
190
+ health_check_failed!(child, age_clock, health_check_timeout)
182
191
  end
183
192
  else
184
193
  state.update(message)
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2018-2024, by Samuel Williams.
4
+ # Copyright, 2018-2025, by Samuel Williams.
5
5
 
6
6
  require "fiber"
7
7
  require "async/clock"
@@ -25,6 +25,7 @@ module Async
25
25
  @queue = nil
26
26
  end
27
27
 
28
+ # @returns [String] A human-readable representation of the group.
28
29
  def inspect
29
30
  "#<#{self.class} running=#{@running.size}>"
30
31
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2019-2024, by Samuel Williams.
4
+ # Copyright, 2019-2025, by Samuel Williams.
5
5
  # Copyright, 2022, by Anton Sozontov.
6
6
 
7
7
  require_relative "forked"
@@ -1,29 +1,30 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2020-2022, by Samuel Williams.
4
+ # Copyright, 2020-2025, by Samuel Williams.
5
5
 
6
6
  module Async
7
7
  module Container
8
8
  # Tracks a key/value pair such that unmarked keys can be identified and cleaned up.
9
9
  # This helps implement persistent processes that start up child processes per directory or configuration file. If those directories and/or configuration files are removed, the child process can then be cleaned up automatically, because those key/value pairs will not be marked when reloading the container.
10
10
  class Keyed
11
+ # Initialize the keyed instance
12
+ #
13
+ # @parameter key [Object] The key.
14
+ # @parameter value [Object] The value.
11
15
  def initialize(key, value)
12
16
  @key = key
13
17
  @value = value
14
18
  @marked = true
15
19
  end
16
20
 
17
- # The key. Normally a symbol or a file-system path.
18
- # @attribute [Object]
21
+ # @attribute [Object] The key value, normally a symbol or a file-system path.
19
22
  attr :key
20
23
 
21
- # The value. Normally a child instance of some sort.
22
- # @attribute [Object]
24
+ # @attribute [Object] The value, normally a child instance.
23
25
  attr :value
24
26
 
25
- # Has the instance been marked?
26
- # @returns [Boolean]
27
+ # @returns [Boolean] True if the instance has been marked, during reloading the container.
27
28
  def marked?
28
29
  @marked
29
30
  end
@@ -39,6 +40,8 @@ module Async
39
40
  end
40
41
 
41
42
  # Stop the instance if it was not marked.
43
+ #
44
+ # @returns [Boolean] True if the instance was stopped.
42
45
  def stop?
43
46
  unless @marked
44
47
  @value.stop
@@ -1,12 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2020-2022, by Samuel Williams.
4
+ # Copyright, 2020-2025, by Samuel Williams.
5
5
 
6
6
  module Async
7
7
  module Container
8
8
  # Handles the details of several process readiness protocols.
9
9
  module Notify
10
+ # Represents a client that can send messages to the parent controller in order to notify it of readiness, status changes, etc.
11
+ #
12
+ # A process readiness protocol (e.g. `sd_notify`) is a simple protocol for a child process to notify the parent process that it is ready (e.g. to accept connections, to process requests, etc). This can help dependency-based startup systems to start services in the correct order, and to handle failures gracefully.
10
13
  class Client
11
14
  # Notify the parent controller that the child has become ready, with a brief status message.
12
15
  # @parameters message [Hash] Additional details to send with the message.
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2020-2024, by Samuel Williams.
4
+ # Copyright, 2025, by Samuel Williams.
5
5
 
6
6
  require_relative "client"
7
7
  require "socket"
@@ -9,13 +9,21 @@ require "socket"
9
9
  module Async
10
10
  module Container
11
11
  module Notify
12
+ # Represents a client that uses a local log file to communicate readiness, status changes, etc.
12
13
  class Log < Client
13
14
  # The name of the environment variable which contains the path to the notification socket.
14
15
  NOTIFY_LOG = "NOTIFY_LOG"
15
16
 
17
+ # @returns [String] The path to the notification log file.
18
+ # @parameter environment [Hash] The environment variables, defaults to `ENV`.
19
+ def self.path(environment = ENV)
20
+ environment[NOTIFY_LOG]
21
+ end
22
+
16
23
  # Open a notification client attached to the current {NOTIFY_LOG} if possible.
24
+ # @parameter environment [Hash] The environment variables, defaults to `ENV`.
17
25
  def self.open!(environment = ENV)
18
- if path = environment.delete(NOTIFY_LOG)
26
+ if path = self.path(environment)
19
27
  self.new(path)
20
28
  end
21
29
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2020-2024, by Samuel Williams.
4
+ # Copyright, 2020-2025, by Samuel Williams.
5
5
  # Copyright, 2020, by Juan Antonio Martín Lucas.
6
6
 
7
7
  require_relative "client"
@@ -42,18 +42,18 @@ module Async
42
42
  if notify_pipe = options.delete(:notify_pipe)
43
43
  options[notify_pipe] = @io
44
44
  environment[NOTIFY_PIPE] = notify_pipe.to_s
45
-
45
+
46
46
  # Use stdout if it's not redirected:
47
47
  # This can cause issues if the user expects stdout to be connected to a terminal.
48
48
  # elsif !options.key?(:out)
49
49
  # options[:out] = @io
50
50
  # environment[NOTIFY_PIPE] = "1"
51
-
51
+
52
52
  # Use fileno 3 if it's available:
53
53
  elsif !options.key?(3)
54
54
  options[3] = @io
55
55
  environment[NOTIFY_PIPE] = "3"
56
-
56
+
57
57
  # Otherwise, give up!
58
58
  else
59
59
  raise ArgumentError, "Please specify valid file descriptor for notify_pipe!"
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2020-2024, by Samuel Williams.
4
+ # Copyright, 2020-2025, by Samuel Williams.
5
5
  # Copyright, 2020, by Olle Jonsson.
6
6
 
7
7
  require "tmpdir"
@@ -11,9 +11,14 @@ require "securerandom"
11
11
  module Async
12
12
  module Container
13
13
  module Notify
14
+ # A simple UDP server that can be used to receive messages from a child process, tracking readiness, status changes, etc.
14
15
  class Server
15
16
  MAXIMUM_MESSAGE_SIZE = 4096
16
17
 
18
+ # Parse a message, according to the `sd_notify` protocol.
19
+ #
20
+ # @parameter message [String] The message to parse.
21
+ # @returns [Hash] The parsed message.
17
22
  def self.load(message)
18
23
  lines = message.split("\n")
19
24
 
@@ -38,6 +43,9 @@ module Async
38
43
  return Hash[pairs]
39
44
  end
40
45
 
46
+ # Generate a new unique path for the UNIX socket.
47
+ #
48
+ # @returns [String] The path for the UNIX socket.
41
49
  def self.generate_path
42
50
  File.expand_path(
43
51
  "async-container-#{::Process.pid}-#{SecureRandom.hex(8)}.ipc",
@@ -45,21 +53,33 @@ module Async
45
53
  )
46
54
  end
47
55
 
56
+ # Open a new server instance with a temporary and unique path.
48
57
  def self.open(path = self.generate_path)
49
58
  self.new(path)
50
59
  end
51
60
 
61
+ # Initialize the server with the given path.
62
+ #
63
+ # @parameter path [String] The path to the UNIX socket.
52
64
  def initialize(path)
53
65
  @path = path
54
66
  end
55
67
 
68
+ # @attribute [String] The path to the UNIX socket.
56
69
  attr :path
57
70
 
71
+ # Generate a bound context for receiving messages.
72
+ #
73
+ # @returns [Context] The bound context.
58
74
  def bind
59
75
  Context.new(@path)
60
76
  end
61
77
 
78
+ # A bound context for receiving messages.
62
79
  class Context
80
+ # Initialize the context with the given path.
81
+ #
82
+ # @parameter path [String] The path to the UNIX socket.
63
83
  def initialize(path)
64
84
  @path = path
65
85
  @bound = Addrinfo.unix(@path, ::Socket::SOCK_DGRAM).bind
@@ -67,12 +87,16 @@ module Async
67
87
  @state = {}
68
88
  end
69
89
 
90
+ # Close the bound context.
70
91
  def close
71
92
  @bound.close
72
93
 
73
94
  File.unlink(@path)
74
95
  end
75
96
 
97
+ # Receive a message from the bound context.
98
+ #
99
+ # @returns [Hash] The parsed message.
76
100
  def receive
77
101
  while true
78
102
  data, _address, _flags, *_controls = @bound.recvmsg(MAXIMUM_MESSAGE_SIZE)
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2020-2024, by Samuel Williams.
4
+ # Copyright, 2020-2025, by Samuel Williams.
5
5
 
6
6
  require_relative "client"
7
7
  require "socket"
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2020-2024, by Samuel Williams.
4
+ # Copyright, 2020-2025, by Samuel Williams.
5
5
 
6
6
  require_relative "notify/pipe"
7
7
  require_relative "notify/socket"
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2019-2024, by Samuel Williams.
4
+ # Copyright, 2019-2025, by Samuel Williams.
5
5
 
6
6
  require "async/reactor"
7
7
 
@@ -9,6 +9,7 @@ module Async
9
9
  module Container
10
10
  # Tracks various statistics relating to child instances in a container.
11
11
  class Statistics
12
+ # Initialize the statistics all to 0.
12
13
  def initialize
13
14
  @spawns = 0
14
15
  @restarts = 0
@@ -11,9 +11,6 @@ module Async
11
11
  module Container
12
12
  # A multi-thread container which uses {Thread.fork}.
13
13
  class Threaded < Generic
14
- class Kill < Exception
15
- end
16
-
17
14
  # Indicates that this is not a multi-process container.
18
15
  def self.multiprocess?
19
16
  false
@@ -52,12 +49,18 @@ module Async
52
49
  return instance
53
50
  end
54
51
 
52
+ # Initialize the child thread instance.
53
+ #
54
+ # @parameter io [IO] The IO object to use for communication with the parent.
55
55
  def initialize(io)
56
56
  @thread = ::Thread.current
57
57
 
58
58
  super
59
59
  end
60
60
 
61
+ # Generate a hash representation of the thread.
62
+ #
63
+ # @returns [Hash] The thread as a hash, including `process_id`, `thread_id`, and `name`.
61
64
  def as_json(...)
62
65
  {
63
66
  process_id: ::Process.pid,
@@ -66,6 +69,9 @@ module Async
66
69
  }
67
70
  end
68
71
 
72
+ # Generate a JSON representation of the thread.
73
+ #
74
+ # @returns [String] The thread as JSON.
69
75
  def to_json(...)
70
76
  as_json.to_json(...)
71
77
  end
@@ -101,6 +107,9 @@ module Async
101
107
  end
102
108
  end
103
109
 
110
+ # Start a new child thread and execute the provided block in it.
111
+ #
112
+ # @parameter options [Hash] Additional options to to the new child instance.
104
113
  def self.fork(**options)
105
114
  self.new(**options) do |thread|
106
115
  ::Thread.new do
@@ -113,6 +122,7 @@ module Async
113
122
  end
114
123
 
115
124
  # Initialize the thread.
125
+ #
116
126
  # @parameter name [String] The name to use for the child thread.
117
127
  def initialize(name: nil)
118
128
  super()
@@ -230,6 +240,9 @@ module Async
230
240
  @error.nil?
231
241
  end
232
242
 
243
+ # Convert the status to a hash, suitable for serialization.
244
+ #
245
+ # @returns [Boolean | String] If the status is an error, the error message is returned, otherwise `true`.
233
246
  def as_json(...)
234
247
  if @error
235
248
  @error.inspect
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2017-2024, by Samuel Williams.
4
+ # Copyright, 2017-2025, by Samuel Williams.
5
5
 
6
6
  module Async
7
7
  module Container
8
- VERSION = "0.23.2"
8
+ VERSION = "0.25.0"
9
9
  end
10
10
  end
@@ -1,11 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2017-2024, by Samuel Williams.
4
+ # Copyright, 2017-2025, by Samuel Williams.
5
5
 
6
6
  require_relative "container/controller"
7
7
 
8
+ # @namespace
8
9
  module Async
10
+ # @namespace
9
11
  module Container
10
12
  end
11
13
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2025, by Samuel Williams.
5
+
6
+ require_relative "../../../../async/container/generic"
7
+ require "metrics/provider"
8
+
9
+ Metrics::Provider(Async::Container::Generic) do
10
+ ASYNC_CONTAINER_GENERIC_HEALTH_CHECK_FAILED = Metrics.metric("async.container.generic.health_check_failed", :counter, description: "The number of health checks that failed.")
11
+
12
+ protected def health_check_failed!(child, age_clock, health_check_timeout)
13
+ ASYNC_CONTAINER_GENERIC_HEALTH_CHECK_FAILED.emit(1)
14
+
15
+ super
16
+ end
17
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2025, by Samuel Williams.
5
+
6
+ require_relative "container/generic"
data/readme.md CHANGED
@@ -18,10 +18,22 @@ Please see the [project documentation](https://socketry.github.io/async-containe
18
18
 
19
19
  - [Getting Started](https://socketry.github.io/async-container/guides/getting-started/index) - This guide explains how to use `async-container` to build basic scalable systems.
20
20
 
21
+ - [Systemd Integration](https://socketry.github.io/async-container/guides/systemd-integration/index) - This guide explains how to use `async-container` with systemd to manage your application as a service.
22
+
23
+ - [Kubernetes Integration](https://socketry.github.io/async-container/guides/kubernetes-integration/index) - This guide explains how to use `async-container` with Kubernetes to manage your application as a containerized service.
24
+
21
25
  ## Releases
22
26
 
23
27
  Please see the [project releases](https://socketry.github.io/async-container/releases/index) for all releases.
24
28
 
29
+ ### v0.25.0
30
+
31
+ - Introduce `async:container:notify:log:ready?` task for detecting process readiness.
32
+
33
+ ### v0.24.0
34
+
35
+ - Add support for health check failure metrics.
36
+
25
37
  ### v0.23.0
26
38
 
27
39
  - [Add support for `NOTIFY_LOG` for Kubernetes readiness probes.](https://socketry.github.io/async-container/releases/index#add-support-for-notify_log-for-kubernetes-readiness-probes.)
data/releases.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Releases
2
2
 
3
+ ## v0.25.0
4
+
5
+ - Introduce `async:container:notify:log:ready?` task for detecting process readiness.
6
+
7
+ ## v0.24.0
8
+
9
+ - Add support for health check failure metrics.
10
+
3
11
  ## v0.23.0
4
12
 
5
13
  ### Add support for `NOTIFY_LOG` for Kubernetes readiness probes.
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: async-container
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.23.2
4
+ version: 0.25.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
@@ -40,7 +40,7 @@ cert_chain:
40
40
  Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
41
41
  voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
42
42
  -----END CERTIFICATE-----
43
- date: 2025-02-28 00:00:00.000000000 Z
43
+ date: 1980-01-02 00:00:00.000000000 Z
44
44
  dependencies:
45
45
  - !ruby/object:Gem::Dependency
46
46
  name: async
@@ -80,6 +80,8 @@ files:
80
80
  - lib/async/container/statistics.rb
81
81
  - lib/async/container/threaded.rb
82
82
  - lib/async/container/version.rb
83
+ - lib/metrics/provider/async/container.rb
84
+ - lib/metrics/provider/async/container/generic.rb
83
85
  - license.md
84
86
  - readme.md
85
87
  - releases.md
@@ -96,14 +98,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
96
98
  requirements:
97
99
  - - ">="
98
100
  - !ruby/object:Gem::Version
99
- version: '3.1'
101
+ version: '3.2'
100
102
  required_rubygems_version: !ruby/object:Gem::Requirement
101
103
  requirements:
102
104
  - - ">="
103
105
  - !ruby/object:Gem::Version
104
106
  version: '0'
105
107
  requirements: []
106
- rubygems_version: 3.6.2
108
+ rubygems_version: 3.6.7
107
109
  specification_version: 4
108
110
  summary: Abstract container-based parallelism using threads and processes where appropriate.
109
111
  test_files: []
metadata.gz.sig CHANGED
Binary file