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` 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