• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

temporalio / sdk-java / #343

31 Oct 2024 06:31PM UTC coverage: 75.148% (-3.6%) from 78.794%
#343

push

github

web-flow
Fix jacoco coverage (#2304)

5139 of 8240 branches covered (62.37%)

Branch coverage included in aggregate %.

22841 of 28993 relevant lines covered (78.78%)

0.79 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.0
/temporal-sdk/src/main/java/io/temporal/internal/sync/CancellationScopeImpl.java
1
/*
2
 * Copyright (C) 2022 Temporal Technologies, Inc. All Rights Reserved.
3
 *
4
 * Copyright (C) 2012-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
5
 *
6
 * Modifications copyright (C) 2017 Uber Technologies, Inc.
7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this material except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 *   http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 */
20

21
package io.temporal.internal.sync;
22

23
import io.temporal.workflow.*;
24
import java.util.ArrayDeque;
25
import java.util.Deque;
26
import java.util.HashSet;
27
import java.util.Set;
28

29
class CancellationScopeImpl implements CancellationScope {
30

31
  private static final ThreadLocal<Deque<CancellationScopeImpl>> scopeStack =
1✔
32
      ThreadLocal.withInitial(ArrayDeque::new);
1✔
33
  private boolean detached;
34
  private CompletablePromise<String> cancellationPromise;
35

36
  static CancellationScopeImpl current() {
37
    if (scopeStack.get().isEmpty()) {
1!
38
      throw new IllegalStateException("Cannot be called by non workflow thread");
×
39
    }
40
    return scopeStack.get().peekFirst();
1✔
41
  }
42

43
  private static void pushCurrent(CancellationScopeImpl scope) {
44
    scopeStack.get().addFirst(scope);
1✔
45
  }
1✔
46

47
  private static void popCurrent(CancellationScopeImpl expected) {
48
    CancellationScopeImpl current = scopeStack.get().pollFirst();
1✔
49
    if (current != expected) {
1!
50
      throw new Error("Unexpected scope");
×
51
    }
52
    if (!current.detached && current.cancellationPromise == null && current.children.isEmpty()) {
1✔
53
      current.parent.removeChild(current);
1✔
54
    }
55
  }
1✔
56

57
  private final Runnable runnable;
58
  private CancellationScopeImpl parent;
59
  private final Set<CancellationScopeImpl> children = new HashSet<>();
1✔
60

61
  /**
62
   * When disconnected scope has no parent and thus doesn't receive cancellation requests from it.
63
   */
64
  private boolean cancelRequested;
65

66
  private String reason;
67

68
  CancellationScopeImpl(boolean ignoreParentCancellation, Runnable runnable) {
69
    this(ignoreParentCancellation, runnable, current());
1✔
70
  }
1✔
71

72
  CancellationScopeImpl(boolean detached, Runnable runnable, CancellationScopeImpl parent) {
1✔
73
    this.detached = detached;
1✔
74
    this.runnable = runnable;
1✔
75
    setParent(parent);
1✔
76
  }
1✔
77

78
  public CancellationScopeImpl(
79
      boolean ignoreParentCancellation, Functions.Proc1<CancellationScope> proc) {
1✔
80
    this.detached = ignoreParentCancellation;
1✔
81
    this.runnable = () -> proc.apply(this);
1✔
82
    setParent(current());
1✔
83
  }
1✔
84

85
  private void setParent(CancellationScopeImpl parent) {
86
    if (parent == null) {
1✔
87
      detached = true;
1✔
88
      return;
1✔
89
    }
90
    if (!detached) {
1✔
91
      this.parent = parent;
1✔
92
      parent.addChild(this);
1✔
93
      if (parent.isCancelRequested()) {
1!
94
        cancel(parent.getCancellationReason());
×
95
      }
96
    }
97
  }
1✔
98

99
  @Override
100
  public void run() {
101
    try {
102
      pushCurrent(this);
1✔
103
      runnable.run();
1✔
104
    } finally {
105
      popCurrent(this);
1✔
106
    }
107
  }
1✔
108

109
  @Override
110
  public boolean isDetached() {
111
    return detached;
×
112
  }
113

114
  @Override
115
  public void cancel() {
116
    cancelRequested = true;
1✔
117
    reason = null;
1✔
118
    for (CancellationScopeImpl child : children) {
1✔
119
      child.cancel();
1✔
120
    }
1✔
121
    if (cancellationPromise != null) {
1✔
122
      cancellationPromise.complete(null);
1✔
123
      cancellationPromise = null;
1✔
124
    }
125
  }
1✔
126

127
  @Override
128
  public void cancel(String reason) {
129
    cancelRequested = true;
1✔
130
    this.reason = reason;
1✔
131
    for (CancellationScopeImpl child : children) {
1✔
132
      child.cancel(reason);
1✔
133
    }
1✔
134
    if (cancellationPromise != null) {
1✔
135
      cancellationPromise.complete(reason);
1✔
136
      cancellationPromise = null;
1✔
137
    }
138
  }
1✔
139

140
  @Override
141
  public String getCancellationReason() {
142
    return reason;
1✔
143
  }
144

145
  @Override
146
  public boolean isCancelRequested() {
147
    return cancelRequested;
1✔
148
  }
149

150
  @Override
151
  public CompletablePromise<String> getCancellationRequest() {
152
    if (cancellationPromise == null) {
1✔
153
      cancellationPromise = Workflow.newPromise();
1✔
154
      if (isCancelRequested()) {
1✔
155
        cancellationPromise.complete(getCancellationReason());
1✔
156
      }
157
    }
158
    return cancellationPromise;
1✔
159
  }
160

161
  private void addChild(CancellationScopeImpl scope) {
162
    children.add(scope);
1✔
163
  }
1✔
164

165
  private void removeChild(CancellationScopeImpl scope) {
166
    if (!children.remove(scope)) {
1!
167
      throw new Error("Not a child");
×
168
    }
169
  }
1✔
170
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc