Skip to content

Commit 170c3a1

Browse files
committed
Improved RPC mechanism.
1 parent 9b75597 commit 170c3a1

File tree

14 files changed

+356
-220
lines changed

14 files changed

+356
-220
lines changed

async-container-supervisor.gemspec

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ Gem::Specification.new do |spec|
2424

2525
spec.required_ruby_version = ">= 3.1"
2626

27-
spec.add_dependency "async-container"
27+
spec.add_dependency "async-container", "~> 0.22"
2828
spec.add_dependency "async-service"
2929
spec.add_dependency "io-stream"
30-
spec.add_dependency "memory-leak", "~> 0.2"
30+
spec.add_dependency "memory-leak", "~> 0.3"
3131
end

example/simple/simple.rb

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,23 @@ class SleepService < Async::Service::Generic
66
def setup(container)
77
super
88

9-
container.run(count: 1, restart: true, health_check_timeout: 2) do |instance|
9+
container.run(name: self.class.name, count: 4, restart: true, health_check_timeout: 2) do |instance|
1010
Async do
1111
client = Async::Container::Supervisor::Client.new(instance, @evaluator.supervisor_endpoint)
1212
client.run
1313

14+
start_time = Time.now
15+
1416
instance.ready!
1517

1618
chunks = []
1719
while true
18-
Console.info(self, "Allocating memory...")
19-
# Allocate 10MB of memory every second:
20-
chunks << " " * 1024 * 1024
21-
sleep 0.1
20+
chunks << " " * 1024 * 1024 * rand(10)
21+
sleep 1
2222
instance.ready!
23+
24+
uptime = Time.now - start_time
25+
instance.name = "Sleeping for #{uptime.to_i} seconds..."
2326
end
2427
ensure
2528
Console.info(self, "Exiting...")
@@ -38,6 +41,6 @@ def setup(container)
3841
include Async::Container::Supervisor::Environment
3942

4043
monitors do
41-
[Async::Container::Supervisor::Monitor::MemoryMonitor.new(interval: 1, limit: 1024 * 1024 * 100)]
44+
[Async::Container::Supervisor::MemoryMonitor.new(interval: 1, limit: 1024 * 1024 * 100)]
4245
end
4346
end

gems.locked

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,11 @@
1-
PATH
2-
remote: ../async-container
3-
specs:
4-
async-container (0.21.0)
5-
async (~> 2.22)
6-
71
PATH
82
remote: .
93
specs:
104
async-container-supervisor (0.0.0)
11-
async-container
5+
async-container (~> 0.22)
126
async-service
137
io-stream
14-
memory-leak (~> 0.2)
8+
memory-leak (~> 0.3)
159

1610
GEM
1711
remote: https://rubygems.org/
@@ -23,6 +17,8 @@ GEM
2317
io-event (~> 1.9)
2418
metrics (~> 0.12)
2519
traces (~> 0.15)
20+
async-container (0.22.0)
21+
async (~> 2.22)
2622
async-http (0.87.0)
2723
async (>= 2.10.2)
2824
async-pool (~> 0.9)
@@ -104,7 +100,7 @@ GEM
104100
net-smtp
105101
mapping (1.1.1)
106102
markly (0.12.1)
107-
memory-leak (0.2.0)
103+
memory-leak (0.4.0)
108104
metrics (0.12.1)
109105
mime-types (3.6.0)
110106
logger
@@ -148,7 +144,7 @@ GEM
148144
variant
149145
rainbow (3.1.1)
150146
regexp_parser (2.10.0)
151-
rubocop (1.72.2)
147+
rubocop (1.73.0)
152148
json (~> 2.3)
153149
language_server-protocol (~> 3.17.0.2)
154150
lint_roller (~> 1.1.0)
@@ -206,7 +202,6 @@ PLATFORMS
206202
ruby
207203

208204
DEPENDENCIES
209-
async-container!
210205
async-container-supervisor!
211206
bake-gem
212207
bake-modernize

gems.rb

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77

88
gemspec
99

10-
gem "async-container", path: "../async-container"
11-
1210
group :maintenance, optional: true do
1311
gem "bake-gem"
1412
gem "bake-modernize"

lib/async/container/supervisor.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77

88
require_relative "supervisor/server"
99
require_relative "supervisor/client"
10-
require_relative "supervisor/monitor"
10+
11+
require_relative "supervisor/memory_monitor"
1112

1213
require_relative "supervisor/environment"
1314
require_relative "supervisor/service"

lib/async/container/supervisor/client.rb

Lines changed: 67 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# Copyright, 2025, by Samuel Williams.
55

66
require "io/stream"
7-
require_relative "wrapper"
7+
require_relative "connection"
88

99
module Async
1010
module Container
@@ -19,47 +19,96 @@ def initialize(instance, endpoint = Supervisor.endpoint)
1919
@endpoint = endpoint
2020
end
2121

22+
def dispatch(call)
23+
method_name = "do_#{call.message[:do]}"
24+
self.public_send(method_name, call)
25+
end
26+
2227
def connect
23-
unless @wrapper
28+
unless @connection
2429
peer = @endpoint.connect
2530
stream = IO::Stream(peer)
26-
@wrapper = Wrapper.new(stream)
31+
@connection = Connection.new(stream, 0, instance: @instance)
2732

28-
@wrapper.write(action: "register", instance: @instance)
33+
# Register the instance with the server:
34+
Async do
35+
@connection.call(do: :register, state: @instance)
36+
end
2937
end
3038

31-
return @wrapper unless block_given?
39+
return @connection unless block_given?
3240

3341
begin
34-
yield @wrapper
42+
yield @connection
3543
ensure
36-
@wrapper.close
44+
@connection.close
3745
end
3846
end
3947

4048
def close
41-
if wrapper = @wrapper
42-
@wrapper = nil
43-
wrapper.close
49+
if connection = @connection
50+
@connection = nil
51+
connection.close
52+
end
53+
end
54+
55+
private def dump(call)
56+
if path = call[:path]
57+
File.open(path, "w") do |file|
58+
yield file
59+
end
60+
61+
call.finish(path: path)
62+
else
63+
buffer = StringIO.new
64+
yield buffer
65+
66+
call.finish(data: buffer.string)
67+
end
68+
end
69+
70+
def do_scheduler_dump(call)
71+
dump(call) do |file|
72+
Fiber.scheduler.print_hierarchy(file)
4473
end
4574
end
4675

47-
def do_memory_dump(wrapper, message)
48-
Console.info(self, "Memory dump:", message)
49-
path = message[:path]
76+
def do_memory_dump(call)
77+
require "objspace"
5078

51-
File.open(path, "w") do |file|
79+
dump(call) do |file|
5280
ObjectSpace.dump_all(output: file)
5381
end
5482
end
5583

84+
def do_thread_dump(call)
85+
dump(call) do |file|
86+
Thread.list.each do |thread|
87+
file.puts(thread.inspect)
88+
file.puts(thread.backtrace)
89+
end
90+
end
91+
end
92+
93+
def do_garbage_profile_start(connection, message)
94+
Console.info(self, "Garbage profile start:", message)
95+
GC::Profiler.enable
96+
end
97+
98+
def do_garbage_profile_stop(connection, message)
99+
Console.info(self, "Garbage profile stop:", message)
100+
GC::Profiler.disable
101+
102+
dump(connection, message) do |file|
103+
file.puts GC::Profiler.result
104+
end
105+
end
106+
56107
def run
57108
Async do |task|
58109
loop do
59-
Console.info(self, "Connecting to supervisor...")
60-
connect do |wrapper|
61-
Console.info(self, "Connected to supervisor.")
62-
wrapper.run(self)
110+
connect do |connection|
111+
connection.run(self)
63112
end
64113
rescue => error
65114
Console.error(self, "Unexpected error while running client!", exception: error)

0 commit comments

Comments
 (0)