What is the best way to test the setScheduleToCloseTimeout, setStartToCloseTimeout, retryOptions for an activity in a non-prod environment (using the test environment preferably)
To support timeout mocking the SDK treats TimeoutFailure thrown from an activity implementation specially. It doesn’t wrap it in ApplicationFailure, but delivers to the workflow as it is. The following code:
GreetingActivities activities = mock(GreetingActivities.class);
when(activities.composeGreeting("Hello", "World"))
.thenThrow(new TimeoutFailure("not yet1", null, TimeoutType.TIMEOUT_TYPE_START_TO_CLOSE));
worker.registerActivitiesImplementations(activities);
testEnv.start();
// Get a workflow stub using the same task queue the worker uses.
GreetingWorkflow workflow =
client.newWorkflowStub(
GreetingWorkflow.class, WorkflowOptions.newBuilder().setTaskQueue(TASK_QUEUE).build());
// Execute a workflow waiting for it to complete.
String greeting = workflow.getGreeting("World");
throws the exception:
16:18:55.463 [workflow-method] ERROR i.t.i.s.POJOWorkflowImplementationFactory - Workflow execution failure WorkflowId=0a0f8a5a-1d73-41b0-94fb-ba1b913daf2a, RunId=6df40464-262e-407b-b36a-cfd2821dafdd, WorkflowType=GreetingWorkflow
io.temporal.failure.ActivityFailure: scheduledEventId=5, startedEventId=6, activityType='ComposeGreeting', activityId='0', identity='', retryState=RETRY_STATE_TIMEOUT
at java.lang.Thread.getStackTrace(Thread.java:1559)
at io.temporal.internal.sync.ActivityStubBase.execute(ActivityStubBase.java:48)
at io.temporal.internal.sync.ActivityInvocationHandler.lambda$getActivityFunc$0(ActivityInvocationHandler.java:59)
at io.temporal.internal.sync.ActivityInvocationHandlerBase.invoke(ActivityInvocationHandlerBase.java:65)
at com.sun.proxy.$Proxy15.composeGreeting(Unknown Source)
at io.temporal.samples.hello.HelloActivity$GreetingWorkflowImpl.getGreeting(HelloActivity.java:73)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at io.temporal.internal.sync.POJOWorkflowImplementationFactory$POJOWorkflowImplementation$RootWorkflowInboundCallsInterceptor.execute(POJOWorkflowImplementationFactory.java:286)
at io.temporal.internal.sync.POJOWorkflowImplementationFactory$POJOWorkflowImplementation.execute(POJOWorkflowImplementationFactory.java:250)
at io.temporal.internal.sync.WorkflowExecuteRunnable.run(WorkflowExecuteRunnable.java:52)
at io.temporal.internal.sync.SyncWorkflow.lambda$start$0(SyncWorkflow.java:121)
at io.temporal.internal.sync.CancellationScopeImpl.run(CancellationScopeImpl.java:104)
at io.temporal.internal.sync.WorkflowThreadImpl$RunnableWrapper.run(WorkflowThreadImpl.java:107)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: io.temporal.failure.TimeoutFailure: message='not yet1', timeoutType=TIMEOUT_TYPE_START_TO_CLOSE
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method:0)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at io.temporal.internal.sync.POJOActivityTaskHandler$POJOActivityInboundCallsInterceptor.execute(POJOActivityTaskHandler.java:259)
at io.temporal.internal.sync.POJOActivityTaskHandler$POJOActivityImplementation.execute(POJOActivityTaskHandler.java:220)
at io.temporal.internal.sync.POJOActivityTaskHandler.handle(POJOActivityTaskHandler.java:185)
at io.temporal.internal.worker.ActivityWorker$TaskHandlerImpl.handle(ActivityWorker.java:194)
at io.temporal.internal.worker.ActivityWorker$TaskHandlerImpl.handle(ActivityWorker.java:154)
at io.temporal.internal.worker.PollTaskExecutor.lambda$process$0(PollTaskExecutor.java:73)
... 3 common frames omitted
Thanks, Maxim. Here’s my fine tuned question : when(apiClient.xxxxxx(any())).thenThrow(
new IllegalStateException(“Some Exception for activity 1”));
This does cause a few retries - but under the testenv, when I change the value of any of these parameters:
setScheduleToCloseTimeout, setStartToCloseTimeout, retryOptions(change the setMaximumInterval, the backofcoeff) , I see absolutely no difference in freq or number of retries. Is there something I am missing.
Are you taking into account the time skipping the unit testing framework is doing? Try comparing times between different activity invocations using WorkflowTestEnvironment.currentTimeMillis().
Thanks for your reply. . Since I was not aware of the time skipping, I could not explain my performance numbers, but now I do see the expected behavior.