Skip to content

Commit 77ed4ed

Browse files
committed
feat: finalize integration of manager's available? in update_deployment_state
1 parent 7be40bc commit 77ed4ed

File tree

3 files changed

+118
-2
lines changed

3 files changed

+118
-2
lines changed

lib/syskit/runtime/update_deployment_states.rb

+12
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,24 @@ def self.update_deployment_states(plan)
1010
# #cleanup_dead_connections, thus avoiding to disconnect connections
1111
# between already-dead processes
1212

13+
poll_managers
1314
handle_dead_deployments(plan)
1415
trigger_ready_deployments(plan)
1516
end
1617

18+
def self.poll_managers
19+
server_config = Syskit.conf.each_process_server_config.to_a
20+
server_config.each do |config|
21+
config.client.poll if config.client.respond_to?(:poll)
22+
end
23+
end
24+
1725
def self.handle_dead_deployments(plan)
1826
all_dead_deployments = Set.new
1927
server_config = Syskit.conf.each_process_server_config.to_a
2028
server_config.each do |config|
29+
next unless config.available?
30+
2131
begin
2232
dead_deployments = config.client.wait_termination
2333
rescue ::Exception => e
@@ -42,6 +52,8 @@ def self.trigger_ready_deployments(plan)
4252
not_ready_deployments = find_all_not_ready_deployments(plan)
4353
not_ready_deployments.each do |process_server_name, deployments|
4454
server_config = Syskit.conf.process_server_config_for(process_server_name)
55+
next unless server_config.available?
56+
4557
wait_result = server_config.client.wait_running(
4658
*deployments.map { |d| d.arguments[:process_name] }
4759
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# frozen_string_literal: true
2+
3+
$stdout.sync = true
4+
require "roby/schedulers/temporal"
5+
Roby.scheduler = Roby::Schedulers::Temporal.new
6+
7+
TOKEN = ENV.fetch("SYSKIT_TEST_MISSING_PROCESS_SERVER_TOKEN", nil)
8+
PROCESS_SERVER_PORT = Integer(ENV.fetch("SYSKIT_TEST_MISSING_PROCESS_SERVER_PORT", nil))
9+
10+
Syskit.conf.remote_process_managers_initial_connection_timeout = 1
11+
Syskit.conf.remote_process_managers_connection_timeout = 1
12+
Syskit.conf.remote_process_managers_response_timeout = 1
13+
Syskit.conf.remote_process_managers_accept_failed_connections = true
14+
Syskit.conf.register_remote_manager(
15+
"test", "localhost", port: PROCESS_SERVER_PORT
16+
)
17+
test_remote_manager = Syskit.conf.process_server_config_for("test")
18+
if test_remote_manager.available?
19+
puts "#{TOKEN} - failed - process manager available on start"
20+
Roby.app.quit
21+
end
22+
23+
using_task_library "orogen_syskit_tests"
24+
25+
deadline = nil
26+
spawned = false
27+
Robot.controller do
28+
Roby.execution_engine.each_cycle do
29+
if test_remote_manager.available? && !spawned
30+
spawned = true
31+
task_m =
32+
OroGen.orogen_syskit_tests.Empty
33+
.deployed_as("#{Process.pid}_missing_empty", on: "test")
34+
task = Roby.plan.add_mission_task(task_m)
35+
task.start_event.on do |_event|
36+
puts "#{TOKEN} - success"
37+
Roby.app.quit
38+
end
39+
end
40+
end
41+
42+
deadline ||= Time.now + 10
43+
if Time.now > deadline
44+
puts "#{TOKEN} - failed"
45+
Roby.app.quit
46+
end
47+
end

test/runtime/test_update_deployment_state.rb

+59-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# frozen_string_literal: true
22

33
require "syskit/test/self"
4+
require "syskit/test/roby_app_helpers"
5+
require "syskit/process_managers/remote/server"
46

57
module Syskit
68
module Runtime
@@ -38,11 +40,50 @@ def disconnect; end
3840
end
3941

4042
describe ".update_deployment_states" do
43+
describe "system behaviour with remote manager availability" do
44+
include Syskit::Test::RobyAppHelpers
45+
46+
after do
47+
if @remote_process_server_pid
48+
remote_process_server_quit(@remote_process_server_pid)
49+
end
50+
end
51+
52+
def roby_app_fixture_path
53+
File.expand_path("fixtures", __dir__)
54+
end
55+
56+
it "gracefully handles a process manager that appears after start" do
57+
dir = roby_app_setup_single_script(
58+
"missing_process_manager_on_start.rb"
59+
)
60+
port = roby_app_allocate_port
61+
token = SecureRandom.base64(10)
62+
env = {
63+
"SYSKIT_TEST_MISSING_PROCESS_SERVER_PORT" => port.to_s,
64+
"SYSKIT_TEST_MISSING_PROCESS_SERVER_TOKEN" => token
65+
}
66+
67+
pid, = roby_app_start(
68+
"run", "-c", "scripts/missing_process_manager_on_start.rb",
69+
capture_output: true, chdir: dir, env: env
70+
)
71+
sleep 5
72+
73+
@remote_process_server_pid = remote_process_server_spawn(port)
74+
assert_roby_app_exits(pid)
75+
output = roby_app_captured_output(pid)
76+
refute_match(/#{token} - failed/, output[:out])
77+
assert_match(/#{token} - success/, output[:out])
78+
end
79+
end
80+
4181
describe "#handle_dead_deployments" do
4282
it "calls #dead! on the dead deployments" do
4383
client = flexmock
44-
flexmock(Syskit.conf).should_receive(:each_process_server_config)
45-
.and_return([flexmock(client: client)])
84+
flexmock(Syskit.conf)
85+
.should_receive(:each_process_server_config)
86+
.and_return([flexmock(client: client, available?: true)])
4687
client.should_receive(:wait_termination)
4788
.and_return([[p = flexmock, s = flexmock]])
4889
flexmock(Deployment).should_receive(:deployment_by_process).with(p)
@@ -185,6 +226,22 @@ def mocked_deployment(
185226
mock
186227
end
187228
end
229+
230+
def remote_process_server_spawn(port)
231+
log_dir = make_tmpdir
232+
pid = spawn(
233+
"syskit", "process_server",
234+
"--log-dir=#{log_dir}", "--port=#{port}",
235+
chdir: log_dir, out: "/dev/null", err: "/dev/null"
236+
)
237+
register_pid(pid)
238+
pid
239+
end
240+
241+
def remote_process_server_quit(pid)
242+
Process.kill "INT", pid
243+
assert_process_exits(pid)
244+
end
188245
end
189246
end
190247
end

0 commit comments

Comments
 (0)