Module: Servus::Extensions::Async::Call

Defined in:
lib/servus/extensions/async/call.rb

Overview

Provides asynchronous service execution via ActiveJob.

This module extends Base with the #call_async method, enabling services to be executed in background jobs. Requires ActiveJob to be loaded.

See Also:

Instance Method Summary collapse

Instance Method Details

#call_async(**args) ⇒ void

Note:

Only available when ActiveJob is loaded (typically in Rails applications)

This method returns an undefined value.

Enqueues the service for asynchronous execution via ActiveJob.

This method schedules the service to run in a background job, supporting all standard ActiveJob options for scheduling, queue routing, and priority.

Service arguments are passed as keyword arguments alongside job configuration. Job-specific options are extracted and the remaining arguments are passed to the service's initialize method.

Examples:

Basic async execution

Services::SendEmail::Service.call_async(
  user_id: 123,
  template: :welcome
)

With delay

Services::SendReminder::Service.call_async(
  wait: 1.day,
  user_id: 123
)

With queue and priority

Services::ProcessPayment::Service.call_async(
  queue: :critical,
  priority: 10,
  order_id: 456
)

With custom job options

Services::GenerateReport::Service.call_async(
  wait_until: Date.tomorrow.beginning_of_day,
  job_options: { tags: ['reports', 'daily'] },
  report_type: :sales
)

Parameters:

  • args (Hash)

    combined service arguments and job configuration options

Options Hash (**args):

  • :wait (ActiveSupport::Duration)

    delay before execution (e.g., 5.minutes)

  • :wait_until (Time)

    specific time to execute (e.g., 2.hours.from_now)

  • :queue (Symbol, String)

    queue name (e.g., :low_priority)

  • :priority (Integer)

    job priority (adapter-dependent)

  • :job_options (Hash)

    additional ActiveJob options

Raises:

See Also:



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/servus/extensions/async/call.rb', line 60

def call_async(**args)
  # Extract ActiveJob configuration options
  job_options = args.slice(:wait, :wait_until, :queue, :priority)
  job_options.merge!(args.delete(:job_options) || {}) # merge custom job options

  # Remove special keys that shouldn't be passed to the service
  args.except!(:wait, :wait_until, :queue, :priority, :job_options)

  # Build job with optional delay, scheduling, or queue settings
  job = job_options.any? ? Job.set(**job_options.compact) : Job

  # Enqueue the job asynchronously
  job.perform_later(name: name, args: args)
rescue StandardError => e
  raise Errors::JobEnqueueError, "Failed to enqueue async job for #{self}: #{e.message}"
end