Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 13 additions & 17 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,19 @@ to docs, or any other relevant information.

## [Unreleased]

### Added

- Exposed `Temporalio::Workflow::ContinueAsNewError#backoff_start_interval`, to allow the new workflow to start after a delay.

### Fixed

#### `Workflow.suggest_continue_as_new_reasons` returns workflow enum values

Workflow activations containing continue-as-new suggestion reasons previously failed because the worker tried to call `to_i` on bridge enum symbols. Continue-as-new suggestion reasons are now converted from bridge enum symbols to
`Temporalio::SuggestContinueAsNewReason` integer enum values before being exposed to workflows.

## [v1.5.0] - 2026-06-11

### Breaking Changes

#### `Activity::Info` workflow fields are now nullable
Expand All @@ -35,8 +48,6 @@ Existing workflow-only code paths are unaffected at runtime. The recommended mig

### Added

- Exposed `Temporalio::Workflow::ContinueAsNewError#backoff_start_interval`, to allow the new workflow to start after a delay.

#### Standalone Activities

Activities can now be started directly from a client, independently of any workflow. `Client#start_activity`
Expand Down Expand Up @@ -65,19 +76,4 @@ correctly receives `Temporalio::Error::WorkflowUpdateFailedError`. (#454)
but defers dispatch to a worker until the delay elapses. Retry attempts do not re-apply the delay.
`ScheduleToStart` and `ScheduleToClose` timeout clocks begin counting after the delay
elapses; `StartToClose` and `Heartbeat` are unaffected. Currently experimental.
<!--
High-level release notes.
Loosely based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

When your PR includes a user-facing change, add an entry below under the
appropriate heading (create the heading if it does not yet exist). Within
each heading content can be free-form. Feel free to include examples, links
to docs, or any other relevant information.

### Added — new features
### Changed — changes in existing functionality
### Deprecated — soon-to-be-removed features
### Breaking Changes — removed or backwards-incompatible features
### Fixed — notable bug fixes
### Security — notable security fixes
-->
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,9 @@ def activate(activation)
@commands = []
@current_activation_error = nil
@continue_as_new_suggested = activation.continue_as_new_suggested
@suggest_continue_as_new_reasons = activation.suggest_continue_as_new_reasons.map(&:to_i)
@suggest_continue_as_new_reasons = activation.suggest_continue_as_new_reasons.map do |reason|
ProtoUtils.enum_to_int(Api::Enums::V1::SuggestContinueAsNewReason, reason)
end
@target_worker_deployment_version_changed = activation.target_worker_deployment_version_changed
@current_deployment_version = WorkerDeploymentVersion._from_bridge(
activation.deployment_version_for_current_task
Expand Down
88 changes: 88 additions & 0 deletions temporalio/test/worker/workflow_instance_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# frozen_string_literal: true

require 'logger'
require 'temporalio/converters'
require 'temporalio/internal/bridge/api'
require 'temporalio/internal/worker/workflow_instance'
require 'temporalio/runtime'
require 'temporalio/workflow'
require 'test'

module Worker
class WorkflowInstanceTest < Test
class ContinueAsNewSuggestionWorkflow < Temporalio::Workflow::Definition
def execute
[
Temporalio::Workflow.continue_as_new_suggested,
Temporalio::Workflow.suggest_continue_as_new_reasons
]
end
end

def test_continue_as_new_suggestion_reasons_are_visible_as_workflow_enum_ints
data_converter = Temporalio::Converters::DataConverter.default
initial_activation = Temporalio::Internal::Bridge::Api::WorkflowActivation::WorkflowActivation.new(
run_id: 'run-id',
timestamp: Google::Protobuf::Timestamp.new(seconds: Time.now.to_i),
history_length: 1,
history_size_bytes: 1,
jobs: [
Temporalio::Internal::Bridge::Api::WorkflowActivation::WorkflowActivationJob.new(
initialize_workflow: Temporalio::Internal::Bridge::Api::WorkflowActivation::InitializeWorkflow.new(
workflow_type: 'ContinueAsNewSuggestionWorkflow',
workflow_id: 'workflow-id',
randomness_seed: 1,
start_time: Google::Protobuf::Timestamp.new(seconds: Time.now.to_i),
workflow_task_timeout: Google::Protobuf::Duration.new(seconds: 10)
)
)
]
)

instance = Temporalio::Internal::Worker::WorkflowInstance.new(
Temporalio::Internal::Worker::WorkflowInstance::Details.new(
namespace: 'namespace',
task_queue: 'task-queue',
definition: Temporalio::Workflow::Definition::Info.from_class(ContinueAsNewSuggestionWorkflow),
initial_activation:,
logger: Logger.new(nil),
metric_meter: Temporalio::Runtime.default.metric_meter,
payload_converter: data_converter.payload_converter,
failure_converter: data_converter.failure_converter,
interceptors: [],
disable_eager_activity_execution: false,
illegal_calls: nil,
workflow_failure_exception_types: [],
unsafe_workflow_io_enabled: false,
assert_valid_local_activity: ->(_) {}
)
)

completion = instance.activate(
Temporalio::Internal::Bridge::Api::WorkflowActivation::WorkflowActivation.new(
run_id: 'run-id',
timestamp: Google::Protobuf::Timestamp.new(seconds: Time.now.to_i),
history_length: 1,
history_size_bytes: 1,
continue_as_new_suggested: true,
suggest_continue_as_new_reasons: [
Temporalio::Api::Enums::V1::SuggestContinueAsNewReason::
SUGGEST_CONTINUE_AS_NEW_REASON_HISTORY_SIZE_TOO_LARGE,
Temporalio::Api::Enums::V1::SuggestContinueAsNewReason::
SUGGEST_CONTINUE_AS_NEW_REASON_TOO_MANY_HISTORY_EVENTS
]
)
)
command = completion.successful.commands.fetch(0)
result = data_converter.payload_converter.from_payload(command.complete_workflow_execution.result)

assert_equal [
true,
[
Temporalio::SuggestContinueAsNewReason::HISTORY_SIZE_TOO_LARGE,
Temporalio::SuggestContinueAsNewReason::TOO_MANY_HISTORY_EVENTS
]
], result
end
end
end
8 changes: 6 additions & 2 deletions temporalio/test/worker_workflow_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -240,16 +240,20 @@ def execute
[
Temporalio::Workflow.continue_as_new_suggested,
Temporalio::Workflow.current_history_length,
Temporalio::Workflow.current_history_size
Temporalio::Workflow.current_history_size,
Temporalio::Workflow.suggest_continue_as_new_reasons
]
end
end

def test_history_info
can_suggested, hist_len, hist_size = execute_workflow(HistoryInfoWorkflow) #: [bool, Integer, Integer]
can_suggested, hist_len, hist_size, reasons =
execute_workflow(HistoryInfoWorkflow) #: [bool, Integer, Integer, Array[Integer]]
refute can_suggested
assert hist_len > 60
assert hist_size > 1500
assert_instance_of Array, reasons
assert_empty reasons
end

class WaitConditionWorkflow < Temporalio::Workflow::Definition
Expand Down