Module: Rigor::Plugin::Isolation
- Defined in:
- lib/rigor/plugin/isolation.rb
Overview
ADR-39 slice 5 — the selectable isolation strategy for target-library invocation. A plugin invokes a pure method on a trusted target library (e.g. ‘ActiveSupport::Inflector.pluralize(“post”)`) through Isolation.call; how much the invocation is isolated from Rigor’s own process is a **configurable strategy** (‘RIGOR_PLUGIN_ISOLATION` env; the `exe/rigor` launcher maps `.rigor.yml`’s ‘plugins_isolation:` onto it before re-exec). Three backends behind one interface:
-
‘none` (default) — load into the main space and call directly. Lowest cost; no isolation. Fine for the common case because the invoked library is trusted + pure.
-
‘ruby_box` — call inside a Box (`Ruby::Box`, `RUBY_BOX=1`). Isolates core-class monkey-patches + lets gem versions coexist, but a native crash in the boxed work still takes the process down (in-process).
-
‘process` — call in a forked worker (Process); returns data over a pipe. The strongest: a child crash (even `SIGSEGV`) is contained —the parent survives and declines. Higher cost (fork + IPC).
All three answer with the method’s return value, or raise Unavailable (never approximate) when the target library cannot be reached in the chosen strategy — the caller’s per-plugin rescue turns that into silence, never a wrong fact.
Defined Under Namespace
Modules: Direct, Process, RubyBox Classes: Unavailable
Constant Summary collapse
- STRATEGIES =
%w[none ruby_box process].freeze
- DEFAULT =
The default strategy. ‘process` (a crash-contained forked worker) is the default: it isolates the target library’s monkey-patches + crashes from Rigor with no in-process contamination, and forks a single persistent worker (not one per call). It falls back to ‘none` where fork is unavailable (see #backend).
"process"
Class Method Summary collapse
-
.backend ⇒ Object
The backend module for the configured strategy.
-
.call(feature:, receiver:, method:, args:) ⇒ Object
Invokes ‘receiver.method(*args)` on a target library, requiring `feature` first, under the configured isolation strategy.
-
.strategy_name ⇒ Object
The configured strategy name (‘RIGOR_PLUGIN_ISOLATION`), defaulting to DEFAULT for any unset / unrecognised value.
Class Method Details
.backend ⇒ Object
The backend module for the configured strategy. ‘process` (including the default) falls back to `Direct` where `fork` is unavailable (Windows / JRuby) so inflection still works rather than silently degrading — the libraries are trusted + pure, so the main-space fallback is acceptable when no fork-based isolation can be had.
67 68 69 70 71 72 73 |
# File 'lib/rigor/plugin/isolation.rb', line 67 def backend case strategy_name when "ruby_box" then RubyBox when "none" then Direct else Process.available? ? Process : Direct end end |
.call(feature:, receiver:, method:, args:) ⇒ Object
Invokes ‘receiver.method(*args)` on a target library, requiring `feature` first, under the configured isolation strategy. `receiver` is a constant name (String), `method` a Symbol from the caller’s allow-list, and ‘args` simple, Marshal-able / inspectable values (Strings) — never free input. Returns the result, or raises Unavailable.
57 58 59 |
# File 'lib/rigor/plugin/isolation.rb', line 57 def call(feature:, receiver:, method:, args:) backend.call(feature: feature, receiver: receiver, method: method, args: args) end |
.strategy_name ⇒ Object
The configured strategy name (‘RIGOR_PLUGIN_ISOLATION`), defaulting to DEFAULT for any unset / unrecognised value.
46 47 48 49 |
# File 'lib/rigor/plugin/isolation.rb', line 46 def strategy_name name = ENV["RIGOR_PLUGIN_ISOLATION"].to_s STRATEGIES.include?(name) ? name : DEFAULT end |