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

temporalio / sdk-java / #294

05 Aug 2024 05:36PM UTC coverage: 77.709% (+0.09%) from 77.618%
#294

push

github

web-flow
Test server Nexus endpoint operator apis (#2162)

* Bump API version to v1.36.0

* Nexus endpoint test server CRUD API implementation

* cleanup

* functional tests

* test operator service external setup

* test environment setup

* test environment setup

* skip functional tests with external server

132 of 138 new or added lines in 4 files covered. (95.65%)

4 existing lines in 2 files now uncovered.

19878 of 25580 relevant lines covered (77.71%)

0.78 hits per line

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

95.29
/temporal-test-server/src/main/java/io/temporal/internal/testservice/TestNexusEndpointStoreImpl.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.testservice;
22

23
import io.grpc.Status;
24
import io.temporal.api.nexus.v1.Endpoint;
25
import io.temporal.api.nexus.v1.EndpointSpec;
26
import java.util.*;
27
import java.util.concurrent.ConcurrentSkipListMap;
28
import java.util.regex.Pattern;
29
import java.util.stream.Collectors;
30

31
/**
32
 * TestNexusEndpointStoreImpl is an in-memory implementation of Nexus endpoint CRUD operations for
33
 * use with the test server. Because conflict resolution is not required, there is no handling for
34
 * created or updated timestamps.
35
 */
36
public class TestNexusEndpointStoreImpl implements TestNexusEndpointStore {
1✔
37

38
  private static final Pattern ENDPOINT_NAME_REGEX = Pattern.compile("^[a-zA-Z_][a-zA-Z0-9_]*$");
1✔
39

40
  private final SortedMap<String, Endpoint> endpoints = new ConcurrentSkipListMap<>();
1✔
41
  private final Set<String> endpointNames = new HashSet<>();
1✔
42

43
  @Override
44
  public Endpoint createEndpoint(EndpointSpec spec) {
45
    validateEndpointSpec(spec);
1✔
46

47
    if (!endpointNames.add(spec.getName())) {
1✔
48
      throw Status.ALREADY_EXISTS
1✔
49
          .withDescription("Nexus endpoint already registered with name: " + spec.getName())
1✔
50
          .asRuntimeException();
1✔
51
    }
52

53
    String id = UUID.randomUUID().toString();
1✔
54
    Endpoint endpoint = Endpoint.newBuilder().setId(id).setVersion(1).setSpec(spec).build();
1✔
55

56
    if (endpoints.putIfAbsent(id, endpoint) != null) {
1✔
57
      // This should never happen in practice
NEW
58
      throw Status.ALREADY_EXISTS
×
NEW
59
          .withDescription("Nexus endpoint already exists with ID: " + id)
×
NEW
60
          .asRuntimeException();
×
61
    }
62

63
    return endpoint;
1✔
64
  }
65

66
  @Override
67
  public Endpoint updateEndpoint(String id, long version, EndpointSpec spec) {
68
    validateEndpointSpec(spec);
1✔
69

70
    Endpoint prev = endpoints.get(id);
1✔
71

72
    if (prev == null) {
1✔
73
      throw Status.NOT_FOUND
1✔
74
          .withDescription("Could not find Nexus endpoint with ID: " + id)
1✔
75
          .asRuntimeException();
1✔
76
    }
77

78
    if (prev.getVersion() != version) {
1✔
79
      throw Status.INVALID_ARGUMENT
1✔
80
          .withDescription(
1✔
81
              "Error updating Nexus endpoint: version mismatch."
82
                  + " Expected: "
83
                  + prev.getVersion()
1✔
84
                  + " Received: "
85
                  + version)
86
          .asRuntimeException();
1✔
87
    }
88

89
    if (!prev.getSpec().getName().equals(spec.getName()) && !endpointNames.add(spec.getName())) {
1✔
90
      throw Status.ALREADY_EXISTS
1✔
91
          .withDescription(
1✔
92
              "Error updating Nexus endpoint: "
93
                  + "endpoint already registered with updated name: "
94
                  + spec.getName())
1✔
95
          .asRuntimeException();
1✔
96
    } else {
97
      endpointNames.remove(prev.getSpec().getName());
1✔
98
    }
99

100
    Endpoint updated = Endpoint.newBuilder(prev).setVersion(version + 1).setSpec(spec).build();
1✔
101

102
    endpoints.put(id, updated);
1✔
103
    return updated;
1✔
104
  }
105

106
  @Override
107
  public void deleteEndpoint(String id, long version) {
108
    Endpoint existing = endpoints.get(id);
1✔
109

110
    if (existing == null) {
1✔
111
      throw Status.NOT_FOUND
1✔
112
          .withDescription("Could not find Nexus endpoint with ID: " + id)
1✔
113
          .asRuntimeException();
1✔
114
    }
115

116
    if (existing.getVersion() != version) {
1✔
117
      throw Status.INVALID_ARGUMENT
1✔
118
          .withDescription(
1✔
119
              "Error deleting Nexus endpoint: version mismatch."
120
                  + " Expected "
121
                  + existing.getVersion()
1✔
122
                  + " Received: "
123
                  + version)
124
          .asRuntimeException();
1✔
125
    }
126

127
    endpoints.remove(id);
1✔
128
  }
1✔
129

130
  @Override
131
  public Endpoint getEndpoint(String id) {
132
    Endpoint endpoint = endpoints.get(id);
1✔
133
    if (endpoint == null) {
1✔
134
      throw Status.NOT_FOUND
1✔
135
          .withDescription("Could not find Nexus endpoint with ID: " + id)
1✔
136
          .asRuntimeException();
1✔
137
    }
138
    return endpoint;
1✔
139
  }
140

141
  @Override
142
  public List<Endpoint> listEndpoints(long pageSize, byte[] nextPageToken, String name) {
143
    if (name != null && !name.isEmpty()) {
1✔
144
      return endpoints.values().stream()
1✔
145
          .filter(ep -> ep.getSpec().getName().equals(name))
1✔
146
          .limit(1)
1✔
147
          .collect(Collectors.toList());
1✔
148
    }
149

150
    if (nextPageToken.length > 0) {
1✔
151
      return endpoints.tailMap(new String(nextPageToken)).values().stream()
1✔
152
          .skip(1)
1✔
153
          .limit(pageSize)
1✔
154
          .collect(Collectors.toList());
1✔
155
    }
156
    return endpoints.values().stream().limit(pageSize).collect(Collectors.toList());
1✔
157
  }
158

159
  @Override
160
  public void validateEndpointSpec(EndpointSpec spec) {
161
    if (spec.getName().isEmpty()) {
1✔
162
      throw Status.INVALID_ARGUMENT
1✔
163
          .withDescription("Nexus endpoint name cannot be empty")
1✔
164
          .asRuntimeException();
1✔
165
    }
166
    if (!ENDPOINT_NAME_REGEX.matcher(spec.getName()).matches()) {
1✔
167
      throw Status.INVALID_ARGUMENT
1✔
168
          .withDescription(
1✔
169
              "Nexus endpoint name ("
170
                  + spec.getName()
1✔
171
                  + ") does not match expected pattern: "
172
                  + ENDPOINT_NAME_REGEX.pattern())
1✔
173
          .asRuntimeException();
1✔
174
    }
175
    if (!spec.hasTarget()) {
1✔
176
      throw Status.INVALID_ARGUMENT
1✔
177
          .withDescription("Nexus endpoint spec must have a target")
1✔
178
          .asRuntimeException();
1✔
179
    }
180
    if (!spec.getTarget().hasWorker()) {
1✔
181
      throw Status.INVALID_ARGUMENT
1✔
182
          .withDescription("Test server only supports Nexus endpoints with worker targets")
1✔
183
          .asRuntimeException();
1✔
184
    }
185
  }
1✔
186

187
  @Override
NEW
188
  public void close() {}
×
189
}
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