Skip to content
Merged
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
7 changes: 5 additions & 2 deletions temporalio/lib/temporalio/converters/failure_converter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ def to_failure(error, converter)
type: error.type,
non_retryable: error.non_retryable,
details: converter.to_payloads(error.details),
next_retry_delay: Internal::ProtoUtils.seconds_to_duration(error.next_retry_delay)
next_retry_delay: Internal::ProtoUtils.seconds_to_duration(error.next_retry_delay),
category: error.category
)
when Error::TimeoutError
failure.timeout_failure_info = Api::Failure::V1::TimeoutFailureInfo.new(
Expand Down Expand Up @@ -132,7 +133,9 @@ def from_failure(failure, converter)
non_retryable: failure.application_failure_info.non_retryable,
next_retry_delay: Internal::ProtoUtils.duration_to_seconds(
failure.application_failure_info.next_retry_delay
)
),
category: Internal::ProtoUtils.enum_to_int(Api::Enums::V1::ApplicationErrorCategory,
failure.application_failure_info.category)
)
elsif failure.timeout_failure_info
Error::TimeoutError.new(
Expand Down
20 changes: 19 additions & 1 deletion temporalio/lib/temporalio/error/failure.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,25 +46,43 @@ class ApplicationError < Failure
# @return [Float, nil] Delay in seconds before the next activity retry attempt.
attr_reader :next_retry_delay

# @return [Category] Error category.
attr_reader :category

# Create an application error.
#
# @param message [String] Error message.
# @param details [Array<Object, nil>] Error details.
# @param type [String, nil] Error type.
# @param non_retryable [Boolean] Whether this error should be considered non-retryable.
# @param next_retry_delay [Float, nil] Specific amount of time to delay before next retry.
def initialize(message, *details, type: nil, non_retryable: false, next_retry_delay: nil)
# @param category [Category] Error category.
def initialize(
message,
*details,
type: nil,
non_retryable: false,
next_retry_delay: nil,
category: Category::UNSPECIFIED
)
super(message)
@details = details
@type = type
@non_retryable = non_retryable
@next_retry_delay = next_retry_delay
@category = category
end

# @return [Boolean] Inverse of {non_retryable}.
def retryable?
!@non_retryable
end

# Error category.
module Category
UNSPECIFIED = Api::Enums::V1::ApplicationErrorCategory::APPLICATION_ERROR_CATEGORY_UNSPECIFIED
BENIGN = Api::Enums::V1::ApplicationErrorCategory::APPLICATION_ERROR_CATEGORY_BENIGN
end
end

# Error raised on workflow/activity cancellation.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -279,8 +279,13 @@ def run_activity(defn, activity, input)
)
else
# General failure
@scoped_logger.warn('Completing activity as failed')
@scoped_logger.warn(e)
log_level = if e.is_a?(Error::ApplicationError) && e.category == Error::ApplicationError::Category::BENIGN
Logger::DEBUG
else
Logger::WARN
end
@scoped_logger.add(log_level, 'Completing activity as failed')
@scoped_logger.add(log_level, e)
Bridge::Api::ActivityResult::ActivityExecutionResult.new(
failed: Bridge::Api::ActivityResult::Failure.new(
failure: @worker.options.client.data_converter.to_failure(e)
Expand Down
11 changes: 10 additions & 1 deletion temporalio/sig/temporalio/error/failure.rbs
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,25 @@ module Temporalio
attr_reader type: String?
attr_reader non_retryable: bool
attr_reader next_retry_delay: duration?
attr_reader category: Category::enum

def initialize: (
String message,
*Object? details,
?type: String?,
?non_retryable: bool,
?next_retry_delay: duration?
?next_retry_delay: duration?,
?category: Category::enum
) -> void

def retryable?: -> bool

module Category
type enum = Integer

UNSPECIFIED: enum
BENIGN: enum
end
end

class CanceledError < Failure
Expand Down
14 changes: 14 additions & 0 deletions temporalio/test/worker_activity_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,12 @@ def execute(form)
non_retryable: true,
next_retry_delay: 1.23
)
when 'application-benign'
raise Temporalio::Error::ApplicationError.new(
'application-error-benign',
type: 'some-error-type',
category: Temporalio::Error::ApplicationError::Category::BENIGN
)
end
end
end
Expand All @@ -203,6 +209,14 @@ def test_failure
assert_equal 'some-error-type', error.cause.cause.type
assert error.cause.cause.non_retryable
assert_equal 1.23, error.cause.cause.next_retry_delay

# Check that benign application error category is set
error = assert_raises(Temporalio::Error::WorkflowFailedError) do
execute_activity(FailureActivity, 'application-benign')
end
assert_equal 'application-error-benign', error.cause.cause.message
assert_equal 'some-error-type', error.cause.cause.type
assert_equal Temporalio::Error::ApplicationError::Category::BENIGN, error.cause.cause.category
end

class UnimplementedExecuteActivity < Temporalio::Activity::Definition
Expand Down
Loading