Skip to content

Commit 2e9234b

Browse files
Remove incomplete reload/keyed reconciliation. (#73)
1 parent 03b1fa4 commit 2e9234b

5 files changed

Lines changed: 18 additions & 184 deletions

File tree

lib/async/container/controller.rb

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -194,32 +194,6 @@ def restart
194194
end
195195
end
196196

197-
# Reload the existing container. Children instances will be reloaded using `SIGHUP`.
198-
def reload
199-
@notify&.reloading!
200-
201-
Console.info(self){"Reloading container: #{@container}..."}
202-
203-
begin
204-
self.setup(@container)
205-
rescue
206-
raise SetupError, container
207-
end
208-
209-
# Wait for all child processes to enter the ready state.
210-
Console.info(self, "Waiting for startup...")
211-
@container.wait_until_ready
212-
Console.info(self, "Finished startup.")
213-
214-
if @container.failed?
215-
@notify.error!("Container failed to reload!")
216-
217-
raise SetupError, @container
218-
else
219-
@notify&.ready!(size: @container.size, status: "Running with #{@container.size} children.")
220-
end
221-
end
222-
223197
# Enter the controller run loop, trapping `SIGINT` and `SIGTERM`.
224198
def run
225199
@notify&.status!("Initializing controller...")

lib/async/container/generic.rb

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
require "async/clock"
99

1010
require_relative "group"
11-
require_relative "keyed"
1211
require_relative "statistics"
1312
require_relative "policy"
1413

@@ -79,7 +78,7 @@ def to_s
7978
# Look up a child process by key.
8079
# A key could be a symbol, a file path, or something else which the child instance represents.
8180
def [] key
82-
@keyed[key]&.value
81+
@keyed[key]
8382
end
8483

8584
# Statistics relating to the behavior of children instances.
@@ -210,13 +209,13 @@ def stop(timeout = true)
210209
# Spawn a child instance into the container.
211210
# @parameter name [String] The name of the child instance.
212211
# @parameter restart [Boolean] Whether to restart the child instance if it fails.
213-
# @parameter key [Symbol] A key used for reloading child instances.
212+
# @parameter key [Symbol] An optional key used to look up (via {[]}) and reuse the child instance.
214213
# @parameter health_check_timeout [Numeric | Nil] The maximum time a child instance can run without updating its state, before it is terminated as unhealthy.
215214
# @parameter startup_timeout [Numeric | Nil] The maximum time a child instance can run without becoming ready, before it is terminated as unhealthy.
216215
def spawn(name: nil, restart: false, key: nil, health_check_timeout: nil, startup_timeout: nil, &block)
217216
name ||= UNNAMED
218217

219-
if mark?(key)
218+
if reuse?(key)
220219
Console.debug(self, "Reusing existing child.", child: {key: key, name: name})
221220
return false
222221
end
@@ -326,32 +325,22 @@ def async(**options, &block)
326325
end
327326
end
328327

329-
# Reload the container's keyed instances.
328+
# Re-run the given block against the container.
329+
#
330+
# Existing keyed children are reused (see {spawn}), so re-running setup will not
331+
# duplicate them. Reconciliation of children whose keys are no longer configured
332+
# (i.e. stopping obsolete children) is not currently supported and will be revisited.
330333
def reload
331-
@keyed.each_value(&:clear!)
332-
333334
yield
334-
335-
dirty = false
336-
337-
@keyed.delete_if do |key, value|
338-
value.stop? && (dirty = true)
339-
end
340-
341-
return dirty
342335
end
343336

344-
# Mark the container's keyed instance which ensures that it won't be discarded.
345-
def mark?(key)
337+
# Whether a child instance already exists for the given key, in which case it can be reused rather than spawned again.
338+
def reuse?(key)
346339
if key
347-
if value = @keyed[key]
348-
value.mark!
349-
350-
return true
351-
end
340+
@keyed.key?(key)
341+
else
342+
false
352343
end
353-
354-
return false
355344
end
356345

357346
# Whether a child instance exists for the given key.
@@ -366,7 +355,7 @@ def key?(key)
366355
# Register the child (value) as running.
367356
def insert(key, child)
368357
if key
369-
@keyed[key] = Keyed.new(key, child)
358+
@keyed[key] = child
370359
end
371360

372361
state = {}

lib/async/container/keyed.rb

Lines changed: 0 additions & 53 deletions
This file was deleted.

releases.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Releases
22

3+
## Unreleased
4+
5+
- **Removed** `Controller#reload` and the container-level keyed reconciliation (`Keyed`, mark/sweep, and stopping of obsolete keyed children on reload). This functionality was incomplete and not correctly wired, and will be revisited with a simpler design. Keyed `spawn(key:)` registration and `container[key]` lookup are retained, and `Container#reload` now simply re-runs the given block (reusing existing keyed children).
6+
37
## v0.37.0
48

59
- Rename `ASYNC_CONTAINER_GRACEFUL_TIMEOUT` to `ASYNC_CONTAINER_GRACEFUL_STOP` and apply it at the controller level as `GRACEFUL_STOP`. `Group#stop` now only applies the shutdown policy it is given.

test/async/container/controller.rb

Lines changed: 0 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -44,46 +44,6 @@ def read_graceful_stop(value)
4444
end
4545
end
4646

47-
with "#reload" do
48-
it "can reuse keyed child" do
49-
input, output = IO.pipe
50-
51-
controller.instance_variable_set(:@output, output)
52-
53-
def controller.setup(container)
54-
container.spawn(key: "test") do |instance|
55-
instance.ready!
56-
57-
@output.write(".")
58-
@output.flush
59-
60-
sleep(0.2)
61-
end
62-
63-
container.spawn do |instance|
64-
instance.ready!
65-
66-
sleep(0.1)
67-
68-
@output.write(",")
69-
@output.flush
70-
end
71-
end
72-
73-
controller.start
74-
75-
expect(controller.state_string).to be == "running"
76-
77-
expect(input.read(2)).to be == ".,"
78-
79-
controller.reload
80-
81-
expect(input.read(1)).to be == ","
82-
83-
controller.wait
84-
end
85-
end
86-
8747
with "#restart" do
8848
it "replaces the running container with a new one" do
8949
def controller.setup(container)
@@ -127,46 +87,6 @@ def controller.setup(container)
12787
end
12888
end
12989

130-
with "notify" do
131-
before do
132-
@notify_server = Async::Container::Notify::Server.open
133-
@notify_client = Async::Container::Notify::Socket.new(@notify_server.path)
134-
@notify = @notify_server.bind
135-
end
136-
137-
after do
138-
@notify&.close
139-
end
140-
141-
let(:controller) {subject.new(notify: @notify_client)}
142-
143-
it "sends status with ready notification on reload" do
144-
def controller.setup(container)
145-
container.spawn do |instance|
146-
instance.ready!
147-
sleep(0.1)
148-
end
149-
end
150-
151-
controller.start
152-
153-
# Drain the start ready message:
154-
@notify.wait_until_ready
155-
156-
controller.reload
157-
158-
# Capture messages until we find the reload ready notification:
159-
while message = @notify.receive
160-
break if message[:ready]
161-
end
162-
163-
expect(message).to have_keys(
164-
ready: be == true,
165-
status: be =~ /Running/
166-
)
167-
end
168-
end
169-
17090
with "#start" do
17191
it "can start up a container" do
17292
expect(controller).to receive(:setup)

0 commit comments

Comments
 (0)