1 // Copyright 2020 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_PUBSUB_SUBSCRIPTION_ADMIN_CLIENT_H
16 #define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_PUBSUB_SUBSCRIPTION_ADMIN_CLIENT_H
17 
18 #include "google/cloud/pubsub/snapshot_mutation_builder.h"
19 #include "google/cloud/pubsub/subscription_admin_connection.h"
20 #include "google/cloud/pubsub/subscription_mutation_builder.h"
21 #include "google/cloud/pubsub/version.h"
22 #include <memory>
23 
24 namespace google {
25 namespace cloud {
26 namespace pubsub {
27 inline namespace GOOGLE_CLOUD_CPP_PUBSUB_NS {
28 
29 /**
30  * Performs subscription administrative operations in Cloud Pub/Sub.
31  *
32  * Applications use this class to perform subscription administrative operations
33  * on [Cloud Pub/Sub][pubsub-doc-link].
34  *
35  * @par Performance
36  *
37  * `SubscriptionAdminClient` objects are relatively cheap to create, copy, and
38  * move. However, each `SubscriptionAdminClient` object must be created with a
39  * `std::shared_ptr<SubscriptionAdminConnection>`, which itself is relatively
40  * expensive to create. Therefore, connection instances should be shared when
41  * possible. See the `MakeSubscriptionAdminConnection()` function and the
42  * `SubscriptionAdminConnection` interface for more details.
43  *
44  * @par Thread Safety
45  *
46  * Instances of this class created via copy-construction or copy-assignment
47  * share the underlying pool of connections. Access to these copies via multiple
48  * threads is guaranteed to work. Two threads operating on the same instance of
49  * this class is not guaranteed to work.
50  *
51  * @par Error Handling
52  *
53  * This class uses `StatusOr<T>` to report errors. When an operation fails to
54  * perform its work the returned `StatusOr<T>` contains the error details. If
55  * the `ok()` member function in the `StatusOr<T>` returns `true` then it
56  * contains the expected result. Please consult the
57  * [`StatusOr<T>` documentation](#google::cloud::v1::StatusOr) for more details.
58  *
59  * [pubsub-doc-link]: https://cloud.google.com/pubsub/docs
60  */
61 class SubscriptionAdminClient {
62  public:
63   explicit SubscriptionAdminClient(
64       std::shared_ptr<SubscriptionAdminConnection> connection);
65 
66   /**
67    * The default constructor is deleted.
68    *
69    * Use `SubscriberClient(std::shared_ptr<SubscriberConnection>)`
70    */
71   SubscriptionAdminClient() = delete;
72 
73   /**
74    * Create a new subscription in Cloud Pub/Sub.
75    *
76    * @par Idempotency
77    * This operation is idempotent, the state of the system is the same after one
78    * or several calls, and therefore it is always retried.
79    *
80    * @par Example: Create a Pull Subscription
81    * @snippet samples.cc create-subscription
82    *
83    * @par Example: Create a Push Subscription
84    * @snippet samples.cc create-push-subscription
85    *
86    * @param topic the topic that the subscription will attach to
87    * @param subscription the name for the subscription
88    * @param builder any additional configuration for the subscription
89    */
90   StatusOr<google::pubsub::v1::Subscription> CreateSubscription(
91       Topic const& topic, Subscription const& subscription,
92       SubscriptionMutationBuilder builder = {}) {
93     return connection_->CreateSubscription(
94         {std::move(builder).BuildCreateSubscription(topic, subscription)});
95   }
96 
97   /**
98    * Get the metadata for an existing Cloud Pub/Sub subscription.
99    *
100    * @par Idempotency
101    * This is a read-only operation and therefore always idempotent and retried.
102    *
103    * @par Example
104    * @snippet samples.cc get-subscription
105    */
GetSubscription(Subscription subscription)106   StatusOr<google::pubsub::v1::Subscription> GetSubscription(
107       Subscription subscription) {
108     return connection_->GetSubscription({std::move(subscription)});
109   }
110 
111   /**
112    * Update an existing subscription in Cloud Pub/Sub.
113    *
114    * @par Idempotency
115    * This operation is idempotent, the state of the system is the same after one
116    * or several calls, and therefore it is always retried.
117    *
118    * @par Example
119    * @snippet samples.cc update-subscription
120    *
121    * @param subscription the name for the subscription
122    * @param builder any additional configuration for the subscription
123    */
UpdateSubscription(Subscription const & subscription,SubscriptionMutationBuilder builder)124   StatusOr<google::pubsub::v1::Subscription> UpdateSubscription(
125       Subscription const& subscription, SubscriptionMutationBuilder builder) {
126     return connection_->UpdateSubscription(
127         {std::move(builder).BuildUpdateSubscription(subscription)});
128   }
129 
130   /**
131    * List all the subscriptions for a given project id.
132    *
133    * @par Idempotency
134    * This is a read-only operation and therefore always idempotent and retried.
135    *
136    * @par Example
137    * @snippet samples.cc list-subscriptions
138    */
ListSubscriptions(std::string const & project_id)139   ListSubscriptionsRange ListSubscriptions(std::string const& project_id) {
140     return connection_->ListSubscriptions({"projects/" + project_id});
141   }
142 
143   /**
144    * Delete an existing subscription in Cloud Pub/Sub.
145    *
146    * @par Idempotency
147    * This operation is idempotent, the state of the system is the same after one
148    * or several calls, and therefore it is always retried.
149    *
150    * @par Example
151    * @snippet samples.cc delete-subscription
152    *
153    * @param subscription the name of the subscription to be deleted.
154    */
DeleteSubscription(Subscription subscription)155   Status DeleteSubscription(Subscription subscription) {
156     return connection_->DeleteSubscription({std::move(subscription)});
157   }
158 
159   /**
160    * Modifies an existing subscription's push configuration.
161    *
162    * This can change a push subscription into a pull subscription (by setting
163    * an empty push config), change the push endpoint, or change a pull
164    * subscription into a push config.
165    *
166    * @par Idempotency
167    * This operation is idempotent, the state of the system is the same after one
168    * or several calls, and therefore it is always retried.
169    *
170    * @par Example
171    * @snippet samples.cc modify-push-config
172    *
173    * @param subscription the name of the subscription to be modified.
174    * @param builder a description of the changes to be made.
175    */
ModifyPushSubscription(Subscription const & subscription,PushConfigBuilder builder)176   Status ModifyPushSubscription(Subscription const& subscription,
177                                 PushConfigBuilder builder) {
178     return connection_->ModifyPushConfig(
179         {std::move(builder).BuildModifyPushConfig(subscription)});
180   }
181 
182   /**
183    * Create a new snapshot for a subscription with a server-assigned name.
184    *
185    * @par Idempotency
186    * This is not an idempotent operation, repeated calls would create multiple
187    * snapshots with different names assigned by the service, and therefore
188    * it is never retried.
189    *
190    * @param subscription the name of the subscription
191    * @param builder additional configuration for the snapshot, e.g., labels
192    */
193   // TODO(#4792) - add missing example once it is testable
194   StatusOr<google::pubsub::v1::Snapshot> CreateSnapshot(
195       Subscription const& subscription, SnapshotMutationBuilder builder = {}) {
196     return connection_->CreateSnapshot(
197         {std::move(builder).BuildCreateMutation(subscription)});
198   }
199 
200   /**
201    * Create a new snapshot for a subscription with a given name.
202    *
203    * @par Idempotency
204    * This operation is idempotent, the state of the system is the same after one
205    * or several calls, and therefore it is always retried.
206    *
207    * @par Example
208    * @snippet samples.cc create-snapshot-with-name
209    *
210    * @param subscription the name of the subscription
211    * @param snapshot the name of the snapshot
212    * @param builder additional configuration for the snapshot, e.g., labels
213    */
214   StatusOr<google::pubsub::v1::Snapshot> CreateSnapshot(
215       Subscription const& subscription, Snapshot const& snapshot,
216       SnapshotMutationBuilder builder = {}) {
217     return connection_->CreateSnapshot(
218         {std::move(builder).BuildCreateMutation(subscription, snapshot)});
219   }
220 
221   /**
222    * Get information about an existing snapshot.
223    *
224    * @par Idempotency
225    * This is a read-only operation and therefore always idempotent and retried.
226    *
227    * @par Example
228    * @snippet samples.cc get-snapshot
229    *
230    * @param snapshot the name of the snapshot
231    */
GetSnapshot(Snapshot const & snapshot)232   StatusOr<google::pubsub::v1::Snapshot> GetSnapshot(Snapshot const& snapshot) {
233     return connection_->GetSnapshot({snapshot});
234   }
235 
236   /**
237    * Update an existing snapshot.
238    *
239    * @par Idempotency
240    * This operation is idempotent, the state of the system is the same after one
241    * or several calls, and therefore it is always retried.
242    *
243    * @par Example
244    * @snippet samples.cc update-snapshot
245    *
246    * @param snapshot the name of the snapshot
247    * @param builder the changes applied to the snapshot
248    */
UpdateSnapshot(Snapshot const & snapshot,SnapshotMutationBuilder builder)249   StatusOr<google::pubsub::v1::Snapshot> UpdateSnapshot(
250       Snapshot const& snapshot, SnapshotMutationBuilder builder) {
251     return connection_->UpdateSnapshot(
252         {std::move(builder).BuildUpdateMutation(snapshot)});
253   }
254 
255   /**
256    * List all the snapshots for a given project id.
257    *
258    * @par Idempotency
259    * This is a read-only operation and therefore always idempotent and retried.
260    *
261    * @par Example
262    * @snippet samples.cc list-snapshots
263    */
ListSnapshots(std::string const & project_id)264   ListSnapshotsRange ListSnapshots(std::string const& project_id) {
265     return connection_->ListSnapshots({"projects/" + project_id});
266   }
267 
268   /**
269    * Delete a snapshot.
270    *
271    * @par Idempotency
272    * This operation is idempotent, the state of the system is the same after one
273    * or several calls, and therefore it is always retried.
274    *
275    * @par Example
276    * @snippet samples.cc create-snapshot-with-name
277    *
278    * @param snapshot the name of the snapshot
279    */
DeleteSnapshot(Snapshot const & snapshot)280   Status DeleteSnapshot(Snapshot const& snapshot) {
281     return connection_->DeleteSnapshot({snapshot});
282   }
283 
284   /**
285    * Seeks a subscription to @p timestamp.
286    *
287    * Messages retained in the subscription that were published before
288    * @p timestamp are marked as acknowledged, while messages published after
289    * @p timestamp are marked as unacknowledged.
290    *
291    * @par Idempotency
292    * This operation is idempotent, the state of the system is the same after one
293    * or several calls, and therefore it is always retried.
294    *
295    * @par Example
296    * @snippet samples.cc seek-with-timestamp
297    *
298    * @see https://cloud.google.com/pubsub/docs/replay-overview for a detailed
299    *     description of Cloud Pub/Sub's `Seek()` functionality.
300    */
301   StatusOr<google::pubsub::v1::SeekResponse> Seek(
302       Subscription const& subscription,
303       std::chrono::system_clock::time_point timestamp);
304 
305   /**
306    * Seeks a subscription to @p snapshot.
307    *
308    * @par Idempotency
309    * This operation is idempotent, the state of the system is the same after one
310    * or several calls, and therefore it is always retried.
311    *
312    * @par Example
313    * @snippet samples.cc seek-with-timestamp
314    *
315    * @see https://cloud.google.com/pubsub/docs/replay-overview for a detailed
316    *     description of Cloud Pub/Sub's `Seek()` functionality.
317    */
318   StatusOr<google::pubsub::v1::SeekResponse> Seek(
319       Subscription const& subscription, Snapshot const& snapshot);
320 
321  private:
322   std::shared_ptr<SubscriptionAdminConnection> connection_;
323 };
324 
325 }  // namespace GOOGLE_CLOUD_CPP_PUBSUB_NS
326 }  // namespace pubsub
327 }  // namespace cloud
328 }  // namespace google
329 
330 #endif  // GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_PUBSUB_SUBSCRIPTION_ADMIN_CLIENT_H
331