async-container 0.27.2 → 0.27.4

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: 7d43fc927cb1564c1ed256976873b66245386fe54d11467935184c1f38da9d96
4
- data.tar.gz: 3738e9b3009bd87388fe23c34085d99a4ba384fe8ef274465ec732a8398f6b7b
3
+ metadata.gz: a81d686d7bcf4debd164fb322e88e4da3bbc9224d5191c49f020d386b996ecf4
4
+ data.tar.gz: fd4ff31ee2a1b3b03d4a72b9b73ae1e398bff6966b8b68759c27f0db6972b825
5
5
  SHA512:
6
- metadata.gz: 14700cf9cb8952affd49569383348715fa357660b809f033a1a0d345a03f3b16145ec868b07022df1bece5224008a49ce78441d86113ef18c94530247fadf104
7
- data.tar.gz: 7665c5a66280b04bd835e9708e81fff08ab5116ab07886fae1aa3c3b155bef6011167d10bcdb63b08c3a877d5df795dd3901740a0e46ac0a433ff7cf024feac1
6
+ metadata.gz: b3ab253a07c2c1878c316d3bd19a6889969741ccaea279dc4e1d9787f1ffd4973445f98f9262b8dfa0d1d30dda0114327226e14696632ec8813ab7648a37e95f
7
+ data.tar.gz: bf928811afebfd226c25ca62d368624f6914a283d07470277ee159903694e412268c6e2d2965cbe834ea9205c097ca2d8a78eb8f3664cb6a74fca4fe8c90c9c4
checksums.yaml.gz.sig CHANGED
Binary file
@@ -260,7 +260,6 @@ module Async
260
260
  end
261
261
  end
262
262
 
263
-
264
263
  # Start a named child process and execute the provided block in it.
265
264
  # @parameter name [String] The name (title) of the child process.
266
265
  # @parameter block [Proc] The block to execute in the child process.
@@ -179,10 +179,13 @@ module Async
179
179
 
180
180
  fiber do
181
181
  while @running
182
- child = self.start(name, &block)
182
+ Console.info(self, "Starting child...", child: {key: key, name: name, restart: restart, health_check_timeout: health_check_timeout}, statistics: @statistics)
183
183
 
184
+ child = self.start(name, &block)
184
185
  state = insert(key, child)
185
186
 
187
+ Console.info(self, "Started child.", child: child, spawn: {key: key, restart: restart, health_check_timeout: health_check_timeout}, statistics: @statistics)
188
+
186
189
  # If a health check is specified, we will monitor the child process and terminate it if it does not update its state within the specified time.
187
190
  if health_check_timeout
188
191
  age_clock = state[:age] = Clock.start
@@ -100,9 +100,14 @@ module Async
100
100
  end
101
101
  end
102
102
 
103
+ private def each_running(&block)
104
+ # We create a copy of the values here, in case the block modifies the running set:
105
+ @running.values.each(&block)
106
+ end
107
+
103
108
  # Perform a health check on all running processes.
104
109
  def health_check!
105
- @running.each_value do |fiber|
110
+ each_running do |fiber|
106
111
  fiber.resume(:health_check!)
107
112
  end
108
113
  end
@@ -111,7 +116,7 @@ module Async
111
116
  # This resumes the controlling fiber with an instance of {Interrupt}.
112
117
  def interrupt
113
118
  Console.info(self, "Sending interrupt to #{@running.size} running processes...")
114
- @running.each_value do |fiber|
119
+ each_running do |fiber|
115
120
  fiber.resume(Interrupt)
116
121
  end
117
122
  end
@@ -120,7 +125,7 @@ module Async
120
125
  # This resumes the controlling fiber with an instance of {Terminate}.
121
126
  def terminate
122
127
  Console.info(self, "Sending terminate to #{@running.size} running processes...")
123
- @running.each_value do |fiber|
128
+ each_running do |fiber|
124
129
  fiber.resume(Terminate)
125
130
  end
126
131
  end
@@ -129,7 +134,7 @@ module Async
129
134
  # This resumes the controlling fiber with an instance of {Kill}.
130
135
  def kill
131
136
  Console.info(self, "Sending kill to #{@running.size} running processes...")
132
- @running.each_value do |fiber|
137
+ each_running do |fiber|
133
138
  fiber.resume(Kill)
134
139
  end
135
140
  end
@@ -183,7 +188,7 @@ module Async
183
188
  self.wait_for_exit(clock, interrupt_timeout)
184
189
  end
185
190
 
186
- if terminate_timeout
191
+ if terminate_timeout and self.any?
187
192
  clock = Async::Clock.start
188
193
 
189
194
  # If the children are still running, terminate them:
@@ -231,8 +236,8 @@ module Async
231
236
  protected
232
237
 
233
238
  def wait_for_children(duration = nil)
234
- # This log is a big noisy and doesn't really provide a lot of useful information.
235
- # Console.debug(self, "Waiting for children...", duration: duration, running: @running)
239
+ # This log is a bit noisy and doesn't really provide a lot of useful information:
240
+ Console.debug(self, "Waiting for children...", duration: duration, running: @running)
236
241
 
237
242
  unless @running.empty?
238
243
  # Maybe consider using a proper event loop here:
@@ -56,6 +56,24 @@ module Async
56
56
  @restarts += other.restarts
57
57
  @failures += other.failures
58
58
  end
59
+
60
+ # Generate a hash representation of the statistics.
61
+ #
62
+ # @returns [Hash] The statistics as a hash.
63
+ def as_json(...)
64
+ {
65
+ spawns: @spawns,
66
+ restarts: @restarts,
67
+ failures: @failures,
68
+ }
69
+ end
70
+
71
+ # Generate a JSON representation of the statistics.
72
+ #
73
+ # @returns [String] The statistics as JSON.
74
+ def to_json(...)
75
+ as_json.to_json(...)
76
+ end
59
77
  end
60
78
  end
61
79
  end
@@ -5,6 +5,6 @@
5
5
 
6
6
  module Async
7
7
  module Container
8
- VERSION = "0.27.2"
8
+ VERSION = "0.27.4"
9
9
  end
10
10
  end
data/readme.md CHANGED
@@ -26,6 +26,15 @@ Please see the [project documentation](https://socketry.github.io/async-containe
26
26
 
27
27
  Please see the [project releases](https://socketry.github.io/async-container/releases/index) for all releases.
28
28
 
29
+ ### v0.27.4
30
+
31
+ - Fix race condition where `wait_for` could modify `@running` while it was being iterated over (`each_value`) during health checks.
32
+
33
+ ### v0.27.3
34
+
35
+ - Add log for starting child, including container statistics.
36
+ - Don't try to (log) "terminate 0 child processes" if there are none.
37
+
29
38
  ### v0.27.2
30
39
 
31
40
  - More logging, especially around failure cases.
@@ -59,17 +68,6 @@ Please see the [project releases](https://socketry.github.io/async-container/rel
59
68
 
60
69
  - Use `SIGKILL`/`Thread#kill` when the health check fails. In some cases, `SIGTERM` may not be sufficient to terminate a process because the signal can be ignored or the process may be in an uninterruptible state.
61
70
 
62
- ### v0.20.1
63
-
64
- - Fix compatibility between <code class="language-ruby">Async::Container::Hybrid</code> and the health check.
65
- - <code class="language-ruby">Async::Container::Generic\#initialize</code> passes unused arguments through to <code class="language-ruby">Async::Container::Group</code>.
66
-
67
- ### v0.20.0
68
-
69
- - Improve container signal handling reliability by using `Thread.handle_interrupt` except at known safe points.
70
- - Improved logging when child process fails and container startup.
71
- - [Add `health_check_timeout` for detecting hung processes.](https://socketry.github.io/async-container/releases/index#add-health_check_timeout-for-detecting-hung-processes.)
72
-
73
71
  ## Contributing
74
72
 
75
73
  We welcome contributions to this project.
data/releases.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Releases
2
2
 
3
+ ## v0.27.4
4
+
5
+ - Fix race condition where `wait_for` could modify `@running` while it was being iterated over (`each_value`) during health checks.
6
+
7
+ ## v0.27.3
8
+
9
+ - Add log for starting child, including container statistics.
10
+ - Don't try to (log) "terminate 0 child processes" if there are none.
11
+
3
12
  ## v0.27.2
4
13
 
5
14
  - More logging, especially around failure cases.
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.27.2
4
+ version: 0.27.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
metadata.gz.sig CHANGED
Binary file