Skip to content

Commit 8859070

Browse files
authored
doc(pubsub): add CloudStorageConfigBuilder for samples (#11894)
1 parent 54bbb79 commit 8859070

File tree

3 files changed

+209
-0
lines changed

3 files changed

+209
-0
lines changed

google/cloud/pubsub/subscription_builder.cc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,20 @@ SubscriptionBuilder& SubscriptionBuilder::set_bigquery_config(
7777
return *this;
7878
}
7979

80+
SubscriptionBuilder& SubscriptionBuilder::set_cloud_storage_config(
81+
CloudStorageConfigBuilder v) & {
82+
if (v.paths_.empty()) {
83+
proto_.clear_cloud_storage_config();
84+
paths_.insert("cloud_storage_config");
85+
} else {
86+
*proto_.mutable_cloud_storage_config() = std::move(v.proto_);
87+
for (auto const& s : v.paths_) {
88+
paths_.insert("cloud_storage_config." + s);
89+
}
90+
}
91+
return *this;
92+
}
93+
8094
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
8195
} // namespace pubsub
8296
} // namespace cloud

google/cloud/pubsub/subscription_builder.h

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,110 @@ class BigQueryConfigBuilder {
201201
std::set<std::string> paths_;
202202
};
203203

204+
/**
205+
* A helper class to build `google::pubsub::v1::CloudStorageConfig` protos.
206+
*
207+
* Makes it easier to create the protobuf messages consumed by
208+
* `SubscriptionAdminClient`. The main advantages are:
209+
*
210+
* - Use a fluent API to set multiple values when constructing complex objects.
211+
* - Automatically compute the set of paths for update requests.
212+
*/
213+
class CloudStorageConfigBuilder {
214+
public:
215+
CloudStorageConfigBuilder() = default;
216+
217+
/// @name Setters for each protocol buffer field.
218+
///@{
219+
CloudStorageConfigBuilder& set_bucket(std::string bucket) & {
220+
*proto_.mutable_bucket() = std::move(bucket);
221+
paths_.insert("bucket");
222+
return *this;
223+
}
224+
CloudStorageConfigBuilder&& set_bucket(std::string bucket) && {
225+
return std::move(set_bucket(std::move(bucket)));
226+
}
227+
228+
CloudStorageConfigBuilder& set_filename_prefix(
229+
std::string filename_prefix) & {
230+
*proto_.mutable_filename_prefix() = std::move(filename_prefix);
231+
paths_.insert("filename_prefix");
232+
return *this;
233+
}
234+
CloudStorageConfigBuilder&& set_filename_prefix(
235+
std::string filename_prefix) && {
236+
return std::move(set_filename_prefix(std::move(filename_prefix)));
237+
}
238+
239+
CloudStorageConfigBuilder& set_filename_suffix(
240+
std::string filename_suffix) & {
241+
*proto_.mutable_filename_suffix() = std::move(filename_suffix);
242+
paths_.insert("filename_suffix");
243+
return *this;
244+
}
245+
CloudStorageConfigBuilder&& set_filename_suffix(
246+
std::string filename_suffix) && {
247+
return std::move(set_filename_suffix(std::move(filename_suffix)));
248+
}
249+
250+
static google::pubsub::v1::CloudStorageConfig::AvroConfig MakeAvroConfig(
251+
bool write_metadata) {
252+
google::pubsub::v1::CloudStorageConfig::AvroConfig proto;
253+
proto.set_write_metadata(write_metadata);
254+
return proto;
255+
}
256+
257+
CloudStorageConfigBuilder& set_avro_config(
258+
google::pubsub::v1::CloudStorageConfig::AvroConfig avro_config) & {
259+
*proto_.mutable_avro_config() = std::move(avro_config);
260+
paths_.insert("avro_config");
261+
return *this;
262+
}
263+
CloudStorageConfigBuilder&& set_avro_config(
264+
google::pubsub::v1::CloudStorageConfig::AvroConfig avro_config) && {
265+
return std::move(set_avro_config(std::move(avro_config)));
266+
}
267+
268+
template <typename Rep, typename Period>
269+
CloudStorageConfigBuilder& set_max_duration(
270+
std::chrono::duration<Rep, Period> d) & {
271+
*proto_.mutable_max_duration() =
272+
google::cloud::internal::ToDurationProto(d);
273+
paths_.insert("max_duration");
274+
return *this;
275+
}
276+
template <typename Rep, typename Period>
277+
CloudStorageConfigBuilder&& set_max_duration(
278+
std::chrono::duration<Rep, Period> d) && {
279+
return std::move(set_max_duration(d));
280+
}
281+
CloudStorageConfigBuilder& set_max_duration(
282+
google::protobuf::Duration const& d) & {
283+
*proto_.mutable_max_duration() = d;
284+
paths_.insert("max_duration");
285+
return *this;
286+
}
287+
CloudStorageConfigBuilder&& set_max_duration(
288+
google::protobuf::Duration const& d) && {
289+
return std::move(set_max_duration(d));
290+
}
291+
292+
CloudStorageConfigBuilder& set_max_bytes(int v) & {
293+
proto_.set_max_bytes(v);
294+
paths_.insert("max_bytes");
295+
return *this;
296+
}
297+
CloudStorageConfigBuilder&& set_max_bytes(int v) && {
298+
return std::move(set_max_bytes(v));
299+
}
300+
///@}
301+
302+
private:
303+
friend class SubscriptionBuilder;
304+
google::pubsub::v1::CloudStorageConfig proto_;
305+
std::set<std::string> paths_;
306+
};
307+
204308
/**
205309
* Create a Cloud Pub/Sub subscription configuration.
206310
*
@@ -234,6 +338,12 @@ class SubscriptionBuilder {
234338
return std::move(set_bigquery_config(std::move(v)));
235339
}
236340

341+
SubscriptionBuilder& set_cloud_storage_config(CloudStorageConfigBuilder v) &;
342+
SubscriptionBuilder&& set_cloud_storage_config(
343+
CloudStorageConfigBuilder v) && {
344+
return std::move(set_cloud_storage_config(std::move(v)));
345+
}
346+
237347
SubscriptionBuilder& set_ack_deadline(std::chrono::seconds v) & {
238348
proto_.set_ack_deadline_seconds(static_cast<std::int32_t>(v.count()));
239349
paths_.insert("ack_deadline_seconds");

google/cloud/pubsub/subscription_builder_test.cc

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,91 @@ TEST(SubscriptionBuilder, SetAckDeadline) {
390390
EXPECT_THAT(actual, IsProtoEqual(expected));
391391
}
392392

393+
TEST(SubscriptionBuilder, CreateWithCloudStorageFull) {
394+
auto const actual =
395+
SubscriptionBuilder{}
396+
.set_cloud_storage_config(
397+
CloudStorageConfigBuilder()
398+
.set_bucket("test-bucket")
399+
.set_filename_prefix("test-filename-prefix")
400+
.set_filename_suffix("test-filename-suffix")
401+
.set_avro_config(
402+
CloudStorageConfigBuilder::MakeAvroConfig(true))
403+
.set_max_duration(std::chrono::minutes(1))
404+
.set_max_bytes(2000))
405+
.BuildCreateRequest(
406+
Topic("test-project", "test-topic"),
407+
Subscription("test-project", "test-subscription"));
408+
google::pubsub::v1::Subscription expected;
409+
std::string const text = R"pb(
410+
topic: "projects/test-project/topics/test-topic"
411+
name: "projects/test-project/subscriptions/test-subscription"
412+
cloud_storage_config {
413+
bucket: "test-bucket"
414+
filename_prefix: "test-filename-prefix"
415+
filename_suffix: "test-filename-suffix"
416+
avro_config { write_metadata: true }
417+
max_duration { seconds: 60 }
418+
max_bytes: 2000
419+
})pb";
420+
ASSERT_TRUE(TextFormat::ParseFromString(text, &expected));
421+
EXPECT_THAT(actual, IsProtoEqual(expected));
422+
}
423+
424+
TEST(SubscriptionBuilder, UpdateWithCloudStorageFull) {
425+
auto const actual =
426+
SubscriptionBuilder{}
427+
.set_cloud_storage_config(
428+
CloudStorageConfigBuilder()
429+
.set_bucket("test-bucket")
430+
.set_filename_prefix("test-filename-prefix")
431+
.set_filename_suffix("test-filename-suffix")
432+
.set_avro_config(
433+
CloudStorageConfigBuilder::MakeAvroConfig(true))
434+
.set_max_duration(std::chrono::minutes(1))
435+
.set_max_bytes(2000))
436+
.BuildUpdateRequest(
437+
Subscription("test-project", "test-subscription"));
438+
google::pubsub::v1::UpdateSubscriptionRequest expected;
439+
std::string const text = R"pb(
440+
subscription {
441+
name: "projects/test-project/subscriptions/test-subscription"
442+
cloud_storage_config {
443+
bucket: "test-bucket"
444+
filename_prefix: "test-filename-prefix"
445+
filename_suffix: "test-filename-suffix"
446+
avro_config { write_metadata: true }
447+
max_duration { seconds: 60 }
448+
max_bytes: 2000
449+
}
450+
}
451+
update_mask {
452+
paths: "cloud_storage_config.avro_config"
453+
paths: "cloud_storage_config.bucket"
454+
paths: "cloud_storage_config.filename_prefix"
455+
paths: "cloud_storage_config.filename_suffix"
456+
paths: "cloud_storage_config.max_bytes"
457+
paths: "cloud_storage_config.max_duration"
458+
})pb";
459+
ASSERT_TRUE(TextFormat::ParseFromString(text, &expected));
460+
EXPECT_THAT(actual, IsProtoEqual(expected));
461+
}
462+
463+
TEST(SubscriptionBuilder, UpdateWithCloudStorageEmpty) {
464+
auto const actual = SubscriptionBuilder{}
465+
.set_cloud_storage_config(CloudStorageConfigBuilder())
466+
.BuildUpdateRequest(Subscription(
467+
"test-project", "test-subscription"));
468+
google::pubsub::v1::UpdateSubscriptionRequest expected;
469+
std::string const text = R"pb(
470+
subscription {
471+
name: "projects/test-project/subscriptions/test-subscription"
472+
}
473+
update_mask { paths: "cloud_storage_config" })pb";
474+
ASSERT_TRUE(TextFormat::ParseFromString(text, &expected));
475+
EXPECT_THAT(actual, IsProtoEqual(expected));
476+
}
477+
393478
TEST(SubscriptionBuilder, SetRetainAckedMessages) {
394479
auto const actual =
395480
SubscriptionBuilder{}.set_retain_acked_messages(true).BuildUpdateRequest(

0 commit comments

Comments
 (0)