3131import com .google .cloud .pubsublite .cloudpubsub .FlowControlSettings ;
3232import com .google .cloud .pubsublite .flink .internal .reader .*;
3333import com .google .cloud .pubsublite .flink .internal .split .SubscriptionPartitionSplit ;
34- import com .google .cloud .pubsublite .internal .BlockingPullSubscriber ;
3534import com .google .cloud .pubsublite .internal .BlockingPullSubscriberImpl ;
3635import com .google .cloud .pubsublite .internal .CursorClient ;
3736import com .google .cloud .pubsublite .internal .CursorClientSettings ;
37+ import com .google .cloud .pubsublite .internal .TopicStatsClient ;
38+ import com .google .cloud .pubsublite .internal .TopicStatsClientSettings ;
3839import com .google .cloud .pubsublite .internal .wire .PubsubContext ;
3940import com .google .cloud .pubsublite .internal .wire .RoutingMetadata ;
4041import com .google .cloud .pubsublite .internal .wire .SubscriberBuilder ;
@@ -65,7 +66,7 @@ public static <OutputT> Builder<OutputT> builder(
6566 .setDeserializationSchema (schema )
6667 .setBoundedness (Boundedness .CONTINUOUS_UNBOUNDED )
6768 .setTimestampSelector (MessageTimestampExtractor .publishTimeExtractor ())
68- .setPartitionFinishedCondition ( PartitionFinishedCondition .continueIndefinitely ());
69+ .setStopCondition ( StopCondition .continueIndefinitely ());
6970 }
7071
7172 public static Builder <SequencedMessage > messagesBuilder () {
@@ -85,7 +86,7 @@ public static Builder<SequencedMessage> messagesBuilder() {
8586 public abstract MessageTimestampExtractor timestampSelector ();
8687
8788 // Optional
88- public abstract PartitionFinishedCondition . Factory partitionFinishedCondition ();
89+ public abstract StopCondition stopCondition ();
8990
9091 // Internal
9192 abstract PubsubLiteDeserializationSchema <OutputT > deserializationSchema ();
@@ -94,6 +95,38 @@ public static Builder<SequencedMessage> messagesBuilder() {
9495
9596 abstract @ Nullable SerializableSupplier <CursorClient > cursorClientSupplier ();
9697
98+ abstract @ Nullable SerializableSupplier <TopicStatsClient > topicStatsClientSupplier ();
99+
100+ AdminClient getAdminClient () {
101+ if (adminClientSupplier () != null ) {
102+ return adminClientSupplier ().get ();
103+ }
104+ return AdminClient .create (
105+ AdminClientSettings .newBuilder ()
106+ .setRegion (subscriptionPath ().location ().extractRegion ())
107+ .build ());
108+ }
109+
110+ TopicStatsClient getTopicStatsClient () {
111+ if (topicStatsClientSupplier () != null ) {
112+ return topicStatsClientSupplier ().get ();
113+ }
114+ return TopicStatsClient .create (
115+ TopicStatsClientSettings .newBuilder ()
116+ .setRegion (subscriptionPath ().location ().extractRegion ())
117+ .build ());
118+ }
119+
120+ CursorClient getCursorClient () {
121+ if (cursorClientSupplier () != null ) {
122+ return cursorClientSupplier ().get ();
123+ }
124+ return CursorClient .create (
125+ CursorClientSettings .newBuilder ()
126+ .setRegion (subscriptionPath ().location ().extractRegion ())
127+ .build ());
128+ }
129+
97130 private static SubscriberServiceClient newSubscriberServiceClient (
98131 SubscriptionPath path , Partition partition ) throws ApiException {
99132 try {
@@ -110,51 +143,29 @@ private static SubscriberServiceClient newSubscriberServiceClient(
110143 }
111144 }
112145
113- private static SubscriberFactory getSubscriberFactory (
114- SubscriptionPath path , Partition partition , SeekRequest seek ) {
146+ private static SubscriberFactory getSubscriberFactory (SubscriptionPartitionSplit split ) {
115147 return (consumer ) ->
116148 SubscriberBuilder .newBuilder ()
117- .setSubscriptionPath (path )
118- .setPartition (partition )
119- .setServiceClient (newSubscriberServiceClient (path , partition ))
149+ .setSubscriptionPath (split .subscriptionPath ())
150+ .setPartition (split .partition ())
151+ .setServiceClient (
152+ newSubscriberServiceClient (split .subscriptionPath (), split .partition ()))
120153 .setMessageConsumer (consumer )
121- .setInitialLocation (seek )
154+ .setInitialLocation (
155+ SeekRequest .newBuilder ()
156+ .setCursor (Cursor .newBuilder ().setOffset (split .start ().value ()).build ())
157+ .build ())
122158 .build ();
123159 }
124160
125- AdminClient getAdminClient () {
126- if (adminClientSupplier () != null ) {
127- return adminClientSupplier ().get ();
128- }
129- return AdminClient .create (
130- AdminClientSettings .newBuilder ()
131- .setRegion (subscriptionPath ().location ().extractRegion ())
132- .build ());
133- }
134-
135- CursorClient getCursorClient () {
136- if (cursorClientSupplier () != null ) {
137- return cursorClientSupplier ().get ();
138- }
139- return CursorClient .create (
140- CursorClientSettings .newBuilder ()
141- .setRegion (subscriptionPath ().location ().extractRegion ())
142- .build ());
143- }
144-
145161 CompletablePullSubscriber .Factory getSplitStateFactory () {
146- return split -> {
147- SeekRequest seek =
148- SeekRequest .newBuilder ()
149- .setCursor (Cursor .newBuilder ().setOffset (split .start ().value ()).build ())
150- .build ();
151- SubscriberFactory factory =
152- getSubscriberFactory (split .subscriptionPath (), split .partition (), seek );
153-
154- BlockingPullSubscriber b = new BlockingPullSubscriberImpl (factory , flowControlSettings ());
155- return new CompletablePullSubscriberImpl (
156- b , partitionFinishedCondition ().New (split .subscriptionPath (), split .partition ()));
157- };
162+ PartitionFinishedCondition .Factory conditionFactory = stopCondition ().toFinishCondition ();
163+ return new ConditionallyCompleteSubscriberFactory (
164+ (split ) ->
165+ new CompletablePullSubscriberImpl (
166+ new BlockingPullSubscriberImpl (getSubscriberFactory (split ), flowControlSettings ()),
167+ conditionFactory .New (split .subscriptionPath (), split .partition ())),
168+ conditionFactory );
158169 }
159170
160171 Supplier <SplitReader <Record <OutputT >, SubscriptionPartitionSplit >> getSplitReaderSupplier () {
@@ -184,7 +195,7 @@ public void onSuccess(Void unused) {}
184195 }
185196
186197 @ AutoValue .Builder
187- abstract static class Builder <OutputT > {
198+ public abstract static class Builder <OutputT > {
188199 // Required
189200 public abstract Builder <OutputT > setSubscriptionPath (SubscriptionPath path );
190201
@@ -198,8 +209,7 @@ abstract static class Builder<OutputT> {
198209 public abstract Builder <OutputT > setTimestampSelector (MessageTimestampExtractor value );
199210
200211 // Optional
201- public abstract Builder <OutputT > setPartitionFinishedCondition (
202- PartitionFinishedCondition .Factory value );
212+ public abstract Builder <OutputT > setStopCondition (StopCondition value );
203213
204214 abstract Builder <OutputT > setDeserializationSchema (
205215 PubsubLiteDeserializationSchema <OutputT > schema );
@@ -208,6 +218,21 @@ abstract Builder<OutputT> setDeserializationSchema(
208218
209219 abstract Builder <OutputT > setCursorClientSupplier (SerializableSupplier <CursorClient > value );
210220
211- abstract PubsubLiteSourceSettings <OutputT > build ();
221+ abstract Builder <OutputT > setTopicStatsClientSupplier (
222+ SerializableSupplier <TopicStatsClient > value );
223+
224+ public abstract PubsubLiteSourceSettings <OutputT > autoBuild ();
225+
226+ public PubsubLiteSourceSettings <OutputT > build () {
227+ PubsubLiteSourceSettings <OutputT > settings = autoBuild ();
228+ setStopCondition (
229+ settings
230+ .stopCondition ()
231+ .canonicalize (
232+ settings .subscriptionPath (),
233+ settings ::getAdminClient ,
234+ settings ::getTopicStatsClient ));
235+ return autoBuild ();
236+ }
212237 }
213238}
0 commit comments