Class: RailsConsole::Broker
- Inherits:
-
Object
- Object
- RailsConsole::Broker
- Includes:
- Logging
- Defined in:
- lib/rails-console/broker.rb
Overview
Owns the single PTY console session per container. Puma workers reach it over a local Unix socket, so any worker can serve the browser's WebSocket and hit the same session.
Constant Summary collapse
- REDRAW =
Ctrl-L: tells the console to redraw its prompt so a just-attached client sees it.
"\f"- RELOAD_MARKER =
Sent to clients when the session is replaced (safe!/unsafe!), so the frontend resets the screen and shows the booting spinner again. NUL-delimited so it never collides with real terminal output.
"\x00CONSOLE_RELOAD\x00"- SAFE_MARKER =
The console prints this to ask for sandbox (safe) mode. NUL bytes never appear in terminal output, so it can't be triggered by accident.
"\x00CONSOLE_SAFE_REQUEST\x00"- SPAWN_TIMEOUT =
Seconds to wait for a freshly spawned broker to start listening.
15- UNSAFE_MARKER =
The console prints this to ask for write (unsafe) mode. NUL bytes never appear in terminal output, so it can't be triggered by accident.
"\x00CONSOLE_UNSAFE_REQUEST\x00"
Constants included from Logging
Instance Attribute Summary collapse
-
#console_session ⇒ Object
readonly
Returns the value of attribute console_session.
-
#owner_label ⇒ Object
readonly
Returns the value of attribute owner_label.
Class Method Summary collapse
-
.boot(socket_path: nil) ⇒ Object
rubocop:disable Naming/PredicateMethod.
- .running?(socket_path: nil) ⇒ Boolean
Instance Method Summary collapse
-
#initialize(safe_command: nil, socket_path: nil, unsafe_command: nil) ⇒ Broker
constructor
A new instance of Broker.
- #run ⇒ Object
- #shutdown ⇒ Object
Methods included from Logging
Constructor Details
#initialize(safe_command: nil, socket_path: nil, unsafe_command: nil) ⇒ Broker
Returns a new instance of Broker.
62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/rails-console/broker.rb', line 62 def initialize(safe_command: nil, socket_path: nil, unsafe_command: nil) @clients = [] @console_session = nil @idle_timer = nil @mutex = Mutex.new @owner_label = nil @pty_session = nil @safe_command = safe_command @server = nil @shutting_down = false @socket_path = socket_path || RailsConsole.socket_path @unsafe_command = unsafe_command end |
Instance Attribute Details
#console_session ⇒ Object (readonly)
Returns the value of attribute console_session.
32 33 34 |
# File 'lib/rails-console/broker.rb', line 32 def console_session @console_session end |
#owner_label ⇒ Object (readonly)
Returns the value of attribute owner_label.
32 33 34 |
# File 'lib/rails-console/broker.rb', line 32 def owner_label @owner_label end |
Class Method Details
.boot(socket_path: nil) ⇒ Object
rubocop:disable Naming/PredicateMethod
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/rails-console/broker.rb', line 34 def self.boot(socket_path: nil) # rubocop:disable Naming/PredicateMethod socket_path ||= RailsConsole.socket_path return true if running?(socket_path:) broker_bin = Gem.bin_path('rails-console', 'rails_console') Process.spawn('bundle', 'exec', broker_bin, chdir: Rails.root.to_s) SPAWN_TIMEOUT.times do return true if running?(socket_path:) sleep(1) end false end |
.running?(socket_path: nil) ⇒ Boolean
52 53 54 55 56 57 58 59 60 |
# File 'lib/rails-console/broker.rb', line 52 def self.running?(socket_path: nil) socket_path ||= RailsConsole.socket_path UNIXSocket.new(socket_path.to_s).close true rescue Errno::ENOENT, Errno::ECONNREFUSED false end |
Instance Method Details
#run ⇒ Object
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/rails-console/broker.rb', line 76 def run return log("Already listening on #{@socket_path}, aborting.") if already_running? prepare_socket_path @server = UNIXServer.new(@socket_path) log("Listening on #{@socket_path}") loop { Thread.new(@server.accept) { |client| handle_client(client) } } rescue IOError nil ensure @server&.close end |
#shutdown ⇒ Object
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/rails-console/broker.rb', line 92 def shutdown @shutting_down = true @mutex.synchronize do @idle_timer&.kill @idle_timer = nil @clients.each do |item| item.close rescue IOError nil end @clients.clear @pty_session&.kill! end @server&.close @server = nil end |