Class: Kobako::RPC::Server
- Inherits:
-
Object
- Object
- Kobako::RPC::Server
- Defined in:
- lib/kobako/rpc/server.rb
Overview
Kobako::RPC::Server — per-Sandbox host-side RPC coordinator. Maintains the Namespace / Member registry, owns the HandleTable, and routes incoming Requests to the resolved Service object (SPEC.md B-07..B-21).
Public API:
server = Kobako::RPC::Server.new
namespace = server.define(:MyService) # => Kobako::RPC::Namespace
namespace.bind(:KV, kv_object) # => namespace (chainable)
server.to_preamble # => array for Frame 1
server.dispatch(request_bytes) # => msgpack bytes (delegated to Dispatcher)
Namespaces live at Kobako::RPC::Namespace (lib/kobako/rpc/namespace.rb). The opaque Handle allocator lives at Kobako::RPC::HandleTable (lib/kobako/rpc/handle_table.rb). Dispatch helpers live at Kobako::RPC::Dispatcher (lib/kobako/rpc/dispatcher.rb).
Instance Attribute Summary collapse
-
#handle_table ⇒ Object
readonly
Expose the
HandleTablefor tests and wire-layer Handle wrapping.
Instance Method Summary collapse
-
#bound?(target) ⇒ Boolean
Returns
truewhentarget(a “Namespace::Member” path) resolves to a bound member,falseotherwise. -
#define(name) ⇒ Object
Declare or retrieve the Namespace named
name(idempotent — SPEC.md B-10). -
#dispatch(request_bytes) ⇒ Object
Dispatch a single RPC request and return the encoded response bytes (SPEC.md B-12).
-
#empty? ⇒ Boolean
Returns
truewhen no namespaces have been declared,falseotherwise. -
#encoded_preamble ⇒ Object
Encode the preamble as msgpack bytes for stdin Frame 1 delivery (SPEC.md B-02).
-
#initialize(handle_table: HandleTable.new) ⇒ Server
constructor
Build a fresh Server.
-
#lookup(target) ⇒ Object
Resolve a
targetpath of the form “Namespace::Member” to the bound Host object. -
#namespaces ⇒ Object
Returns all declared
Kobako::RPC::Namespaceinstances as anArray. -
#reset_handles! ⇒ Object
Reset the HandleTable for a new
#runboundary. -
#seal! ⇒ Object
Mark the Server as sealed.
-
#sealed? ⇒ Boolean
Returns
truewhen #seal! has been called,falseotherwise. -
#size ⇒ Object
Returns the number of declared namespaces as an
Integer. -
#to_preamble ⇒ Object
Structured Frame 1 description.
Constructor Details
#initialize(handle_table: HandleTable.new) ⇒ Server
Build a fresh Server. handle_table is an internal seam that injects a pre-configured HandleTable; tests pass one whose next_id is pinned near MAX_ID to exercise the B-21 cap-exhaustion path without 2³¹ allocations. Production callers leave it at the default.
36 37 38 39 40 |
# File 'lib/kobako/rpc/server.rb', line 36 def initialize(handle_table: HandleTable.new) @namespaces = {} # : Hash[String, Kobako::RPC::Namespace] @handle_table = handle_table @sealed = false end |
Instance Attribute Details
#handle_table ⇒ Object (readonly)
Expose the HandleTable for tests and wire-layer Handle wrapping.
142 143 144 |
# File 'lib/kobako/rpc/server.rb', line 142 def handle_table @handle_table end |
Instance Method Details
#bound?(target) ⇒ Boolean
Returns true when target (a “Namespace::Member” path) resolves to a bound member, false otherwise.
74 75 76 77 |
# File 'lib/kobako/rpc/server.rb', line 74 def bound?(target) namespace, member_name, = parse_target(target) !namespace.nil? && !member_name.nil? && !namespace[member_name].nil? end |
#define(name) ⇒ Object
Declare or retrieve the Namespace named name (idempotent — SPEC.md B-10). name is a constant-form name as a Symbol or String (must satisfy Namespace::NAME_PATTERN). Returns the Kobako::RPC::Namespace for that name, creating it if it does not exist. Raises ArgumentError when name is malformed, or when called after the owning Sandbox has been sealed by #run.
48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/kobako/rpc/server.rb', line 48 def define(name) raise ArgumentError, "cannot define after Sandbox#run has been invoked" if @sealed name_str = name.to_s unless Namespace::NAME_PATTERN.match?(name_str) raise ArgumentError, "Namespace name must match #{Namespace::NAME_PATTERN.inspect} (got #{name.inspect})" end @namespaces[name_str] ||= Namespace.new(name_str) end |
#dispatch(request_bytes) ⇒ Object
Dispatch a single RPC request and return the encoded response bytes (SPEC.md B-12). request_bytes is a msgpack-encoded Request envelope. Called by the Rust ext from inside __kobako_dispatch. Always returns a binary String — never raises. Delegates to Dispatcher.dispatch which reifies any failure as a Response.error envelope so the guest sees the failure as a normal RPC error rather than a wasm trap.
137 138 139 |
# File 'lib/kobako/rpc/server.rb', line 137 def dispatch(request_bytes) Dispatcher.dispatch(request_bytes, self) end |
#empty? ⇒ Boolean
Returns true when no namespaces have been declared, false otherwise.
90 91 92 |
# File 'lib/kobako/rpc/server.rb', line 90 def empty? @namespaces.empty? end |
#encoded_preamble ⇒ Object
Encode the preamble as msgpack bytes for stdin Frame 1 delivery (SPEC.md B-02). Uses plain MessagePack (no kobako ext types) because the preamble contains only strings — no Handles or Fault envelopes. Structure: [[“Namespace”, [“MemberA”, “MemberB”]], …]. Returns a binary String of msgpack bytes.
108 109 110 |
# File 'lib/kobako/rpc/server.rb', line 108 def encoded_preamble MessagePack.pack(to_preamble) end |
#lookup(target) ⇒ Object
Resolve a target path of the form “Namespace::Member” to the bound Host object. target is a two-level path using the :: separator. Returns the bound Host object. Raises KeyError when the namespace or the member is not bound.
64 65 66 67 68 69 70 |
# File 'lib/kobako/rpc/server.rb', line 64 def lookup(target) namespace, member_name, namespace_name = parse_target(target) raise KeyError, "no namespace named #{namespace_name.inspect}" if namespace.nil? raise KeyError, "no member #{target.inspect} bound on server" unless member_name namespace.fetch(member_name) end |
#namespaces ⇒ Object
Returns all declared Kobako::RPC::Namespace instances as an Array.
80 81 82 |
# File 'lib/kobako/rpc/server.rb', line 80 def namespaces @namespaces.values end |
#reset_handles! ⇒ Object
Reset the HandleTable for a new #run boundary. Called by Sandbox#run before each invocation (SPEC.md B-19).
126 127 128 |
# File 'lib/kobako/rpc/server.rb', line 126 def reset_handles! @handle_table.reset! end |
#seal! ⇒ Object
Mark the Server as sealed. Called by Sandbox#run on first run. After sealing, #define raises ArgumentError. Idempotent.
114 115 116 117 |
# File 'lib/kobako/rpc/server.rb', line 114 def seal! @sealed = true self end |
#sealed? ⇒ Boolean
Returns true when #seal! has been called, false otherwise.
120 121 122 |
# File 'lib/kobako/rpc/server.rb', line 120 def sealed? @sealed end |
#size ⇒ Object
Returns the number of declared namespaces as an Integer.
85 86 87 |
# File 'lib/kobako/rpc/server.rb', line 85 def size @namespaces.size end |
#to_preamble ⇒ Object
Structured Frame 1 description. Called by Sandbox#run when assembling stdin Frame 1 (SPEC.md B-02). Returns an unencoded preamble array — an Array of two-element [name, members] arrays, one per declared namespace.
98 99 100 |
# File 'lib/kobako/rpc/server.rb', line 98 def to_preamble @namespaces.values.map(&:to_preamble) end |