Class: Harnex::Adapters::CodexAppServer::JsonRpcClient
- Inherits:
-
Object
- Object
- Harnex::Adapters::CodexAppServer::JsonRpcClient
- Defined in:
- lib/harnex/adapters/codex_appserver.rb
Overview
Minimal JSON-RPC 2.0 client. One JSON object per line. Responses keyed by id; everything else is a notification.
Instance Attribute Summary collapse
-
#pid ⇒ Object
readonly
Returns the value of attribute pid.
Instance Method Summary collapse
- #close ⇒ Object
-
#initialize(read_io:, write_io:, pid: nil) ⇒ JsonRpcClient
constructor
A new instance of JsonRpcClient.
- #notify(method, params = {}) ⇒ Object
- #on_disconnect(&block) ⇒ Object
- #on_notification(&block) ⇒ Object
-
#on_request(&block) ⇒ Object
Handler for server-initiated requests (id + method).
- #request(method, params = {}) ⇒ Object
- #start ⇒ Object
- #terminate_process(term_grace_seconds:, kill_grace_seconds:) ⇒ Object
Constructor Details
#initialize(read_io:, write_io:, pid: nil) ⇒ JsonRpcClient
Returns a new instance of JsonRpcClient.
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 |
# File 'lib/harnex/adapters/codex_appserver.rb', line 322 def initialize(read_io:, write_io:, pid: nil) @read_io = read_io @write_io = write_io @pid = pid @next_id = 1 @pending = {} @id_mutex = Mutex.new @write_mutex = Mutex.new @notification_handler = nil @request_handler = nil @disconnect_handler = nil @disconnect_signaled = false @closed = false @reader_thread = nil end |
Instance Attribute Details
#pid ⇒ Object (readonly)
Returns the value of attribute pid.
320 321 322 |
# File 'lib/harnex/adapters/codex_appserver.rb', line 320 def pid @pid end |
Instance Method Details
#close ⇒ Object
381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 |
# File 'lib/harnex/adapters/codex_appserver.rb', line 381 def close return if @closed @closed = true @id_mutex.synchronize do @pending.each_value { |q| q.push(StandardError.new("codex_appserver client closed")) } @pending.clear end begin @write_io.close unless @write_io.closed? rescue IOError nil end if @pid && process_alive?(@pid) sleep 0.05 begin Process.kill("TERM", @pid) rescue Errno::ESRCH nil end end @reader_thread&.join(2) end |
#notify(method, params = {}) ⇒ Object
375 376 377 378 379 |
# File 'lib/harnex/adapters/codex_appserver.rb', line 375 def notify(method, params = {}) return if @closed write_line({ jsonrpc: "2.0", method: method, params: params }) end |
#on_disconnect(&block) ⇒ Object
349 350 351 |
# File 'lib/harnex/adapters/codex_appserver.rb', line 349 def on_disconnect(&block) @disconnect_handler = block end |
#on_notification(&block) ⇒ Object
338 339 340 |
# File 'lib/harnex/adapters/codex_appserver.rb', line 338 def on_notification(&block) @notification_handler = block end |
#on_request(&block) ⇒ Object
Handler for server-initiated requests (id + method). The block receives (method, params) and returns the response body for the JSON-RPC ‘result` field, or nil to reject with -32601.
345 346 347 |
# File 'lib/harnex/adapters/codex_appserver.rb', line 345 def on_request(&block) @request_handler = block end |
#request(method, params = {}) ⇒ Object
357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 |
# File 'lib/harnex/adapters/codex_appserver.rb', line 357 def request(method, params = {}) raise "codex_appserver client is closed" if @closed queue = Queue.new id = @id_mutex.synchronize do assigned = @next_id @next_id += 1 @pending[assigned] = queue assigned end write_line({ jsonrpc: "2.0", id: id, method: method, params: params }) result = queue.pop raise result if result.is_a?(Exception) result end |
#start ⇒ Object
353 354 355 |
# File 'lib/harnex/adapters/codex_appserver.rb', line 353 def start @reader_thread = Thread.new { read_loop } end |
#terminate_process(term_grace_seconds:, kill_grace_seconds:) ⇒ Object
409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 |
# File 'lib/harnex/adapters/codex_appserver.rb', line 409 def terminate_process(term_grace_seconds:, kill_grace_seconds:) return false unless @pid begin Process.kill("TERM", @pid) rescue Errno::ESRCH return true end return true if wait_for_process_exit(@pid, term_grace_seconds) begin Process.kill("KILL", @pid) rescue Errno::ESRCH return true end wait_for_process_exit(@pid, kill_grace_seconds) end |