From 877d4dc80a0d22119d11b6b77ec3eff2f7e30204 Mon Sep 17 00:00:00 2001 From: Greg Haskins Date: Mon, 7 Oct 2024 14:54:56 -0400 Subject: [PATCH] Fix default retry behavior for local activities Signed-off-by: Greg Haskins --- src/temporal/internal/activity.clj | 11 +++++-- test/temporal/test/local_retry.clj | 47 ++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 3 deletions(-) create mode 100644 test/temporal/test/local_retry.clj diff --git a/src/temporal/internal/activity.clj b/src/temporal/internal/activity.clj index 47200df..9e9bb4f 100644 --- a/src/temporal/internal/activity.clj +++ b/src/temporal/internal/activity.clj @@ -40,16 +40,21 @@ ^ActivityOptions [params] (u/build (ActivityOptions/newBuilder) invoke-option-spec (import-invoke-options params))) +(defn- local-retry-options-> [{:keys [maximum-attempts] :or {maximum-attempts 0} :as options}] + (-> options + (cond-> (zero? maximum-attempts) (assoc :maximum-attempts Integer/MAX_VALUE)) ;; workaround for https://github.com/temporalio/sdk-java/issues/1727 + (common/retry-options->))) + (def local-invoke-option-spec {:start-to-close-timeout #(.setStartToCloseTimeout ^LocalActivityOptions$Builder %1 %2) :schedule-to-close-timeout #(.setScheduleToCloseTimeout ^LocalActivityOptions$Builder %1 %2) - :retry-options #(.setRetryOptions ^LocalActivityOptions$Builder %1 (common/retry-options-> %2)) + :retry-options #(.setRetryOptions ^LocalActivityOptions$Builder %1 (local-retry-options-> %2)) :do-not-include-args #(.setDoNotIncludeArgumentsIntoMarker ^LocalActivityOptions$Builder %1 %2) :local-retry-threshold #(.setLocalRetryThreshold ^LocalActivityOptions$Builder %1 %2)}) (defn local-invoke-options-> - ^LocalActivityOptions [params] - (u/build (LocalActivityOptions/newBuilder (LocalActivityOptions/getDefaultInstance)) local-invoke-option-spec (import-invoke-options params))) + ^LocalActivityOptions [{:keys [retry-options] :or {retry-options {}} :as params}] + (u/build (LocalActivityOptions/newBuilder (LocalActivityOptions/getDefaultInstance)) local-invoke-option-spec (import-invoke-options (assoc params :retry-options retry-options)))) (extend-protocol p/Datafiable ActivityInfo diff --git a/test/temporal/test/local_retry.clj b/test/temporal/test/local_retry.clj new file mode 100644 index 0000000..966a8a2 --- /dev/null +++ b/test/temporal/test/local_retry.clj @@ -0,0 +1,47 @@ +;; Copyright © Manetu, Inc. All rights reserved + +(ns temporal.test.local-retry + (:require [clojure.test :refer :all] + [promesa.core :as p] + [taoensso.timbre :as log] + [temporal.client.core :as c] + [temporal.workflow :refer [defworkflow]] + [temporal.activity :refer [defactivity] :as a] + [temporal.test.utils :as t]) + (:import (io.temporal.client WorkflowFailedException) + [io.temporal.failure TimeoutFailure ActivityFailure] + [java.time Duration])) + +(use-fixtures :once t/wrap-service) + +(defactivity local-retry-activity + [ctx args] + (log/info "local-retry-activity") + (Thread/sleep 100000000)) + +(defworkflow local-retry-workflow + [args] + (log/info "local-retry-workflow:" args) + @(-> (a/local-invoke local-retry-activity {} (merge args {:do-not-include-args true + :start-to-close-timeout (Duration/ofMillis 500)})) + (p/catch ActivityFailure + :fail))) + +(defn exec [args] + (let [workflow (t/create-workflow local-retry-workflow)] + (c/start workflow args) + @(-> (c/get-result workflow) + (p/then (constantly :fail)) + (p/catch WorkflowFailedException + (fn [ex] + (if (instance? TimeoutFailure (ex-cause ex)) + :pass + :fail)))))) + +(deftest the-test + (testing "RetryPolicy defaults" + (is (= :pass (exec {})))) + (testing "Explicit unlimited" + (is (= :pass (exec {:retry-options {:maximum-attempts 0}})))) + (testing "Verify that setting maximum-attempts to a finite value is respected" + (is (= :fail (exec {:retry-options {:maximum-attempts 1}})))))