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

temporalio / sdk-java / #185

28 Aug 2023 02:02PM CUT coverage: 77.642% (-0.04%) from 77.685%
#185

push

github-actions

web-flow
Reconcile typed search attributes with schedules (#1848)

Reconcile typed search attributes with schedules

30 of 30 new or added lines in 6 files covered. (100.0%)

18579 of 23929 relevant lines covered (77.64%)

0.78 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
        patchBuilder.setTriggerImmediately(
×
102
            TriggerImmediatelyRequest.newBuilder()
×
103
                .setOverlapPolicy(input.getSchedule().getPolicy().getOverlap())
×
104
                .build());
×
105
      }
106

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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