Class: Browserctl::PluginDispatcher

Inherits:
Object
  • Object
show all
Includes:
CommandDispatcher::Handlers::ErrorPayload
Defined in:
lib/browserctl/server/plugin_dispatcher.rb

Overview

Invokes plugin commands registered via register_command from the daemon's command-dispatch loop. Extracted from CommandDispatcher in v0.15 WS-2 PR 5 so plugin invocation gets two daemon-protecting properties:

  • A per-plugin wall-clock timeout (default DEFAULT_PLUGIN_TIMEOUT, configurable via timeout: on register_command, opt-out with timeout: nil). On expiry the dispatcher returns a typed PLUGIN_TIMED_OUT response and the daemon stays answering subsequent commands.
  • A rescue boundary that converts ANY uncaught exception from the plugin block into a typed PLUGIN_FAILED JSON-RPC response. The plugin name is always present in the response's context so agents can branch on it. The daemon process is never taken down by a buggy plugin.

Plugins live in the Extension zone (see docs/reference/api-stability.md); the response shape here is documented in docs/reference/errors.md.

Instance Method Summary collapse

Methods included from CommandDispatcher::Handlers::ErrorPayload

#error_payload

Constructor Details

#initialize(pages, global_mutex:) ⇒ PluginDispatcher

Returns a new instance of PluginDispatcher.

Parameters:

  • pages (Hash{String => PageSession}) —

    shared daemon page registry

  • global_mutex (Mutex) —

    mutex guarding the page registry



32
33
34
35
# File 'lib/browserctl/server/plugin_dispatcher.rb', line 32

def initialize(pages, global_mutex:)
  @pages        = pages
  @global_mutex = global_mutex
end

Instance Method Details

#dispatch(req) ⇒ Hash{Symbol => Object}?

Looks up the plugin command for req[:cmd] and invokes it under the timeout / rescue boundary. Returns nil if no plugin handles this command — the caller falls through to its "unknown command" branch.

Parameters:

  • req (Hash{Symbol => Object}) —

    parsed request

Returns:

  • (Hash{Symbol => Object}, nil)


43
44
45
46
47
48
49
50
51
52
# File 'lib/browserctl/server/plugin_dispatcher.rb', line 43

def dispatch(req)
  plugin = Browserctl.lookup_plugin_command(req[:cmd])
  return nil unless plugin

  name    = req[:cmd].to_s
  session = req[:name] ? @global_mutex.synchronize { @pages[req[:name]] } : nil

  Browserctl.logger.debug("plugin:#{name} #{req[:name]}")
  invoke(plugin, name, session, req)
end