Skip to content

Problem: Testing Temporal Workflows with Signals in Ruby SDK Time-Skipping Environment #360

@NielsKSchjoedt

Description

@NielsKSchjoedt

Problem: Testing Temporal Workflows with Signals in Ruby SDK Time-Skipping Environment

Context

I'm testing a workflow in the Temporalio Ruby SDK that uses wait_condition to wait for signals. The workflow works correctly in production, but I cannot test the signal-driven continuation in the time-skipping test environment (Temporalio::Testing::WorkflowEnvironment.start_time_skipping).

Workflow Pattern (Simplified)

class PipelineExecutionWorkflow < Temporalio::Workflow
  workflow_signal
  def customer_replied
    @customer_replied = true
  end

  def execute(opportunity_id, pipeline_id)
    # Step 1: Send initial email
    send_email_activity(opportunity_id)
    
    # Step 2: Wait for customer reply signal
    Temporalio::Workflow.timeout(48.hours) do
      Temporalio::Workflow.wait_condition { @customer_replied }
    end
    
    # Step 3: Process customer reply (extract data, send AI response)
    if @customer_replied
      extract_and_respond(opportunity_id)
    end
    
    { "success" => true }
  end
end

What I've Tried in Tests

Temporalio::Testing::WorkflowEnvironment.start_time_skipping do |env|
  worker = Temporalio::Worker.new(
    client: env.client,
    task_queue: "test-queue",
    workflows: [PipelineExecutionWorkflow],
    activities: [SendEmailActivity, ExtractActivity]
  )
  
  worker.run do
    # Start workflow (doesn't wait for completion)
    workflow_handle = env.client.start_workflow(
      PipelineExecutionWorkflow,
      opportunity_id,
      pipeline_id,
      id: "test-pipeline-#{opportunity_id}",
      task_queue: "test-queue"
    )
    
    # Give time for initial email to be sent
    sleep 0.5
    
    # Check workflow state - shows it's waiting
    state = workflow_handle.query("get_state")
    # => {"waiting_for_signal" => true, "customer_replied" => false}
    
    # Send the signal
    workflow_handle.signal("customer_replied")
    
    # Check state again - signal was received!
    state_after = workflow_handle.query("get_state")
    # => {"waiting_for_signal" => false, "customer_replied" => true}
    
    # But when I try to get the result, it times out or returns nil
    result = workflow_handle.result  # ← TIMES OUT or returns nil
    # The workflow doesn't continue executing after receiving the signal
  end
end

Observed Behavior

  1. ✅ Workflow starts successfully
  2. ✅ Initial email activity executes
  3. ✅ Workflow enters wait state (wait_condition)
  4. ✅ Signal is received (verified via query - @customer_replied becomes true)
  5. Workflow doesn't continue execution after signal received
  6. workflow_handle.result times out or workflow appears "stuck"

Questions

With the Temporal Ruby SDK source code available:

  1. Is this a known limitation of the time-skipping test environment with wait_condition and signals?

  2. What is the correct way to test workflows that use wait_condition with signals in the time-skipping environment?

  3. Should I use a different testing approach for signal-driven workflows? (e.g., real Temporal server, different test helper methods)

  4. Is there a way to manually advance time or "wake up" the workflow after sending a signal in the test environment?

  5. Are there any special considerations or setup required for testing signal-driven workflows that use wait_condition?

Additional Context

  • Ruby SDK version: 1.0.0 (from Gemfile)
  • The workflow works perfectly in production with real Temporal server
  • Synchronous workflows (without signals/wait) test fine in time-skipping environment
  • I've tried both start_workflow (non-blocking) and execute_workflow (blocking) - neither works for the signal continuation

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions