Module: CMDx::Middlewares::Timeout

Extended by:
Timeout
Included in:
Timeout
Defined in:
lib/cmdx/middlewares/timeout.rb

Overview

Middleware for enforcing execution time limits on tasks.

The Timeout middleware provides execution time control by wrapping task execution with Ruby’s Timeout module. It automatically fails tasks that exceed the configured time limit and provides detailed error information including the exceeded limit.

Constant Summary collapse

DEFAULT_LIMIT =

Default timeout limit in seconds when none is specified.

3

Instance Method Summary collapse

Instance Method Details

#call(task, **options) { ... } ⇒ Object

Middleware entry point that enforces execution time limits.

Evaluates the condition from options and applies timeout control if enabled. Supports various timeout limit configurations including numeric values, task method calls, and dynamic proc evaluation.

Examples:

Basic usage with default 3 second timeout

Timeout.call(task, &block)

Custom timeout limit in seconds

Timeout.call(task, seconds: 10, &block)

Use task method for timeout limit

Timeout.call(task, seconds: :timeout_limit, &block)

Use proc for dynamic timeout calculation

Timeout.call(task, seconds: -> { calculate_timeout }, &block)

Conditional timeout control

Timeout.call(task, if: :enable_timeout, &block)

Parameters:

  • task (Task)

    The task being executed

  • options (Hash)

    Configuration options for timeout control

Options Hash (**options):

  • :seconds (Numeric, Symbol, Proc, Object)

    The timeout limit source

  • :if (Symbol, Proc, Object, nil)

    Condition to enable timeout control

  • :unless (Symbol, Proc, Object, nil)

    Condition to disable timeout control

Yields:

  • The task execution block

Returns:

  • (Object)

    The result of task execution

Raises:

  • (TimeoutError)

    When execution exceeds the configured limit



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/cmdx/middlewares/timeout.rb', line 58

def call(task, **options, &)
  return yield unless Utils::Condition.evaluate(task, options)

  limit =
    case callable = options[:seconds]
    when Numeric then callable
    when Symbol then task.send(callable)
    when Proc then task.instance_eval(&callable)
    else callable.respond_to?(:call) ? callable.call(task) : DEFAULT_LIMIT
    end

  ::Timeout.timeout(limit, TimeoutError, "execution exceeded #{limit} seconds", &)
rescue TimeoutError => e
  task.result.tap { |r| r.fail!("[#{e.class}] #{e.message}", cause: e, limit:) }
end