async-container 0.27.1 → 0.27.7
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 +4 -4
 - checksums.yaml.gz.sig +0 -0
 - data/lib/async/container/channel.rb +7 -7
 - data/lib/async/container/controller.rb +10 -11
 - data/lib/async/container/forked.rb +2 -3
 - data/lib/async/container/generic.rb +20 -6
 - data/lib/async/container/group.rb +12 -7
 - data/lib/async/container/notify/pipe.rb +2 -2
 - data/lib/async/container/statistics.rb +18 -0
 - data/lib/async/container/threaded.rb +2 -2
 - data/lib/async/container/version.rb +1 -1
 - data/license.md +1 -0
 - data/readme.md +17 -15
 - data/releases.md +17 -0
 - data.tar.gz.sig +0 -0
 - metadata +3 -2
 - metadata.gz.sig +0 -0
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 4e0f77eb0f6eb3e7e8f8971af4d653e5ff2c3243ecc12f8dd06b27ae27e09d45
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 869aaa117d285f6f407b482b5fcd5b3bb19edcba215202d2faefe159195eed38
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: f1eb59fda7b292a5ca70b15ea0b70af9d6f41551d9a4818f5820dbc9b078f3008d37f646e8cbcdc74428d3c359c9ec9e731b3b0b008a74922f379b700eda32e4
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 301401ff8bcd736d2e41d1816110625ce038ff65b0a675d11e0ec900feb5550c73e6e754af9e5123dd12b692e4980deac1d197cbdad38e3a48213b38dd938171
         
     | 
    
        checksums.yaml.gz.sig
    CHANGED
    
    | 
         Binary file 
     | 
| 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            # Released under the MIT License.
         
     | 
| 
       4 
     | 
    
         
            -
            # Copyright, 2020- 
     | 
| 
      
 4 
     | 
    
         
            +
            # Copyright, 2020-2025, by Samuel Williams.
         
     | 
| 
       5 
5 
     | 
    
         | 
| 
       6 
6 
     | 
    
         
             
            require "json"
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
         @@ -10,8 +10,9 @@ module Async 
     | 
|
| 
       10 
10 
     | 
    
         
             
            		# Provides a basic multi-thread/multi-process uni-directional communication channel.
         
     | 
| 
       11 
11 
     | 
    
         
             
            		class Channel
         
     | 
| 
       12 
12 
     | 
    
         
             
            			# Initialize the channel using a pipe.
         
     | 
| 
       13 
     | 
    
         
            -
            			def initialize
         
     | 
| 
      
 13 
     | 
    
         
            +
            			def initialize(timeout: 1.0)
         
     | 
| 
       14 
14 
     | 
    
         
             
            				@in, @out = ::IO.pipe
         
     | 
| 
      
 15 
     | 
    
         
            +
            				@in.timeout = timeout
         
     | 
| 
       15 
16 
     | 
    
         
             
            			end
         
     | 
| 
       16 
17 
     | 
    
         | 
| 
       17 
18 
     | 
    
         
             
            			# The input end of the pipe.
         
     | 
| 
         @@ -43,12 +44,11 @@ module Async 
     | 
|
| 
       43 
44 
     | 
    
         
             
            			# @returns [Hash]
         
     | 
| 
       44 
45 
     | 
    
         
             
            			def receive
         
     | 
| 
       45 
46 
     | 
    
         
             
            				if data = @in.gets
         
     | 
| 
       46 
     | 
    
         
            -
            					 
     | 
| 
       47 
     | 
    
         
            -
            						return JSON.parse(data, symbolize_names: true)
         
     | 
| 
       48 
     | 
    
         
            -
            					rescue
         
     | 
| 
       49 
     | 
    
         
            -
            						return {line: data}
         
     | 
| 
       50 
     | 
    
         
            -
            					end
         
     | 
| 
      
 47 
     | 
    
         
            +
            					return JSON.parse(data, symbolize_names: true)
         
     | 
| 
       51 
48 
     | 
    
         
             
            				end
         
     | 
| 
      
 49 
     | 
    
         
            +
            			rescue => error
         
     | 
| 
      
 50 
     | 
    
         
            +
            				Console.error(self, "Error during channel receive!", error)
         
     | 
| 
      
 51 
     | 
    
         
            +
            				return nil
         
     | 
| 
       52 
52 
     | 
    
         
             
            			end
         
     | 
| 
       53 
53 
     | 
    
         
             
            		end
         
     | 
| 
       54 
54 
     | 
    
         
             
            	end
         
     | 
| 
         @@ -91,11 +91,11 @@ module Async 
     | 
|
| 
       91 
91 
     | 
    
         
             
            			# Start the container unless it's already running.
         
     | 
| 
       92 
92 
     | 
    
         
             
            			def start
         
     | 
| 
       93 
93 
     | 
    
         
             
            				unless @container
         
     | 
| 
       94 
     | 
    
         
            -
            					Console.info(self 
     | 
| 
      
 94 
     | 
    
         
            +
            					Console.info(self, "Controller starting...")
         
     | 
| 
       95 
95 
     | 
    
         
             
            					self.restart
         
     | 
| 
       96 
96 
     | 
    
         
             
            				end
         
     | 
| 
       97 
97 
     | 
    
         | 
| 
       98 
     | 
    
         
            -
            				Console.info(self 
     | 
| 
      
 98 
     | 
    
         
            +
            				Console.info(self, "Controller started...")
         
     | 
| 
       99 
99 
     | 
    
         
             
            			end
         
     | 
| 
       100 
100 
     | 
    
         | 
| 
       101 
101 
     | 
    
         
             
            			# Stop the container if it's running.
         
     | 
| 
         @@ -111,9 +111,9 @@ module Async 
     | 
|
| 
       111 
111 
     | 
    
         
             
            				if @container
         
     | 
| 
       112 
112 
     | 
    
         
             
            					@notify&.restarting!
         
     | 
| 
       113 
113 
     | 
    
         | 
| 
       114 
     | 
    
         
            -
            					Console. 
     | 
| 
      
 114 
     | 
    
         
            +
            					Console.info(self, "Restarting container...")
         
     | 
| 
       115 
115 
     | 
    
         
             
            				else
         
     | 
| 
       116 
     | 
    
         
            -
            					Console. 
     | 
| 
      
 116 
     | 
    
         
            +
            					Console.info(self, "Starting container...")
         
     | 
| 
       117 
117 
     | 
    
         
             
            				end
         
     | 
| 
       118 
118 
     | 
    
         | 
| 
       119 
119 
     | 
    
         
             
            				container = self.create_container
         
     | 
| 
         @@ -127,13 +127,14 @@ module Async 
     | 
|
| 
       127 
127 
     | 
    
         
             
            				end
         
     | 
| 
       128 
128 
     | 
    
         | 
| 
       129 
129 
     | 
    
         
             
            				# Wait for all child processes to enter the ready state.
         
     | 
| 
       130 
     | 
    
         
            -
            				Console. 
     | 
| 
      
 130 
     | 
    
         
            +
            				Console.info(self, "Waiting for startup...")
         
     | 
| 
       131 
131 
     | 
    
         
             
            				container.wait_until_ready
         
     | 
| 
       132 
     | 
    
         
            -
            				Console. 
     | 
| 
      
 132 
     | 
    
         
            +
            				Console.info(self, "Finished startup.")
         
     | 
| 
       133 
133 
     | 
    
         | 
| 
       134 
134 
     | 
    
         
             
            				if container.failed?
         
     | 
| 
       135 
135 
     | 
    
         
             
            					@notify&.error!("Container failed to start!")
         
     | 
| 
       136 
136 
     | 
    
         | 
| 
      
 137 
     | 
    
         
            +
            					Console.info(self, "Stopping failed container...")
         
     | 
| 
       137 
138 
     | 
    
         
             
            					container.stop(false)
         
     | 
| 
       138 
139 
     | 
    
         | 
| 
       139 
140 
     | 
    
         
             
            					raise SetupError, container
         
     | 
| 
         @@ -145,7 +146,7 @@ module Async 
     | 
|
| 
       145 
146 
     | 
    
         
             
            				container = nil
         
     | 
| 
       146 
147 
     | 
    
         | 
| 
       147 
148 
     | 
    
         
             
            				if old_container
         
     | 
| 
       148 
     | 
    
         
            -
            					Console. 
     | 
| 
      
 149 
     | 
    
         
            +
            					Console.info(self, "Stopping old container...")
         
     | 
| 
       149 
150 
     | 
    
         
             
            					old_container&.stop(@graceful_stop)
         
     | 
| 
       150 
151 
     | 
    
         
             
            				end
         
     | 
| 
       151 
152 
     | 
    
         | 
| 
         @@ -168,11 +169,9 @@ module Async 
     | 
|
| 
       168 
169 
     | 
    
         
             
            				end
         
     | 
| 
       169 
170 
     | 
    
         | 
| 
       170 
171 
     | 
    
         
             
            				# Wait for all child processes to enter the ready state.
         
     | 
| 
       171 
     | 
    
         
            -
            				Console. 
     | 
| 
       172 
     | 
    
         
            -
            				
         
     | 
| 
      
 172 
     | 
    
         
            +
            				Console.info(self, "Waiting for startup...")
         
     | 
| 
       173 
173 
     | 
    
         
             
            				@container.wait_until_ready
         
     | 
| 
       174 
     | 
    
         
            -
            				
         
     | 
| 
       175 
     | 
    
         
            -
            				Console.debug(self, "Finished startup.")
         
     | 
| 
      
 174 
     | 
    
         
            +
            				Console.info(self, "Finished startup.")
         
     | 
| 
       176 
175 
     | 
    
         | 
| 
       177 
176 
     | 
    
         
             
            				if @container.failed?
         
     | 
| 
       178 
177 
     | 
    
         
             
            					@notify.error!("Container failed to reload!")
         
     | 
| 
         @@ -136,8 +136,8 @@ module Async 
     | 
|
| 
       136 
136 
     | 
    
         | 
| 
       137 
137 
     | 
    
         
             
            				# Initialize the process.
         
     | 
| 
       138 
138 
     | 
    
         
             
            				# @parameter name [String] The name to use for the child process.
         
     | 
| 
       139 
     | 
    
         
            -
            				def initialize(name: nil)
         
     | 
| 
       140 
     | 
    
         
            -
            					super()
         
     | 
| 
      
 139 
     | 
    
         
            +
            				def initialize(name: nil, **options)
         
     | 
| 
      
 140 
     | 
    
         
            +
            					super(**options)
         
     | 
| 
       141 
141 
     | 
    
         | 
| 
       142 
142 
     | 
    
         
             
            					@name = name
         
     | 
| 
       143 
143 
     | 
    
         
             
            					@status = nil
         
     | 
| 
         @@ -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.
         
     | 
| 
         @@ -2,6 +2,7 @@ 
     | 
|
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            # Released under the MIT License.
         
     | 
| 
       4 
4 
     | 
    
         
             
            # Copyright, 2019-2025, by Samuel Williams.
         
     | 
| 
      
 5 
     | 
    
         
            +
            # Copyright, 2025, by Marc-André Cournoyer.
         
     | 
| 
       5 
6 
     | 
    
         | 
| 
       6 
7 
     | 
    
         
             
            require "etc"
         
     | 
| 
       7 
8 
     | 
    
         
             
            require "async/clock"
         
     | 
| 
         @@ -139,12 +140,18 @@ module Async 
     | 
|
| 
       139 
140 
     | 
    
         
             
            			# Stop the children instances.
         
     | 
| 
       140 
141 
     | 
    
         
             
            			# @parameter timeout [Boolean | Numeric] Whether to stop gracefully, or a specific timeout.
         
     | 
| 
       141 
142 
     | 
    
         
             
            			def stop(timeout = true)
         
     | 
| 
      
 143 
     | 
    
         
            +
            				Console.info(self, "Stopping container...", timeout: timeout, caller: caller_locations)
         
     | 
| 
       142 
144 
     | 
    
         
             
            				@running = false
         
     | 
| 
       143 
145 
     | 
    
         
             
            				@group.stop(timeout)
         
     | 
| 
       144 
146 
     | 
    
         | 
| 
       145 
147 
     | 
    
         
             
            				if @group.running?
         
     | 
| 
       146 
     | 
    
         
            -
            					Console.warn(self 
     | 
| 
      
 148 
     | 
    
         
            +
            					Console.warn(self, "Group is still running after stopping it!")
         
     | 
| 
      
 149 
     | 
    
         
            +
            				else
         
     | 
| 
      
 150 
     | 
    
         
            +
            					Console.info(self, "Group has stopped.")
         
     | 
| 
       147 
151 
     | 
    
         
             
            				end
         
     | 
| 
      
 152 
     | 
    
         
            +
            			rescue => error
         
     | 
| 
      
 153 
     | 
    
         
            +
            				Console.error(self, "Error while stopping container!", exception: error)
         
     | 
| 
      
 154 
     | 
    
         
            +
            				raise
         
     | 
| 
       148 
155 
     | 
    
         
             
            			ensure
         
     | 
| 
       149 
156 
     | 
    
         
             
            				@running = true
         
     | 
| 
       150 
157 
     | 
    
         
             
            			end
         
     | 
| 
         @@ -165,7 +172,7 @@ module Async 
     | 
|
| 
       165 
172 
     | 
    
         
             
            				name ||= UNNAMED
         
     | 
| 
       166 
173 
     | 
    
         | 
| 
       167 
174 
     | 
    
         
             
            				if mark?(key)
         
     | 
| 
       168 
     | 
    
         
            -
            					Console.debug(self 
     | 
| 
      
 175 
     | 
    
         
            +
            					Console.debug(self, "Reusing existing child.", child: {key: key, name: name})
         
     | 
| 
       169 
176 
     | 
    
         
             
            					return false
         
     | 
| 
       170 
177 
     | 
    
         
             
            				end
         
     | 
| 
       171 
178 
     | 
    
         | 
| 
         @@ -173,15 +180,20 @@ module Async 
     | 
|
| 
       173 
180 
     | 
    
         | 
| 
       174 
181 
     | 
    
         
             
            				fiber do
         
     | 
| 
       175 
182 
     | 
    
         
             
            					while @running
         
     | 
| 
       176 
     | 
    
         
            -
            						child  
     | 
| 
      
 183 
     | 
    
         
            +
            						Console.debug(self, "Starting child...", child: {key: key, name: name, restart: restart, health_check_timeout: health_check_timeout}, statistics: @statistics)
         
     | 
| 
       177 
184 
     | 
    
         | 
| 
      
 185 
     | 
    
         
            +
            						child = self.start(name, &block)
         
     | 
| 
       178 
186 
     | 
    
         
             
            						state = insert(key, child)
         
     | 
| 
       179 
187 
     | 
    
         | 
| 
      
 188 
     | 
    
         
            +
            						Console.debug(self, "Started child.", child: child, spawn: {key: key, restart: restart, health_check_timeout: health_check_timeout}, statistics: @statistics)
         
     | 
| 
      
 189 
     | 
    
         
            +
            						
         
     | 
| 
       180 
190 
     | 
    
         
             
            						# 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.
         
     | 
| 
       181 
191 
     | 
    
         
             
            						if health_check_timeout
         
     | 
| 
       182 
192 
     | 
    
         
             
            							age_clock = state[:age] = Clock.start
         
     | 
| 
       183 
193 
     | 
    
         
             
            						end
         
     | 
| 
       184 
194 
     | 
    
         | 
| 
      
 195 
     | 
    
         
            +
            						status = nil
         
     | 
| 
      
 196 
     | 
    
         
            +
            						
         
     | 
| 
       185 
197 
     | 
    
         
             
            						begin
         
     | 
| 
       186 
198 
     | 
    
         
             
            							status = @group.wait_for(child) do |message|
         
     | 
| 
       187 
199 
     | 
    
         
             
            								case message
         
     | 
| 
         @@ -194,15 +206,17 @@ module Async 
     | 
|
| 
       194 
206 
     | 
    
         
             
            									age_clock&.reset!
         
     | 
| 
       195 
207 
     | 
    
         
             
            								end
         
     | 
| 
       196 
208 
     | 
    
         
             
            							end
         
     | 
| 
      
 209 
     | 
    
         
            +
            						rescue => error
         
     | 
| 
      
 210 
     | 
    
         
            +
            							Console.error(self, "Error during child process management!", exception: error, running: @running)
         
     | 
| 
       197 
211 
     | 
    
         
             
            						ensure
         
     | 
| 
       198 
212 
     | 
    
         
             
            							delete(key, child)
         
     | 
| 
       199 
213 
     | 
    
         
             
            						end
         
     | 
| 
       200 
214 
     | 
    
         | 
| 
       201 
     | 
    
         
            -
            						if status 
     | 
| 
       202 
     | 
    
         
            -
            							Console.debug(self 
     | 
| 
      
 215 
     | 
    
         
            +
            						if status&.success?
         
     | 
| 
      
 216 
     | 
    
         
            +
            							Console.debug(self, "Child exited successfully.", status: status, running: @running)
         
     | 
| 
       203 
217 
     | 
    
         
             
            						else
         
     | 
| 
       204 
218 
     | 
    
         
             
            							@statistics.failure!
         
     | 
| 
       205 
     | 
    
         
            -
            							Console.error(self, status: status)
         
     | 
| 
      
 219 
     | 
    
         
            +
            							Console.error(self, "Child exited with error!", status: status, running: @running)
         
     | 
| 
       206 
220 
     | 
    
         
             
            						end
         
     | 
| 
       207 
221 
     | 
    
         | 
| 
       208 
222 
     | 
    
         
             
            						if restart
         
     | 
| 
         @@ -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 
     | 
    
         
            -
            				 
     | 
| 
      
 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 
     | 
    
         
            -
            				 
     | 
| 
      
 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 
     | 
    
         
            -
            				 
     | 
| 
      
 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 
     | 
    
         
            -
            				 
     | 
| 
      
 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  
     | 
| 
       235 
     | 
    
         
            -
            				 
     | 
| 
      
 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:
         
     | 
| 
         @@ -63,9 +63,9 @@ module Async 
     | 
|
| 
       63 
63 
     | 
    
         
             
            				# Formats the message using JSON and sends it to the parent controller.
         
     | 
| 
       64 
64 
     | 
    
         
             
            				# This is suitable for use with {Channel}.
         
     | 
| 
       65 
65 
     | 
    
         
             
            				def send(**message)
         
     | 
| 
       66 
     | 
    
         
            -
            					data = ::JSON.dump(message)
         
     | 
| 
      
 66 
     | 
    
         
            +
            					data = ::JSON.dump(message) << "\n"
         
     | 
| 
       67 
67 
     | 
    
         | 
| 
       68 
     | 
    
         
            -
            					@io. 
     | 
| 
      
 68 
     | 
    
         
            +
            					@io.write(data)
         
     | 
| 
       69 
69 
     | 
    
         
             
            					@io.flush
         
     | 
| 
       70 
70 
     | 
    
         
             
            				end
         
     | 
| 
       71 
71 
     | 
    
         | 
| 
         @@ -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
         
     | 
    
        data/license.md
    CHANGED
    
    | 
         @@ -5,6 +5,7 @@ Copyright, 2019, by Yuji Yaginuma. 
     | 
|
| 
       5 
5 
     | 
    
         
             
            Copyright, 2020, by Olle Jonsson.  
         
     | 
| 
       6 
6 
     | 
    
         
             
            Copyright, 2020, by Juan Antonio Martín Lucas.  
         
     | 
| 
       7 
7 
     | 
    
         
             
            Copyright, 2022, by Anton Sozontov.  
         
     | 
| 
      
 8 
     | 
    
         
            +
            Copyright, 2025, by Marc-André Cournoyer.  
         
     | 
| 
       8 
9 
     | 
    
         | 
| 
       9 
10 
     | 
    
         
             
            Permission is hereby granted, free of charge, to any person obtaining a copy
         
     | 
| 
       10 
11 
     | 
    
         
             
            of this software and associated documentation files (the "Software"), to deal
         
     | 
    
        data/readme.md
    CHANGED
    
    | 
         @@ -26,6 +26,23 @@ 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.5
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
              - Make the child handling more robust in the face of exceptions.
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
            ### v0.27.4
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
              - Fix race condition where `wait_for` could modify `@running` while it was being iterated over (`each_value`) during health checks.
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
            ### v0.27.3
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
              - Add log for starting child, including container statistics.
         
     | 
| 
      
 40 
     | 
    
         
            +
              - Don't try to (log) "terminate 0 child processes" if there are none.
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
            ### v0.27.2
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
              - More logging, especially around failure cases.
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
       29 
46 
     | 
    
         
             
            ### v0.27.1
         
     | 
| 
       30 
47 
     | 
    
         | 
| 
       31 
48 
     | 
    
         
             
              - Log caller and timeout when waiting on a child instance to exit, if it blocks.
         
     | 
| 
         @@ -51,21 +68,6 @@ Please see the [project releases](https://socketry.github.io/async-container/rel 
     | 
|
| 
       51 
68 
     | 
    
         | 
| 
       52 
69 
     | 
    
         
             
              - [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.)
         
     | 
| 
       53 
70 
     | 
    
         | 
| 
       54 
     | 
    
         
            -
            ### v0.21.0
         
     | 
| 
       55 
     | 
    
         
            -
             
     | 
| 
       56 
     | 
    
         
            -
              - 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.
         
     | 
| 
       57 
     | 
    
         
            -
             
     | 
| 
       58 
     | 
    
         
            -
            ### v0.20.1
         
     | 
| 
       59 
     | 
    
         
            -
             
     | 
| 
       60 
     | 
    
         
            -
              - Fix compatibility between <code class="language-ruby">Async::Container::Hybrid</code> and the health check.
         
     | 
| 
       61 
     | 
    
         
            -
              - <code class="language-ruby">Async::Container::Generic\#initialize</code> passes unused arguments through to <code class="language-ruby">Async::Container::Group</code>.
         
     | 
| 
       62 
     | 
    
         
            -
             
     | 
| 
       63 
     | 
    
         
            -
            ### v0.20.0
         
     | 
| 
       64 
     | 
    
         
            -
             
     | 
| 
       65 
     | 
    
         
            -
              - Improve container signal handling reliability by using `Thread.handle_interrupt` except at known safe points.
         
     | 
| 
       66 
     | 
    
         
            -
              - Improved logging when child process fails and container startup.
         
     | 
| 
       67 
     | 
    
         
            -
              - [Add `health_check_timeout` for detecting hung processes.](https://socketry.github.io/async-container/releases/index#add-health_check_timeout-for-detecting-hung-processes.)
         
     | 
| 
       68 
     | 
    
         
            -
             
     | 
| 
       69 
71 
     | 
    
         
             
            ## Contributing
         
     | 
| 
       70 
72 
     | 
    
         | 
| 
       71 
73 
     | 
    
         
             
            We welcome contributions to this project.
         
     | 
    
        data/releases.md
    CHANGED
    
    | 
         @@ -1,5 +1,22 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # Releases
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
      
 3 
     | 
    
         
            +
            ## v0.27.5
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
              - Make the child handling more robust in the face of exceptions.
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            ## v0.27.4
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              - Fix race condition where `wait_for` could modify `@running` while it was being iterated over (`each_value`) during health checks.
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            ## v0.27.3
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              - Add log for starting child, including container statistics.
         
     | 
| 
      
 14 
     | 
    
         
            +
              - Don't try to (log) "terminate 0 child processes" if there are none.
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            ## v0.27.2
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
              - More logging, especially around failure cases.
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
       3 
20 
     | 
    
         
             
            ## v0.27.1
         
     | 
| 
       4 
21 
     | 
    
         | 
| 
       5 
22 
     | 
    
         
             
              - Log caller and timeout when waiting on a child instance to exit, if it blocks.
         
     | 
    
        data.tar.gz.sig
    CHANGED
    
    | 
         Binary file 
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,13 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: async-container
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0.27. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.27.7
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Samuel Williams
         
     | 
| 
       8 
8 
     | 
    
         
             
            - Olle Jonsson
         
     | 
| 
       9 
9 
     | 
    
         
             
            - Anton Sozontov
         
     | 
| 
       10 
10 
     | 
    
         
             
            - Juan Antonio Martín Lucas
         
     | 
| 
      
 11 
     | 
    
         
            +
            - Marc-André Cournoyer
         
     | 
| 
       11 
12 
     | 
    
         
             
            - Yuji Yaginuma
         
     | 
| 
       12 
13 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       13 
14 
     | 
    
         
             
            cert_chain:
         
     | 
| 
         @@ -105,7 +106,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement 
     | 
|
| 
       105 
106 
     | 
    
         
             
                - !ruby/object:Gem::Version
         
     | 
| 
       106 
107 
     | 
    
         
             
                  version: '0'
         
     | 
| 
       107 
108 
     | 
    
         
             
            requirements: []
         
     | 
| 
       108 
     | 
    
         
            -
            rubygems_version: 3. 
     | 
| 
      
 109 
     | 
    
         
            +
            rubygems_version: 3.7.2
         
     | 
| 
       109 
110 
     | 
    
         
             
            specification_version: 4
         
     | 
| 
       110 
111 
     | 
    
         
             
            summary: Abstract container-based parallelism using threads and processes where appropriate.
         
     | 
| 
       111 
112 
     | 
    
         
             
            test_files: []
         
     | 
    
        metadata.gz.sig
    CHANGED
    
    | 
         Binary file 
     |