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

temporalio / sdk-java / #188

25 Sep 2023 04:42PM UTC coverage: 77.369% (-0.3%) from 77.663%
#188

push

github-actions

web-flow
Fix null pointer on trigger immediately (#1865)

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

18670 of 24131 relevant lines covered (77.37%)

0.77 hits per line

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

3.77
/temporal-sdk/src/main/java/io/temporal/internal/client/RootScheduleClientInvoker.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.client;
22

23
import static io.temporal.internal.common.HeaderUtils.intoPayloadMap;
24

25
import com.google.common.collect.Iterators;
26
import io.grpc.Status;
27
import io.grpc.StatusRuntimeException;
28
import io.temporal.api.common.v1.Memo;
29
import io.temporal.api.schedule.v1.*;
30
import io.temporal.api.workflowservice.v1.*;
31
import io.temporal.client.ListScheduleListDescriptionIterator;
32
import io.temporal.client.schedules.*;
33
import io.temporal.common.interceptors.ScheduleClientCallsInterceptor;
34
import io.temporal.internal.client.external.GenericWorkflowClient;
35
import io.temporal.internal.common.ProtobufTimeUtils;
36
import io.temporal.internal.common.SearchAttributesUtil;
37
import java.util.*;
38
import java.util.stream.StreamSupport;
39
import org.slf4j.Logger;
40
import org.slf4j.LoggerFactory;
41

42
public class RootScheduleClientInvoker implements ScheduleClientCallsInterceptor {
43
  private static final Logger log = LoggerFactory.getLogger(RootScheduleClientInvoker.class);
1✔
44

45
  private final GenericWorkflowClient genericClient;
46

47
  private final ScheduleClientOptions clientOptions;
48

49
  private final ScheduleProtoUtil scheduleRequestHeader;
50

51
  public RootScheduleClientInvoker(
52
      GenericWorkflowClient genericClient, ScheduleClientOptions clientOptions) {
1✔
53
    this.genericClient = genericClient;
1✔
54
    this.clientOptions = clientOptions;
1✔
55
    this.scheduleRequestHeader = new ScheduleProtoUtil(genericClient, clientOptions);
1✔
56
  }
1✔
57

58
  @Override
59
  @SuppressWarnings("deprecation")
60
  public void createSchedule(CreateScheduleInput input) {
61

62
    CreateScheduleRequest.Builder request =
63
        CreateScheduleRequest.newBuilder()
×
64
            .setIdentity(clientOptions.getIdentity())
×
65
            .setNamespace(clientOptions.getNamespace())
×
66
            .setRequestId(UUID.randomUUID().toString())
×
67
            .setScheduleId(input.getId())
×
68
            .setSchedule(scheduleRequestHeader.scheduleToProto(input.getSchedule()));
×
69

70
    if (input.getOptions().getMemo() != null) {
×
71
      request.setMemo(
×
72
          Memo.newBuilder()
×
73
              .putAllFields(
×
74
                  intoPayloadMap(clientOptions.getDataConverter(), input.getOptions().getMemo())));
×
75
    }
76

77
    if (input.getOptions().getSearchAttributes() != null
×
78
        && !input.getOptions().getSearchAttributes().isEmpty()) {
×
79
      if (input.getOptions().getTypedSearchAttributes() != null) {
×
80
        throw new IllegalArgumentException(
×
81
            "Cannot have search attributes and typed search attributes");
82
      }
83
      request.setSearchAttributes(
×
84
          SearchAttributesUtil.encode(input.getOptions().getSearchAttributes()));
×
85
    } else if (input.getOptions().getTypedSearchAttributes() != null) {
×
86
      request.setSearchAttributes(
×
87
          SearchAttributesUtil.encodeTyped(input.getOptions().getTypedSearchAttributes()));
×
88
    }
89

90
    if (input.getOptions().isTriggerImmediately()
×
91
        || (input.getOptions().getBackfills() != null
×
92
            && input.getOptions().getBackfills().size() > 0)) {
×
93
      SchedulePatch.Builder patchBuilder = SchedulePatch.newBuilder();
×
94

95
      if (input.getOptions().getBackfills() != null) {
×
96
        input.getOptions().getBackfills().stream()
×
97
            .forEach(b -> patchBuilder.addBackfillRequest(backfillToProto(b)));
×
98
      }
99

100
      if (input.getOptions().isTriggerImmediately()) {
×
101
        TriggerImmediatelyRequest.Builder triggerRequest = TriggerImmediatelyRequest.newBuilder();
×
102
        if (input.getSchedule().getPolicy() != null) {
×
103
          triggerRequest.setOverlapPolicy(input.getSchedule().getPolicy().getOverlap());
×
104
        }
105
        patchBuilder.setTriggerImmediately(triggerRequest.build());
×
106
      }
107

108
      request.setInitialPatch(patchBuilder.build());
×
109
    }
110

111
    try {
112
      genericClient.createSchedule(request.build());
×
113
    } catch (StatusRuntimeException e) {
×
114
      if (Status.Code.ALREADY_EXISTS.equals(e.getStatus().getCode())) {
×
115
        throw new ScheduleAlreadyRunningException(e);
×
116
      } else {
117
        throw new ScheduleException(e);
×
118
      }
119
    } catch (Exception e) {
×
120
      throw new ScheduleException(e);
×
121
    }
×
122
  }
×
123

124
  @Override
125
  public ListScheduleOutput listSchedules(ListSchedulesInput input) {
126
    ListScheduleListDescriptionIterator iterator =
×
127
        new ListScheduleListDescriptionIterator(
128
            clientOptions.getNamespace(), input.getPageSize(), genericClient);
×
129
    iterator.init();
×
130
    Iterator<ScheduleListDescription> wrappedIterator =
×
131
        Iterators.transform(
×
132
            iterator, entry -> scheduleRequestHeader.protoToScheduleListDescription(entry));
×
133

134
    final int CHARACTERISTICS =
×
135
        Spliterator.ORDERED | Spliterator.DISTINCT | Spliterator.NONNULL | Spliterator.IMMUTABLE;
136
    return new ListScheduleOutput(
×
137
        StreamSupport.stream(
×
138
            Spliterators.spliteratorUnknownSize(wrappedIterator, CHARACTERISTICS), false));
×
139
  }
140

141
  public BackfillRequest backfillToProto(ScheduleBackfill backfill) {
142
    return BackfillRequest.newBuilder()
×
143
        .setStartTime(ProtobufTimeUtils.toProtoTimestamp(backfill.getStartAt()))
×
144
        .setEndTime(ProtobufTimeUtils.toProtoTimestamp(backfill.getEndAt()))
×
145
        .setOverlapPolicy(backfill.getOverlapPolicy())
×
146
        .build();
×
147
  }
148

149
  @Override
150
  public void backfillSchedule(BackfillScheduleInput input) {
151
    ArrayList<BackfillRequest> backfillRequests =
×
152
        new ArrayList<BackfillRequest>(input.getBackfills().size());
×
153
    for (ScheduleBackfill backfill : input.getBackfills()) {
×
154
      backfillRequests.add(backfillToProto(backfill));
×
155
    }
×
156

157
    SchedulePatch patch =
158
        SchedulePatch.newBuilder().addAllBackfillRequest(backfillRequests).build();
×
159

160
    PatchScheduleRequest request =
161
        PatchScheduleRequest.newBuilder()
×
162
            .setIdentity(clientOptions.getIdentity())
×
163
            .setNamespace(clientOptions.getNamespace())
×
164
            .setScheduleId(input.getScheduleId())
×
165
            .setPatch(patch)
×
166
            .build();
×
167
    try {
168
      genericClient.patchSchedule(request);
×
169
    } catch (Exception e) {
×
170
      throw new ScheduleException(e);
×
171
    }
×
172
  }
×
173

174
  @Override
175
  public void deleteSchedule(DeleteScheduleInput input) {
176
    DeleteScheduleRequest request =
177
        DeleteScheduleRequest.newBuilder()
×
178
            .setIdentity(clientOptions.getIdentity())
×
179
            .setNamespace(clientOptions.getNamespace())
×
180
            .setScheduleId(input.getScheduleId())
×
181
            .build();
×
182
    try {
183
      genericClient.deleteSchedule(request);
×
184
    } catch (Exception e) {
×
185
      throw new ScheduleException(e);
×
186
    }
×
187
  }
×
188

189
  @Override
190
  public DescribeScheduleOutput describeSchedule(DescribeScheduleInput input) {
191
    DescribeScheduleRequest request =
192
        DescribeScheduleRequest.newBuilder()
×
193
            .setNamespace(clientOptions.getNamespace())
×
194
            .setScheduleId(input.getScheduleId())
×
195
            .build();
×
196

197
    try {
198
      DescribeScheduleResponse response = genericClient.describeSchedule(request);
×
199
      return new DescribeScheduleOutput(
×
200
          new ScheduleDescription(
201
              input.getScheduleId(),
×
202
              scheduleRequestHeader.protoToScheduleInfo(response.getInfo()),
×
203
              scheduleRequestHeader.protoToSchedule(response.getSchedule()),
×
204
              Collections.unmodifiableMap(
×
205
                  SearchAttributesUtil.decode(response.getSearchAttributes())),
×
206
              SearchAttributesUtil.decodeTyped(response.getSearchAttributes()),
×
207
              response.getMemo().getFieldsMap(),
×
208
              clientOptions.getDataConverter()));
×
209
    } catch (Exception e) {
×
210
      throw new ScheduleException(e);
×
211
    }
212
  }
213

214
  @Override
215
  public void pauseSchedule(PauseScheduleInput input) {
216
    SchedulePatch patch = SchedulePatch.newBuilder().setPause(input.getNote()).build();
×
217

218
    PatchScheduleRequest request =
219
        PatchScheduleRequest.newBuilder()
×
220
            .setIdentity(clientOptions.getIdentity())
×
221
            .setNamespace(clientOptions.getNamespace())
×
222
            .setScheduleId(input.getScheduleId())
×
223
            .setPatch(patch)
×
224
            .build();
×
225
    try {
226
      genericClient.patchSchedule(request);
×
227
    } catch (Exception e) {
×
228
      throw new ScheduleException(e);
×
229
    }
×
230
  }
×
231

232
  @Override
233
  public void triggerSchedule(TriggerScheduleInput input) {
234
    TriggerImmediatelyRequest trigger =
235
        TriggerImmediatelyRequest.newBuilder().setOverlapPolicy(input.getOverlapPolicy()).build();
×
236

237
    SchedulePatch patch = SchedulePatch.newBuilder().setTriggerImmediately(trigger).build();
×
238

239
    PatchScheduleRequest request =
240
        PatchScheduleRequest.newBuilder()
×
241
            .setIdentity(clientOptions.getIdentity())
×
242
            .setNamespace(clientOptions.getNamespace())
×
243
            .setScheduleId(input.getScheduleId())
×
244
            .setPatch(patch)
×
245
            .build();
×
246
    try {
247
      genericClient.patchSchedule(request);
×
248
    } catch (Exception e) {
×
249
      throw new ScheduleException(e);
×
250
    }
×
251
  }
×
252

253
  @Override
254
  public void unpauseSchedule(UnpauseScheduleInput input) {
255
    SchedulePatch patch = SchedulePatch.newBuilder().setUnpause(input.getNote()).build();
×
256

257
    PatchScheduleRequest request =
258
        PatchScheduleRequest.newBuilder()
×
259
            .setIdentity(clientOptions.getIdentity())
×
260
            .setNamespace(clientOptions.getNamespace())
×
261
            .setScheduleId(input.getScheduleId())
×
262
            .setPatch(patch)
×
263
            .build();
×
264
    try {
265
      genericClient.patchSchedule(request);
×
266
    } catch (Exception e) {
×
267
      throw new ScheduleException(e);
×
268
    }
×
269
  }
×
270

271
  @Override
272
  public void updateSchedule(UpdateScheduleInput input) {
273
    ScheduleUpdate schedule =
×
274
        input.getUpdater().apply(new ScheduleUpdateInput(input.getDescription()));
×
275
    if (schedule == null) {
×
276
      return;
×
277
    }
278

279
    UpdateScheduleRequest request =
280
        UpdateScheduleRequest.newBuilder()
×
281
            .setNamespace(clientOptions.getNamespace())
×
282
            .setIdentity(clientOptions.getIdentity())
×
283
            .setScheduleId(input.getDescription().getId())
×
284
            .setRequestId(UUID.randomUUID().toString())
×
285
            .setSchedule(scheduleRequestHeader.scheduleToProto(schedule.getSchedule()))
×
286
            .build();
×
287
    try {
288
      genericClient.updateSchedule(request);
×
289
    } catch (Exception e) {
×
290
      throw new ScheduleException(e);
×
291
    }
×
292
  }
×
293
}
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

© 2026 Coveralls, Inc