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

temporalio / sdk-java / #169

pending completion
#169

push

github-actions

web-flow
Remove use of deprecated API (#1758)

4 of 4 new or added lines in 1 file covered. (100.0%)

17345 of 21558 relevant lines covered (80.46%)

0.8 hits per line

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

51.63
/temporal-sdk/src/main/java/io/temporal/internal/common/WorkflowExecutionUtils.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.common;
22

23
import com.google.gson.JsonElement;
24
import com.google.gson.JsonPrimitive;
25
import com.google.protobuf.MessageOrBuilder;
26
import com.google.protobuf.TextFormat;
27
import io.temporal.api.command.v1.Command;
28
import io.temporal.api.common.v1.Payloads;
29
import io.temporal.api.common.v1.WorkflowExecution;
30
import io.temporal.api.enums.v1.CommandType;
31
import io.temporal.api.enums.v1.EventType;
32
import io.temporal.api.enums.v1.RetryState;
33
import io.temporal.api.enums.v1.TimeoutType;
34
import io.temporal.api.enums.v1.WorkflowExecutionStatus;
35
import io.temporal.api.history.v1.*;
36
import io.temporal.api.workflowservice.v1.PollWorkflowTaskQueueResponseOrBuilder;
37
import io.temporal.client.WorkflowFailedException;
38
import io.temporal.common.converter.DataConverter;
39
import io.temporal.common.converter.EncodedValues;
40
import io.temporal.failure.CanceledFailure;
41
import io.temporal.failure.TerminatedFailure;
42
import io.temporal.failure.TimeoutFailure;
43
import java.util.ArrayList;
44
import java.util.List;
45
import java.util.Map.Entry;
46
import java.util.Optional;
47
import javax.annotation.Nullable;
48

49
/**
50
 * Convenience methods to be used by unit tests and during development. Intended to be a collection
51
 * of relatively small static utility methods.
52
 */
53
public class WorkflowExecutionUtils {
×
54

55
  /**
56
   * Indentation for history and commands pretty printing. Do not change it from 2 spaces. The gson
57
   * pretty printer has it hardcoded and changing it breaks the indentation of exception stack
58
   * traces.
59
   */
60
  private static final String INDENTATION = "  ";
61

62
  public static Optional<Payloads> getResultFromCloseEvent(
63
      WorkflowExecution workflowExecution,
64
      Optional<String> workflowType,
65
      HistoryEvent closeEvent,
66
      DataConverter dataConverter) {
67
    if (closeEvent == null) {
1✔
68
      throw new IllegalStateException("Workflow is still running");
×
69
    }
70
    switch (closeEvent.getEventType()) {
1✔
71
      case EVENT_TYPE_WORKFLOW_EXECUTION_COMPLETED:
72
        WorkflowExecutionCompletedEventAttributes completedEventAttributes =
1✔
73
            closeEvent.getWorkflowExecutionCompletedEventAttributes();
1✔
74
        if (completedEventAttributes.hasResult()) {
1✔
75
          return Optional.of(completedEventAttributes.getResult());
1✔
76
        }
77
        return Optional.empty();
×
78
      case EVENT_TYPE_WORKFLOW_EXECUTION_CANCELED:
79
        WorkflowExecutionCanceledEventAttributes canceled =
1✔
80
            closeEvent.getWorkflowExecutionCanceledEventAttributes();
1✔
81
        Optional<Payloads> details =
82
            canceled.hasDetails() ? Optional.of(canceled.getDetails()) : Optional.empty();
1✔
83
        throw new WorkflowFailedException(
1✔
84
            workflowExecution,
85
            workflowType.orElse(null),
1✔
86
            closeEvent.getEventType(),
1✔
87
            -1,
88
            RetryState.RETRY_STATE_NON_RETRYABLE_FAILURE,
89
            new CanceledFailure(
90
                "Workflow canceled", new EncodedValues(details, dataConverter), null));
91
      case EVENT_TYPE_WORKFLOW_EXECUTION_FAILED:
92
        WorkflowExecutionFailedEventAttributes failed =
1✔
93
            closeEvent.getWorkflowExecutionFailedEventAttributes();
1✔
94
        throw new WorkflowFailedException(
1✔
95
            workflowExecution,
96
            workflowType.orElse(null),
1✔
97
            closeEvent.getEventType(),
1✔
98
            failed.getWorkflowTaskCompletedEventId(),
1✔
99
            failed.getRetryState(),
1✔
100
            dataConverter.failureToException(failed.getFailure()));
1✔
101
      case EVENT_TYPE_WORKFLOW_EXECUTION_TERMINATED:
102
        WorkflowExecutionTerminatedEventAttributes terminated =
1✔
103
            closeEvent.getWorkflowExecutionTerminatedEventAttributes();
1✔
104
        throw new WorkflowFailedException(
1✔
105
            workflowExecution,
106
            workflowType.orElse(null),
1✔
107
            closeEvent.getEventType(),
1✔
108
            -1,
109
            RetryState.RETRY_STATE_NON_RETRYABLE_FAILURE,
110
            new TerminatedFailure(terminated.getReason(), null));
1✔
111
      case EVENT_TYPE_WORKFLOW_EXECUTION_TIMED_OUT:
112
        WorkflowExecutionTimedOutEventAttributes timedOut =
1✔
113
            closeEvent.getWorkflowExecutionTimedOutEventAttributes();
1✔
114
        throw new WorkflowFailedException(
1✔
115
            workflowExecution,
116
            workflowType.orElse(null),
1✔
117
            closeEvent.getEventType(),
1✔
118
            -1,
119
            timedOut.getRetryState(),
1✔
120
            new TimeoutFailure(null, null, TimeoutType.TIMEOUT_TYPE_START_TO_CLOSE));
121
      default:
122
        throw new RuntimeException(
×
123
            "Workflow end state is not completed: "
124
                + WorkflowExecutionUtils.prettyPrintObject(closeEvent));
×
125
    }
126
  }
127

128
  public static boolean isWorkflowTaskClosedEvent(HistoryEventOrBuilder event) {
129
    return ((event != null)
1✔
130
        && (event.getEventType() == EventType.EVENT_TYPE_WORKFLOW_TASK_COMPLETED
1✔
131
            || event.getEventType() == EventType.EVENT_TYPE_WORKFLOW_TASK_FAILED
1✔
132
            || event.getEventType() == EventType.EVENT_TYPE_WORKFLOW_TASK_TIMED_OUT));
1✔
133
  }
134

135
  public static boolean isWorkflowExecutionClosedEvent(HistoryEventOrBuilder event) {
136
    return ((event != null)
1✔
137
        && (event.getEventType() == EventType.EVENT_TYPE_WORKFLOW_EXECUTION_COMPLETED
1✔
138
            || event.getEventType() == EventType.EVENT_TYPE_WORKFLOW_EXECUTION_CANCELED
1✔
139
            || event.getEventType() == EventType.EVENT_TYPE_WORKFLOW_EXECUTION_FAILED
1✔
140
            || event.getEventType() == EventType.EVENT_TYPE_WORKFLOW_EXECUTION_TIMED_OUT
1✔
141
            || event.getEventType() == EventType.EVENT_TYPE_WORKFLOW_EXECUTION_CONTINUED_AS_NEW
1✔
142
            || event.getEventType() == EventType.EVENT_TYPE_WORKFLOW_EXECUTION_TERMINATED));
1✔
143
  }
144

145
  public static boolean isWorkflowExecutionCompleteCommand(Command command) {
146
    return ((command != null)
1✔
147
        && (command.getCommandType() == CommandType.COMMAND_TYPE_COMPLETE_WORKFLOW_EXECUTION
1✔
148
            || command.getCommandType() == CommandType.COMMAND_TYPE_CANCEL_WORKFLOW_EXECUTION
1✔
149
            || command.getCommandType() == CommandType.COMMAND_TYPE_FAIL_WORKFLOW_EXECUTION
1✔
150
            || command.getCommandType()
1✔
151
                == CommandType.COMMAND_TYPE_CONTINUE_AS_NEW_WORKFLOW_EXECUTION));
152
  }
153

154
  public static boolean isActivityTaskClosedEvent(HistoryEvent event) {
155
    return ((event != null)
×
156
        && (event.getEventType() == EventType.EVENT_TYPE_ACTIVITY_TASK_COMPLETED
×
157
            || event.getEventType() == EventType.EVENT_TYPE_ACTIVITY_TASK_CANCELED
×
158
            || event.getEventType() == EventType.EVENT_TYPE_ACTIVITY_TASK_FAILED
×
159
            || event.getEventType() == EventType.EVENT_TYPE_ACTIVITY_TASK_TIMED_OUT));
×
160
  }
161

162
  public static boolean isExternalWorkflowClosedEvent(HistoryEvent event) {
163
    return ((event != null)
×
164
        && (event.getEventType() == EventType.EVENT_TYPE_CHILD_WORKFLOW_EXECUTION_COMPLETED
×
165
            || event.getEventType() == EventType.EVENT_TYPE_CHILD_WORKFLOW_EXECUTION_CANCELED
×
166
            || event.getEventType() == EventType.EVENT_TYPE_CHILD_WORKFLOW_EXECUTION_FAILED
×
167
            || event.getEventType() == EventType.EVENT_TYPE_CHILD_WORKFLOW_EXECUTION_TERMINATED
×
168
            || event.getEventType() == EventType.EVENT_TYPE_CHILD_WORKFLOW_EXECUTION_TIMED_OUT));
×
169
  }
170

171
  public static WorkflowExecution getWorkflowIdFromExternalWorkflowCompletedEvent(
172
      HistoryEvent event) {
173
    if (event != null) {
×
174
      if (event.getEventType() == EventType.EVENT_TYPE_CHILD_WORKFLOW_EXECUTION_COMPLETED) {
×
175
        return event.getChildWorkflowExecutionCompletedEventAttributes().getWorkflowExecution();
×
176
      } else if (event.getEventType() == EventType.EVENT_TYPE_CHILD_WORKFLOW_EXECUTION_CANCELED) {
×
177
        return event.getChildWorkflowExecutionCanceledEventAttributes().getWorkflowExecution();
×
178
      } else if (event.getEventType() == EventType.EVENT_TYPE_CHILD_WORKFLOW_EXECUTION_FAILED) {
×
179
        return event.getChildWorkflowExecutionFailedEventAttributes().getWorkflowExecution();
×
180
      } else if (event.getEventType() == EventType.EVENT_TYPE_CHILD_WORKFLOW_EXECUTION_TERMINATED) {
×
181
        return event.getChildWorkflowExecutionTerminatedEventAttributes().getWorkflowExecution();
×
182
      } else if (event.getEventType() == EventType.EVENT_TYPE_CHILD_WORKFLOW_EXECUTION_TIMED_OUT) {
×
183
        return event.getChildWorkflowExecutionTimedOutEventAttributes().getWorkflowExecution();
×
184
      }
185
    }
186

187
    return null;
×
188
  }
189

190
  public static String getId(HistoryEvent historyEvent) {
191
    String id = null;
×
192
    if (historyEvent != null) {
×
193
      if (historyEvent.getEventType()
×
194
          == EventType.EVENT_TYPE_START_CHILD_WORKFLOW_EXECUTION_FAILED) {
195
        id = historyEvent.getStartChildWorkflowExecutionFailedEventAttributes().getWorkflowId();
×
196
      }
197
    }
198

199
    return id;
×
200
  }
201

202
  public static String getFailureCause(HistoryEvent historyEvent) {
203
    String failureCause = null;
×
204
    if (historyEvent != null) {
×
205
      if (historyEvent.getEventType()
×
206
          == EventType.EVENT_TYPE_START_CHILD_WORKFLOW_EXECUTION_FAILED) {
207
        failureCause =
×
208
            historyEvent
209
                .getStartChildWorkflowExecutionFailedEventAttributes()
×
210
                .getCause()
×
211
                .toString();
×
212
        //            } else if (historyEvent.getEventType() ==
213
        // EventType.EVENT_TYPE_SIGNAL_EXTERNAL_WORKFLOW_EXECUTION_FAILED) {
214
        //                failureCause =
215
        // historyEvent.getSignalExternalWorkflowExecutionFailedEventAttributes().getCause();
216
      } else {
217
        failureCause = "Cannot extract failure cause from " + historyEvent.getEventType();
×
218
      }
219
    }
220

221
    return failureCause;
×
222
  }
223

224
  public static WorkflowExecutionStatus getCloseStatus(HistoryEvent event) {
225
    switch (event.getEventType()) {
1✔
226
      case EVENT_TYPE_WORKFLOW_EXECUTION_CANCELED:
227
        return WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_CANCELED;
×
228
      case EVENT_TYPE_WORKFLOW_EXECUTION_FAILED:
229
        return WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_FAILED;
1✔
230
      case EVENT_TYPE_WORKFLOW_EXECUTION_TIMED_OUT:
231
        return WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_TIMED_OUT;
×
232
      case EVENT_TYPE_WORKFLOW_EXECUTION_CONTINUED_AS_NEW:
233
        return WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_CONTINUED_AS_NEW;
×
234
      case EVENT_TYPE_WORKFLOW_EXECUTION_COMPLETED:
235
        return WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_COMPLETED;
1✔
236
      case EVENT_TYPE_WORKFLOW_EXECUTION_TERMINATED:
237
        return WorkflowExecutionStatus.WORKFLOW_EXECUTION_STATUS_TERMINATED;
×
238
      default:
239
        throw new IllegalArgumentException("Not a close event: " + event);
×
240
    }
241
  }
242

243
  public static String prettyPrintCommands(Iterable<Command> commands) {
244
    StringBuilder result = new StringBuilder();
×
245
    for (Command command : commands) {
×
246
      result.append(prettyPrintObject(command));
×
247
    }
×
248
    return result.toString();
×
249
  }
250

251
  /** Pretty prints a proto message. */
252
  @SuppressWarnings("deprecation")
253
  public static String prettyPrintObject(MessageOrBuilder object) {
254
    return TextFormat.printToString(object);
×
255
  }
256

257
  public static boolean containsEvent(List<HistoryEvent> history, EventType eventType) {
258
    for (HistoryEvent event : history) {
×
259
      if (event.getEventType() == eventType) {
×
260
        return true;
×
261
      }
262
    }
×
263
    return false;
×
264
  }
265

266
  private static void fixStackTrace(JsonElement json, String stackIndentation) {
267
    if (!json.isJsonObject()) {
×
268
      return;
×
269
    }
270
    for (Entry<String, JsonElement> entry : json.getAsJsonObject().entrySet()) {
×
271
      if ("stackTrace".equals(entry.getKey())) {
×
272
        String value = entry.getValue().getAsString();
×
273
        String replacement = "\n" + stackIndentation;
×
274
        String fixed = value.replaceAll("\\n", replacement);
×
275
        entry.setValue(new JsonPrimitive(fixed));
×
276
        continue;
×
277
      }
278
      fixStackTrace(entry.getValue(), stackIndentation + INDENTATION);
×
279
    }
×
280
  }
×
281

282
  /** Command event is an event that is created to mirror a command issued by a workflow task */
283
  public static boolean isCommandEvent(HistoryEvent event) {
284
    EventType eventType = event.getEventType();
1✔
285
    switch (eventType) {
1✔
286
      case EVENT_TYPE_ACTIVITY_TASK_SCHEDULED:
287
      case EVENT_TYPE_START_CHILD_WORKFLOW_EXECUTION_INITIATED:
288
      case EVENT_TYPE_TIMER_STARTED:
289
      case EVENT_TYPE_WORKFLOW_EXECUTION_COMPLETED:
290
      case EVENT_TYPE_WORKFLOW_EXECUTION_FAILED:
291
      case EVENT_TYPE_WORKFLOW_EXECUTION_CANCELED:
292
      case EVENT_TYPE_WORKFLOW_EXECUTION_CONTINUED_AS_NEW:
293
      case EVENT_TYPE_ACTIVITY_TASK_CANCEL_REQUESTED:
294
      case EVENT_TYPE_TIMER_CANCELED:
295
      case EVENT_TYPE_REQUEST_CANCEL_EXTERNAL_WORKFLOW_EXECUTION_INITIATED:
296
      case EVENT_TYPE_MARKER_RECORDED:
297
      case EVENT_TYPE_SIGNAL_EXTERNAL_WORKFLOW_EXECUTION_INITIATED:
298
      case EVENT_TYPE_UPSERT_WORKFLOW_SEARCH_ATTRIBUTES:
299
      case EVENT_TYPE_WORKFLOW_EXECUTION_UPDATE_ACCEPTED:
300
      case EVENT_TYPE_WORKFLOW_EXECUTION_UPDATE_REJECTED:
301
      case EVENT_TYPE_WORKFLOW_EXECUTION_UPDATE_COMPLETED:
302
        return true;
1✔
303
      default:
304
        return false;
1✔
305
    }
306
  }
307

308
  /** Returns event that corresponds to a command. */
309
  public static EventType getEventTypeForCommand(CommandType commandType) {
310
    switch (commandType) {
1✔
311
      case COMMAND_TYPE_SCHEDULE_ACTIVITY_TASK:
312
        return EventType.EVENT_TYPE_ACTIVITY_TASK_SCHEDULED;
1✔
313
      case COMMAND_TYPE_REQUEST_CANCEL_ACTIVITY_TASK:
314
        return EventType.EVENT_TYPE_ACTIVITY_TASK_CANCEL_REQUESTED;
1✔
315
      case COMMAND_TYPE_START_TIMER:
316
        return EventType.EVENT_TYPE_TIMER_STARTED;
1✔
317
      case COMMAND_TYPE_COMPLETE_WORKFLOW_EXECUTION:
318
        return EventType.EVENT_TYPE_WORKFLOW_EXECUTION_COMPLETED;
1✔
319
      case COMMAND_TYPE_FAIL_WORKFLOW_EXECUTION:
320
        return EventType.EVENT_TYPE_WORKFLOW_EXECUTION_FAILED;
1✔
321
      case COMMAND_TYPE_CANCEL_TIMER:
322
        return EventType.EVENT_TYPE_TIMER_CANCELED;
1✔
323
      case COMMAND_TYPE_CANCEL_WORKFLOW_EXECUTION:
324
        return EventType.EVENT_TYPE_WORKFLOW_EXECUTION_CANCELED;
×
325
      case COMMAND_TYPE_REQUEST_CANCEL_EXTERNAL_WORKFLOW_EXECUTION:
326
        return EventType.EVENT_TYPE_REQUEST_CANCEL_EXTERNAL_WORKFLOW_EXECUTION_INITIATED;
1✔
327
      case COMMAND_TYPE_RECORD_MARKER:
328
        return EventType.EVENT_TYPE_MARKER_RECORDED;
1✔
329
      case COMMAND_TYPE_CONTINUE_AS_NEW_WORKFLOW_EXECUTION:
330
        return EventType.EVENT_TYPE_WORKFLOW_EXECUTION_CONTINUED_AS_NEW;
×
331
      case COMMAND_TYPE_START_CHILD_WORKFLOW_EXECUTION:
332
        return EventType.EVENT_TYPE_START_CHILD_WORKFLOW_EXECUTION_INITIATED;
1✔
333
      case COMMAND_TYPE_SIGNAL_EXTERNAL_WORKFLOW_EXECUTION:
334
        return EventType.EVENT_TYPE_SIGNAL_EXTERNAL_WORKFLOW_EXECUTION_INITIATED;
1✔
335
      case COMMAND_TYPE_UPSERT_WORKFLOW_SEARCH_ATTRIBUTES:
336
        return EventType.EVENT_TYPE_UPSERT_WORKFLOW_SEARCH_ATTRIBUTES;
1✔
337
    }
338
    throw new IllegalArgumentException("Unknown commandType");
×
339
  }
340

341
  public static boolean isFullHistory(PollWorkflowTaskQueueResponseOrBuilder workflowTask) {
342
    return workflowTask.getHistory() != null
1✔
343
        && workflowTask.getHistory().getEventsCount() > 0
1✔
344
        && workflowTask.getHistory().getEvents(0).getEventId() == 1;
1✔
345
  }
346

347
  @Nullable
348
  public static HistoryEvent getEventOfType(History history, EventType eventType) {
349
    List<HistoryEvent> events = getEventsOfType(history, eventType);
1✔
350
    if (events.size() > 1) {
1✔
351
      throw new IllegalStateException(
×
352
          "More than one event of type " + eventType + " found in the history");
353
    }
354
    return events.size() > 0 ? events.get(0) : null;
1✔
355
  }
356

357
  public static List<HistoryEvent> getEventsOfType(History history, EventType eventType) {
358
    List<HistoryEvent> result = new ArrayList<>();
1✔
359
    for (HistoryEvent event : history.getEventsList()) {
1✔
360
      if (eventType == event.getEventType()) {
1✔
361
        result.add(event);
1✔
362
      }
363
    }
1✔
364
    return result;
1✔
365
  }
366
}
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