Skip to content

Commit 79bb58c

Browse files
feat: Add reservation support. (#661)
* feat: Add reservation support. This feature is not be supported in the backend yet. When it is, the BetaApi annotation will be removed. * feat: Add reservation support. This feature is not be supported in the backend yet. When it is, the BetaApi annotation will be removed.
1 parent 06573d1 commit 79bb58c

File tree

13 files changed

+779
-125
lines changed

13 files changed

+779
-125
lines changed

google-cloud-pubsublite/clirr-ignored-differences.xml

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,30 @@
33
<differences>
44
<!-- TODO: Remove on next release -->
55
<difference>
6-
<differenceType>8001</differenceType>
7-
<className>com/google/cloud/pubsublite/PublishMetadata</className>
6+
<differenceType>7006</differenceType>
7+
<className>com/google/cloud/pubsublite/LocationPath</className>
88
<method>*</method>
9+
<to>*</to>
910
</difference>
1011
<difference>
1112
<differenceType>7012</differenceType>
1213
<className>com/google/cloud/pubsublite/AdminClient</className>
1314
<method>*</method>
1415
</difference>
16+
<difference>
17+
<!-- This one is actually a clirr bug: It doesn't handle CRTP well. -->
18+
<differenceType>7006</differenceType>
19+
<className>com/google/cloud/pubsublite/LocationPath$Builder</className>
20+
<method>*</method>
21+
<to>*</to>
22+
</difference>
23+
<difference>
24+
<!-- This one is actually a clirr bug: It doesn't handle CRTP well. -->
25+
<differenceType>7002</differenceType>
26+
<className>com/google/cloud/pubsublite/LocationPath$Builder</className>
27+
<method>*</method>
28+
</difference>
29+
<!-- END TODO: Remove on next release -->
1530
<!-- Added abstract method to AutoValue.Builder class (Always okay) -->
1631
<difference>
1732
<differenceType>7013</differenceType>

google-cloud-pubsublite/src/main/java/com/google/cloud/pubsublite/AdminClient.java

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@
1717
package com.google.cloud.pubsublite;
1818

1919
import com.google.api.core.ApiFuture;
20+
import com.google.api.core.BetaApi;
2021
import com.google.api.gax.rpc.ApiException;
2122
import com.google.cloud.pubsublite.internal.ApiBackgroundResource;
23+
import com.google.cloud.pubsublite.proto.Reservation;
2224
import com.google.cloud.pubsublite.proto.Subscription;
2325
import com.google.cloud.pubsublite.proto.Topic;
2426
import com.google.protobuf.FieldMask;
@@ -174,4 +176,68 @@ ApiFuture<Subscription> createSubscription(
174176
* exception with status {@link com.google.api.gax.rpc.StatusCode.Code#NOT_FOUND}
175177
*/
176178
ApiFuture<Void> deleteSubscription(SubscriptionPath path);
179+
180+
/**
181+
* Create the provided reservation if it does not yet exist.
182+
*
183+
* @param reservation The reservation to create.
184+
* @return A future that will have either an error {@link com.google.api.gax.rpc.ApiException} or
185+
* the reservation on success.
186+
*/
187+
@BetaApi("This may not be implemented in the backend, it is a pre-release feature.")
188+
ApiFuture<Reservation> createReservation(Reservation reservation);
189+
190+
/**
191+
* Get the reservation with id {@code id} if it exists.
192+
*
193+
* @param path The path of the reservation to retrieve.
194+
* @return A future that will have either an error {@link com.google.api.gax.rpc.ApiException} or
195+
* the reservation on success.
196+
*/
197+
@BetaApi("This may not be implemented in the backend, it is a pre-release feature.")
198+
ApiFuture<Reservation> getReservation(ReservationPath path);
199+
200+
/**
201+
* List all reservations for the specified project.
202+
*
203+
* @param path The path of the project to list reservations for.
204+
* @return A future that will have either an error {@link com.google.api.gax.rpc.ApiException} or
205+
* the list of reservation paths on success.
206+
*/
207+
@BetaApi("This may not be implemented in the backend, it is a pre-release feature.")
208+
ApiFuture<List<Reservation>> listReservations(LocationPath path);
209+
210+
/**
211+
* Update the reservation with path {@code reservation.getPath()} if it exists.
212+
*
213+
* @param reservation The reservation to update.
214+
* @param mask The mask indicating which fields should be updated.
215+
* @return A future that will have either an error {@link com.google.api.gax.rpc.ApiException} or
216+
* the resulting reservation on success. Updating nonexistent reservations will cause the
217+
* future to have an exception with status {@link
218+
* com.google.api.gax.rpc.StatusCode.Code#NOT_FOUND}
219+
*/
220+
@BetaApi("This may not be implemented in the backend, it is a pre-release feature.")
221+
ApiFuture<Reservation> updateReservation(Reservation reservation, FieldMask mask);
222+
223+
/**
224+
* Delete the reservation with id {@code id} if it exists.
225+
*
226+
* @param path The path of the reservation to retrieve.
227+
* @return A future that will have either an error {@link com.google.api.gax.rpc.ApiException} or
228+
* void on success. Deleting nonexistent reservations will cause the future to have an
229+
* exception with status {@link com.google.api.gax.rpc.StatusCode.Code#NOT_FOUND}
230+
*/
231+
@BetaApi("This may not be implemented in the backend, it is a pre-release feature.")
232+
ApiFuture<Void> deleteReservation(ReservationPath path);
233+
234+
/**
235+
* Get the list of topics for the reservation with id {@code id} if it exists.
236+
*
237+
* @param path The path of the reservation to retrieve.
238+
* @return A future that will have either an error {@link com.google.api.gax.rpc.ApiException} or
239+
* the list of topics on success.
240+
*/
241+
@BetaApi("This may not be implemented in the backend, it is a pre-release feature.")
242+
ApiFuture<List<TopicPath>> listReservationTopics(ReservationPath path);
177243
}

google-cloud-pubsublite/src/main/java/com/google/cloud/pubsublite/CloudRegion.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@
1616

1717
package com.google.cloud.pubsublite;
1818

19+
import com.google.api.gax.rpc.ApiException;
20+
import com.google.api.gax.rpc.StatusCode.Code;
1921
import com.google.auto.value.AutoValue;
22+
import com.google.cloud.pubsublite.internal.CheckedApiException;
2023
import java.io.Serializable;
2124

2225
/** A wrapped string representing a Google Cloud region. */
@@ -25,10 +28,21 @@ public abstract class CloudRegion implements Serializable {
2528
private static final long serialVersionUID = 6814654654L;
2629

2730
/** Construct a CloudRegion from a string. */
28-
public static CloudRegion of(String value) {
31+
public static CloudRegion of(String value) throws ApiException {
32+
String[] splits = value.split("-", -1);
33+
if (splits.length != 2) {
34+
throw new CheckedApiException("Invalid region name: " + value, Code.INVALID_ARGUMENT)
35+
.underlying;
36+
}
2937
return new AutoValue_CloudRegion(value);
3038
}
3139

3240
/** The string representing this region. */
3341
public abstract String value();
42+
43+
/** {@inheritDoc} */
44+
@Override
45+
public String toString() {
46+
return value();
47+
}
3448
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* Copyright 2020 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.cloud.pubsublite;
18+
19+
import com.google.api.gax.rpc.ApiException;
20+
import com.google.auto.value.AutoOneOf;
21+
import java.io.Serializable;
22+
23+
@AutoOneOf(CloudRegionOrZone.Kind.class)
24+
public abstract class CloudRegionOrZone implements Serializable {
25+
enum Kind {
26+
REGION,
27+
ZONE
28+
}
29+
30+
public abstract Kind getKind();
31+
32+
public abstract CloudRegion region();
33+
34+
public abstract CloudZone zone();
35+
36+
/** Extract the region from this regardless of which case is set. */
37+
public CloudRegion extractRegion() {
38+
switch (getKind()) {
39+
case REGION:
40+
return region();
41+
case ZONE:
42+
return zone().region();
43+
default:
44+
throw new RuntimeException("Unknown case for CloudRegionOrZone.");
45+
}
46+
}
47+
48+
public static CloudRegionOrZone of(CloudRegion region) {
49+
return AutoOneOf_CloudRegionOrZone.region(region);
50+
}
51+
52+
public static CloudRegionOrZone of(CloudZone zone) {
53+
return AutoOneOf_CloudRegionOrZone.zone(zone);
54+
}
55+
56+
public static CloudRegionOrZone parse(String value) throws ApiException {
57+
try {
58+
return of(CloudZone.parse(value));
59+
} catch (ApiException e) {
60+
// pass
61+
}
62+
return of(CloudRegion.of(value));
63+
}
64+
65+
/** {@inheritDoc} */
66+
@Override
67+
public String toString() {
68+
switch (getKind()) {
69+
case REGION:
70+
return region().toString();
71+
case ZONE:
72+
return zone().toString();
73+
default:
74+
throw new RuntimeException("Unknown case for CloudRegionOrZone.");
75+
}
76+
}
77+
}

google-cloud-pubsublite/src/main/java/com/google/cloud/pubsublite/LocationPath.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
public abstract class LocationPath implements Serializable {
2929
public abstract ProjectIdOrNumber project();
3030

31-
public abstract CloudZone location();
31+
public abstract CloudRegionOrZone location();
3232

3333
public ProjectPath projectPath() {
3434
return ProjectPath.newBuilder().setProject(project()).build();
@@ -47,9 +47,7 @@ public static Builder newBuilder() {
4747
public abstract Builder toBuilder();
4848

4949
@AutoValue.Builder
50-
public abstract static class Builder extends ProjectBuilderHelper<Builder> {
51-
public abstract Builder setLocation(CloudZone zone);
52-
50+
public abstract static class Builder extends ProjectLocationBuilderHelper<Builder> {
5351
public abstract LocationPath build();
5452
}
5553

@@ -65,7 +63,7 @@ public static LocationPath parse(String path) throws ApiException {
6563
ProjectPath project = ProjectPath.parse(String.join("/", Arrays.copyOf(splits, 2)));
6664
return LocationPath.newBuilder()
6765
.setProject(project.project())
68-
.setLocation(CloudZone.parse(splits[3]))
66+
.setLocation(CloudRegionOrZone.parse(splits[3]))
6967
.build();
7068
}
7169
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright 2020 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.cloud.pubsublite;
18+
19+
abstract class ProjectLocationBuilderHelper<Builder extends ProjectLocationBuilderHelper<Builder>>
20+
extends ProjectBuilderHelper<Builder> {
21+
public abstract Builder setLocation(CloudRegionOrZone location);
22+
23+
public Builder setLocation(CloudRegion region) {
24+
return setLocation(CloudRegionOrZone.of(region));
25+
}
26+
27+
public Builder setLocation(CloudZone zone) {
28+
return setLocation(CloudRegionOrZone.of(zone));
29+
}
30+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
* Copyright 2020 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.cloud.pubsublite;
18+
19+
import static com.google.cloud.pubsublite.internal.UncheckedApiPreconditions.checkArgument;
20+
21+
import com.google.api.gax.rpc.ApiException;
22+
import com.google.auto.value.AutoValue;
23+
import java.io.Serializable;
24+
25+
/** A string wrapper for the name of a reservation. */
26+
@AutoValue
27+
public abstract class ReservationName implements Serializable {
28+
public abstract String value();
29+
30+
@Override
31+
public String toString() {
32+
return value();
33+
}
34+
35+
public static ReservationName of(String value) throws ApiException {
36+
checkArgument(!value.isEmpty());
37+
return new AutoValue_ReservationName(value);
38+
}
39+
}

0 commit comments

Comments
 (0)