Skip to content

Commit f709c41

Browse files
Warn if root thread yields
1 parent e3921b6 commit f709c41

3 files changed

Lines changed: 53 additions & 2 deletions

File tree

temporal-sdk/src/main/java/io/temporal/internal/sync/DeterministicRunnerImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,7 @@ private WorkflowThread newRootThread(Runnable runnable) {
449449
"newRootThread can be called only if there is no existing root workflow thread");
450450
}
451451
rootWorkflowThread =
452-
new WorkflowThreadImpl(
452+
new RootWorkflowThreadImpl(
453453
workflowThreadExecutor,
454454
workflowContext,
455455
this,
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package io.temporal.internal.sync;
2+
3+
import io.temporal.common.context.ContextPropagator;
4+
import io.temporal.internal.worker.WorkflowExecutorCache;
5+
import java.util.List;
6+
import java.util.Map;
7+
import java.util.function.Supplier;
8+
import javax.annotation.Nonnull;
9+
import org.slf4j.Logger;
10+
import org.slf4j.LoggerFactory;
11+
12+
public class RootWorkflowThreadImpl extends WorkflowThreadImpl {
13+
private static final Logger log = LoggerFactory.getLogger(RootWorkflowThreadImpl.class);
14+
15+
RootWorkflowThreadImpl(
16+
WorkflowThreadExecutor workflowThreadExecutor,
17+
SyncWorkflowContext syncWorkflowContext,
18+
DeterministicRunnerImpl runner,
19+
@Nonnull String name,
20+
int priority,
21+
boolean detached,
22+
CancellationScopeImpl parentCancellationScope,
23+
Runnable runnable,
24+
WorkflowExecutorCache cache,
25+
List<ContextPropagator> contextPropagators,
26+
Map<String, Object> propagatedContexts) {
27+
super(
28+
workflowThreadExecutor,
29+
syncWorkflowContext,
30+
runner,
31+
name,
32+
priority,
33+
detached,
34+
parentCancellationScope,
35+
runnable,
36+
cache,
37+
contextPropagators,
38+
propagatedContexts);
39+
}
40+
41+
@Override
42+
public void yield(String reason, Supplier<Boolean> unblockCondition)
43+
throws DestroyWorkflowThreadError {
44+
log.warn(
45+
"Detected root workflow thread yielding {}. This can happen by making blocking calls during workflow instance creating, such as executing an activity inside a @WorkflowInit constructor. This can cause issues, like Queries or Updates rejection because the workflow instance creation is delayed",
46+
getName());
47+
super.yield(reason, unblockCondition);
48+
}
49+
}

temporal-sdk/src/main/java/io/temporal/workflow/WorkflowInit.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@
3434
* thrown by the constructor are treated the same as exceptions thrown by the workflow method.
3535
*
3636
* <p>Workflow initialization methods are called before the workflow method, signal handlers, update
37-
* handlers or query handlers.
37+
* handlers or query handlers. Users should be careful not to block in constructors. Blocking in the
38+
* constructor will delay handling of the workflow method and signal handlers, and cause rejection
39+
* of the update and query handlers.
3840
*
3941
* <p>This annotation applies only to workflow implementation constructors.
4042
*/

0 commit comments

Comments
 (0)