Module: ActiveJob::Temporal::Cancel

Defined in:
lib/activejob/temporal/cancel.rb,
lib/activejob/temporal/cancel/batch_summary.rb,
lib/activejob/temporal/cancel/batch_canceller.rb

Overview

Note:

Best-Effort Semantics Temporal cancellation is cooperative, not forceful. Activities must check for cancellation by heartbeating or polling Temporalio::Activity::Context.current.cancelled?. Activities that do not check for cancellation will run to completion even after a cancel request.

Note:

Query Strategy This module queries running workflows first, then closed workflows (completed, failed, cancelled, etc.) to determine the workflow state before issuing a cancellation request. This ensures idempotent cancellation behavior.

Job cancellation with query-based workflow discovery.

This module provides cancellation capabilities for ActiveJob workflows running on Temporal. Cancellation is asynchronous and best-effort: workflows will stop only if they are actively checking for cancellation signals (via heartbeating or cancellation checks).

Examples:

Cancel a running job

ActiveJob::Temporal.cancel(SendInvoiceJob, "550e8400-e29b-41d4-a716-446655440000")

See Also:

Defined Under Namespace

Classes: BatchCanceller, BatchSummary

Class Method Summary collapse

Class Method Details

.cancel(job_class, job_id) ⇒ Boolean?

Note:

Asynchronous Cancellation Cancellation requests are asynchronous. The method returns immediately after sending the request. The workflow will stop only if it checks for cancellation.

Cancels a running Temporal workflow by sending a cancellation request.

This method first queries Temporal to determine the workflow state before attempting cancellation. It will not cancel already-completed workflows.

Examples:

Cancel a running job

result = ActiveJob::Temporal.cancel(SendInvoiceJob, "550e8400-e29b-41d4-a716-446655440000")
puts "Cancellation requested" if result.nil?

Handle all outcomes

begin
  result = ActiveJob::Temporal.cancel(MyJob, "abc-123")
  case result
  when false
    puts "Job already completed, cannot cancel"
  when nil
    puts "Cancellation sent to Temporal"
  end
rescue ActiveJob::Temporal::WorkflowNotFoundError
  puts "Job never existed or already removed from history"
rescue ActiveJob::Temporal::TemporalConnectionError => e
  puts "Cannot reach Temporal: #{e.message}"
end

Parameters:

  • job_class (Class)

    The ActiveJob class for the job to cancel.

  • job_id (String)

    Identifier of the job to cancel.

Returns:

  • (Boolean, nil)

    Returns false if workflow already completed, nil if cancellation requested

Raises:

See Also:

  • #find_workflow


111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/activejob/temporal/cancel.rb', line 111

def cancel(job_class, job_id)
  validate_job_id!(job_id)
  client = ActiveJob::Temporal.client
  return nil if cancel_schedule_execution(client, job_class, job_id)

  workflow_state = find_workflow(client, job_class, job_id)
  workflow_id = workflow_state[:workflow_id]

  case workflow_state[:status]
  when :closed
    log_workflow_already_completed(job_class, job_id, workflow_id)
    false
  when :not_found
    raise ActiveJob::Temporal::WorkflowNotFoundError,
          "No workflow found for job_id #{job_id}. The job may have never existed."
  when :running
    request_cancellation(client, job_id, workflow_id)
    log_cancellation_requested(job_class, job_id, workflow_id)
    log_audit_cancellation_requested(job_class, job_id, workflow_id)
    nil
  end
end

.cancel_all(job_class) ⇒ Object



134
135
136
137
138
# File 'lib/activejob/temporal/cancel.rb', line 134

def cancel_all(job_class)
  validate_job_class!(job_class)

  cancel_where(ajClass: job_class.name)
end

.cancel_where(filters) ⇒ Object



140
141
142
# File 'lib/activejob/temporal/cancel.rb', line 140

def cancel_where(filters)
  BatchCanceller.new(ActiveJob::Temporal.client).cancel_where(filters)
end