Class: RubyLLM::MCP::Native::CancellableOperation
- Inherits:
-
Object
- Object
- RubyLLM::MCP::Native::CancellableOperation
- Defined in:
- lib/ruby_llm/mcp/native/cancellable_operation.rb
Overview
Wraps server-initiated requests to support cancellation. The operation tracks terminal state so cancellation outcomes are explicit.
Instance Attribute Summary collapse
-
#request_id ⇒ Object
readonly
Returns the value of attribute request_id.
Instance Method Summary collapse
-
#cancel ⇒ Symbol
:cancelled, :already_cancelled, :already_completed.
- #cancelled? ⇒ Boolean
-
#execute ⇒ Object
Execute a block in a separate thread so cancellation can interrupt execution.
-
#initialize(request_id) ⇒ CancellableOperation
constructor
A new instance of CancellableOperation.
- #state ⇒ Object
- #thread ⇒ Object
Constructor Details
#initialize(request_id) ⇒ CancellableOperation
Returns a new instance of CancellableOperation.
11 12 13 14 15 16 17 18 |
# File 'lib/ruby_llm/mcp/native/cancellable_operation.rb', line 11 def initialize(request_id) @request_id = request_id @state = :pending @mutex = Mutex.new @thread = nil @result = nil @error = nil end |
Instance Attribute Details
#request_id ⇒ Object (readonly)
Returns the value of attribute request_id.
9 10 11 |
# File 'lib/ruby_llm/mcp/native/cancellable_operation.rb', line 9 def request_id @request_id end |
Instance Method Details
#cancel ⇒ Symbol
Returns :cancelled, :already_cancelled, :already_completed.
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/ruby_llm/mcp/native/cancellable_operation.rb', line 25 def cancel thread_to_cancel = nil @mutex.synchronize do case @state when :cancelled, :cancelling return :already_cancelled when :completed return :already_completed when :pending @state = :cancelled return :cancelled when :running @state = :cancelling thread_to_cancel = @thread end end if thread_to_cancel&.alive? thread_to_cancel.raise( Errors::RequestCancelled.new( message: "Request #{@request_id} was cancelled", request_id: @request_id ) ) else @mutex.synchronize do @state = :cancelled if @state == :cancelling end end :cancelled end |
#cancelled? ⇒ Boolean
20 21 22 |
# File 'lib/ruby_llm/mcp/native/cancellable_operation.rb', line 20 def cancelled? @mutex.synchronize { %i[cancelling cancelled].include?(@state) } end |
#execute ⇒ Object
Execute a block in a separate thread so cancellation can interrupt execution. Returns the block result or re-raises non-cancellation exceptions.
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# File 'lib/ruby_llm/mcp/native/cancellable_operation.rb', line 61 def execute(&) return nil if cancelled? worker = @mutex.synchronize do return nil if %i[cancelled cancelling].include?(@state) @state = :running @thread = Thread.new do Thread.current.abort_on_exception = false begin @result = yield rescue Errors::RequestCancelled, StandardError => e @error = e end end end worker.join raise @error if @error && !@error.is_a?(Errors::RequestCancelled) @result ensure @mutex.synchronize do if @state == :running || @state == :cancelling @state = @error.is_a?(Errors::RequestCancelled) ? :cancelled : :completed end @thread = nil end end |
#state ⇒ Object
91 92 93 |
# File 'lib/ruby_llm/mcp/native/cancellable_operation.rb', line 91 def state @mutex.synchronize { @state } end |
#thread ⇒ Object
95 96 97 |
# File 'lib/ruby_llm/mcp/native/cancellable_operation.rb', line 95 def thread @mutex.synchronize { @thread } end |