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

temporalio / sdk-java / #174

pending completion
#174

push

github-actions

web-flow
Add schedules API (#1776)

Add schedules API

1143 of 1143 new or added lines in 35 files covered. (100.0%)

18101 of 23284 relevant lines covered (77.74%)

0.78 hits per line

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

0.0
/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);
×
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) {
×
53
    this.genericClient = genericClient;
×
54
    this.clientOptions = clientOptions;
×
55
    this.scheduleRequestHeader = new ScheduleProtoUtil(genericClient, clientOptions);
×
56
  }
×
57

58
  @Override
59
  public void createSchedule(CreateScheduleInput input) {
60

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

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

76
    if (input.getOptions().getSearchAttributes() != null
×
77
        && !input.getOptions().getSearchAttributes().isEmpty()) {
×
78
      request.setSearchAttributes(
×
79
          SearchAttributesUtil.encode(input.getOptions().getSearchAttributes()));
×
80
    }
81

82
    if (input.getOptions().isTriggerImmediately()
×
83
        || (input.getOptions().getBackfills() != null
×
84
            && input.getOptions().getBackfills().size() > 0)) {
×
85
      SchedulePatch.Builder patchBuilder = SchedulePatch.newBuilder();
×
86

87
      if (input.getOptions().getBackfills() != null) {
×
88
        input.getOptions().getBackfills().stream()
×
89
            .forEach(b -> patchBuilder.addBackfillRequest(backfillToProto(b)));
×
90
      }
91

92
      if (input.getOptions().isTriggerImmediately()) {
×
93
        patchBuilder.setTriggerImmediately(
×
94
            TriggerImmediatelyRequest.newBuilder()
×
95
                .setOverlapPolicy(input.getSchedule().getPolicy().getOverlap())
×
96
                .build());
×
97
      }
98

99
      request.setInitialPatch(patchBuilder.build());
×
100
    }
101

102
    try {
103
      genericClient.createSchedule(request.build());
×
104
    } catch (Exception e) {
×
105
      if (e instanceof StatusRuntimeException) {
×
106
        StatusRuntimeException sre = (StatusRuntimeException) e;
×
107
        if (Status.Code.ALREADY_EXISTS.equals(sre.getStatus().getCode())) {
×
108
          throw new ScheduleAlreadyRunningException(sre);
×
109
        }
110
      }
111
    }
×
112
  }
×
113

114
  @Override
115
  public ListScheduleOutput listSchedules(ListSchedulesInput input) {
116
    ListScheduleListDescriptionIterator iterator =
×
117
        new ListScheduleListDescriptionIterator(
118
            clientOptions.getNamespace(), input.getPageSize(), genericClient);
×
119
    iterator.init();
×
120
    Iterator<ScheduleListDescription> wrappedIterator =
×
121
        Iterators.transform(
×
122
            iterator, entry -> scheduleRequestHeader.protoToScheduleListDescription(entry));
×
123

124
    final int CHARACTERISTICS =
×
125
        Spliterator.ORDERED | Spliterator.DISTINCT | Spliterator.NONNULL | Spliterator.IMMUTABLE;
126
    return new ListScheduleOutput(
×
127
        StreamSupport.stream(
×
128
            Spliterators.spliteratorUnknownSize(wrappedIterator, CHARACTERISTICS), false));
×
129
  }
130

131
  public BackfillRequest backfillToProto(ScheduleBackfill backfill) {
132
    return BackfillRequest.newBuilder()
×
133
        .setStartTime(ProtobufTimeUtils.toProtoTimestamp(backfill.getStartAt()))
×
134
        .setEndTime(ProtobufTimeUtils.toProtoTimestamp(backfill.getEndAt()))
×
135
        .setOverlapPolicy(backfill.getOverlapPolicy())
×
136
        .build();
×
137
  }
138

139
  @Override
140
  public void backfillSchedule(BackfillScheduleInput input) {
141
    ArrayList<BackfillRequest> backfillRequests =
×
142
        new ArrayList<BackfillRequest>(input.getBackfills().size());
×
143
    for (ScheduleBackfill backfill : input.getBackfills()) {
×
144
      backfillRequests.add(backfillToProto(backfill));
×
145
    }
×
146

147
    SchedulePatch patch =
148
        SchedulePatch.newBuilder().addAllBackfillRequest(backfillRequests).build();
×
149

150
    PatchScheduleRequest request =
151
        PatchScheduleRequest.newBuilder()
×
152
            .setIdentity(clientOptions.getIdentity())
×
153
            .setNamespace(clientOptions.getNamespace())
×
154
            .setScheduleId(input.getScheduleId())
×
155
            .setPatch(patch)
×
156
            .build();
×
157
    genericClient.patchSchedule(request);
×
158
  }
×
159

160
  @Override
161
  public void deleteSchedule(DeleteScheduleInput input) {
162
    DeleteScheduleRequest request =
163
        DeleteScheduleRequest.newBuilder()
×
164
            .setIdentity(clientOptions.getIdentity())
×
165
            .setNamespace(clientOptions.getNamespace())
×
166
            .setScheduleId(input.getScheduleId())
×
167
            .build();
×
168
    genericClient.deleteSchedule(request);
×
169
  }
×
170

171
  @Override
172
  public DescribeScheduleOutput describeSchedule(DescribeScheduleInput input) {
173
    DescribeScheduleRequest request =
174
        DescribeScheduleRequest.newBuilder()
×
175
            .setNamespace(clientOptions.getNamespace())
×
176
            .setScheduleId(input.getScheduleId())
×
177
            .build();
×
178

179
    DescribeScheduleResponse response = genericClient.describeSchedule(request);
×
180
    return new DescribeScheduleOutput(
×
181
        new ScheduleDescription(
182
            input.getScheduleId(),
×
183
            scheduleRequestHeader.protoToScheduleInfo(response.getInfo()),
×
184
            scheduleRequestHeader.protoToSchedule(response.getSchedule()),
×
185
            Collections.unmodifiableMap(
×
186
                SearchAttributesUtil.decode(response.getSearchAttributes())),
×
187
            response.getMemo().getFieldsMap(),
×
188
            clientOptions.getDataConverter()));
×
189
  }
190

191
  @Override
192
  public void pauseSchedule(PauseScheduleInput input) {
193
    SchedulePatch patch = SchedulePatch.newBuilder().setPause(input.getNote()).build();
×
194

195
    PatchScheduleRequest request =
196
        PatchScheduleRequest.newBuilder()
×
197
            .setIdentity(clientOptions.getIdentity())
×
198
            .setNamespace(clientOptions.getNamespace())
×
199
            .setScheduleId(input.getScheduleId())
×
200
            .setPatch(patch)
×
201
            .build();
×
202

203
    genericClient.patchSchedule(request);
×
204
  }
×
205

206
  @Override
207
  public void triggerSchedule(TriggerScheduleInput input) {
208
    TriggerImmediatelyRequest trigger =
209
        TriggerImmediatelyRequest.newBuilder().setOverlapPolicy(input.getOverlapPolicy()).build();
×
210

211
    SchedulePatch patch = SchedulePatch.newBuilder().setTriggerImmediately(trigger).build();
×
212

213
    PatchScheduleRequest request =
214
        PatchScheduleRequest.newBuilder()
×
215
            .setIdentity(clientOptions.getIdentity())
×
216
            .setNamespace(clientOptions.getNamespace())
×
217
            .setScheduleId(input.getScheduleId())
×
218
            .setPatch(patch)
×
219
            .build();
×
220
    genericClient.patchSchedule(request);
×
221
  }
×
222

223
  @Override
224
  public void unpauseSchedule(UnpauseScheduleInput input) {
225
    SchedulePatch patch = SchedulePatch.newBuilder().setUnpause(input.getNote()).build();
×
226

227
    PatchScheduleRequest request =
228
        PatchScheduleRequest.newBuilder()
×
229
            .setIdentity(clientOptions.getIdentity())
×
230
            .setNamespace(clientOptions.getNamespace())
×
231
            .setScheduleId(input.getScheduleId())
×
232
            .setPatch(patch)
×
233
            .build();
×
234
    genericClient.patchSchedule(request);
×
235
  }
×
236

237
  @Override
238
  public void updateSchedule(UpdateScheduleInput input) {
239
    ScheduleUpdate schedule =
×
240
        input.getUpdater().apply(new ScheduleUpdateInput(input.getDescription()));
×
241
    if (schedule == null) {
×
242
      return;
×
243
    }
244

245
    UpdateScheduleRequest request =
246
        UpdateScheduleRequest.newBuilder()
×
247
            .setNamespace(clientOptions.getNamespace())
×
248
            .setIdentity(clientOptions.getIdentity())
×
249
            .setScheduleId(input.getDescription().getId())
×
250
            .setRequestId(UUID.randomUUID().toString())
×
251
            .setSchedule(scheduleRequestHeader.scheduleToProto(schedule.getSchedule()))
×
252
            .build();
×
253
    genericClient.updateSchedule(request);
×
254
  }
×
255
}
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