1919
2020import static org .apache .beam .vendor .guava .v32_1_2_jre .com .google .common .collect .ImmutableList .toImmutableList ;
2121
22- import com .google .auto .value .AutoOneOf ;
2322import java .util .ArrayList ;
2423import java .util .Collections ;
2524import java .util .Comparator ;
25+ import java .util .HashSet ;
2626import java .util .List ;
2727import java .util .concurrent .CountDownLatch ;
28- import java . util . stream . Stream ;
28+ import javax . annotation . Nullable ;
2929import org .apache .beam .runners .dataflow .worker .windmill .Windmill ;
30- import org .apache .beam .runners .dataflow .worker .windmill .Windmill .ComputationGetDataRequest ;
3130import org .apache .beam .runners .dataflow .worker .windmill .Windmill .GlobalDataRequest ;
3231import org .apache .beam .runners .dataflow .worker .windmill .Windmill .KeyedGetDataRequest ;
3332import org .apache .beam .runners .dataflow .worker .windmill .client .WindmillStreamShutdownException ;
33+ import org .apache .beam .sdk .util .Preconditions ;
3434import org .apache .beam .vendor .guava .v32_1_2_jre .com .google .common .collect .ImmutableList ;
3535import org .slf4j .Logger ;
3636import org .slf4j .LoggerFactory ;
@@ -46,15 +46,38 @@ private static String debugFormat(long value) {
4646 return String .format ("%016x" , value );
4747 }
4848
49+ static class ComputationAndKeyRequest {
50+ private final String computation ;
51+ private final KeyedGetDataRequest request ;
52+
53+ ComputationAndKeyRequest (String computation , KeyedGetDataRequest request ) {
54+ this .computation = computation ;
55+ this .request = request ;
56+ }
57+
58+ String getComputation () {
59+ return computation ;
60+ }
61+
62+ KeyedGetDataRequest getKeyedGetDataRequest () {
63+ return request ;
64+ }
65+ }
66+
4967 static class QueuedRequest {
5068 private final long id ;
51- private final ComputationOrGlobalDataRequest dataRequest ;
69+ private final @ Nullable ComputationAndKeyRequest computationAndKeyRequest ;
70+ private final @ Nullable GlobalDataRequest globalDataRequest ;
5271 private AppendableInputStream responseStream ;
5372
5473 private QueuedRequest (
55- long id , ComputationOrGlobalDataRequest dataRequest , long deadlineSeconds ) {
74+ long id ,
75+ @ Nullable ComputationAndKeyRequest computationAndKeyRequest ,
76+ @ Nullable GlobalDataRequest globalDataRequest ,
77+ long deadlineSeconds ) {
5678 this .id = id ;
57- this .dataRequest = dataRequest ;
79+ this .computationAndKeyRequest = computationAndKeyRequest ;
80+ this .globalDataRequest = globalDataRequest ;
5881 responseStream = new AppendableInputStream (deadlineSeconds );
5982 }
6083
@@ -63,27 +86,22 @@ static QueuedRequest forComputation(
6386 String computation ,
6487 KeyedGetDataRequest keyedGetDataRequest ,
6588 long deadlineSeconds ) {
66- ComputationGetDataRequest computationGetDataRequest =
67- ComputationGetDataRequest .newBuilder ()
68- .setComputationId (computation )
69- .addRequests (keyedGetDataRequest )
70- .build ();
7189 return new QueuedRequest (
7290 id ,
73- ComputationOrGlobalDataRequest .computation (computationGetDataRequest ),
91+ new ComputationAndKeyRequest (computation , keyedGetDataRequest ),
92+ null ,
7493 deadlineSeconds );
7594 }
7695
7796 static QueuedRequest global (
7897 long id , GlobalDataRequest globalDataRequest , long deadlineSeconds ) {
79- return new QueuedRequest (
80- id , ComputationOrGlobalDataRequest .global (globalDataRequest ), deadlineSeconds );
98+ return new QueuedRequest (id , null , globalDataRequest , deadlineSeconds );
8199 }
82100
83101 static Comparator <QueuedRequest > globalRequestsFirst () {
84102 return (QueuedRequest r1 , QueuedRequest r2 ) -> {
85- boolean r1gd = r1 .dataRequest . isGlobal () ;
86- boolean r2gd = r2 .dataRequest . isGlobal () ;
103+ boolean r1gd = r1 .getKind () == Kind . GLOBAL ;
104+ boolean r2gd = r2 .getKind () == Kind . GLOBAL ;
87105 return r1gd == r2gd ? 0 : (r1gd ? -1 : 1 );
88106 };
89107 }
@@ -93,7 +111,13 @@ long id() {
93111 }
94112
95113 long byteSize () {
96- return dataRequest .serializedSize ();
114+ if (globalDataRequest != null ) {
115+ return globalDataRequest .getSerializedSize ();
116+ }
117+ Preconditions .checkStateNotNull (computationAndKeyRequest );
118+ return 10L
119+ + computationAndKeyRequest .request .getSerializedSize ()
120+ + computationAndKeyRequest .getComputation ().length ();
97121 }
98122
99123 AppendableInputStream getResponseStream () {
@@ -104,22 +128,56 @@ void resetResponseStream() {
104128 this .responseStream = new AppendableInputStream (responseStream .getDeadlineSeconds ());
105129 }
106130
107- public ComputationOrGlobalDataRequest getDataRequest () {
108- return dataRequest ;
131+ enum Kind {
132+ COMPUTATION_AND_KEY_REQUEST ,
133+ GLOBAL
134+ }
135+
136+ Kind getKind () {
137+ return computationAndKeyRequest != null ? Kind .COMPUTATION_AND_KEY_REQUEST : Kind .GLOBAL ;
138+ }
139+
140+ ComputationAndKeyRequest getComputationAndKeyRequest () {
141+ return Preconditions .checkStateNotNull (computationAndKeyRequest );
142+ }
143+
144+ GlobalDataRequest getGlobalDataRequest () {
145+ return Preconditions .checkStateNotNull (globalDataRequest );
109146 }
110147
111148 void addToStreamingGetDataRequest (Windmill .StreamingGetDataRequest .Builder builder ) {
112149 builder .addRequestId (id );
113- if (dataRequest .isForComputation ()) {
114- builder .addStateRequest (dataRequest .computation ());
115- } else {
116- builder .addGlobalDataRequest (dataRequest .global ());
150+ switch (getKind ()) {
151+ case COMPUTATION_AND_KEY_REQUEST :
152+ ComputationAndKeyRequest request = getComputationAndKeyRequest ();
153+ builder
154+ .addStateRequestBuilder ()
155+ .setComputationId (request .getComputation ())
156+ .addRequests (request .request );
157+ break ;
158+ case GLOBAL :
159+ builder .addGlobalDataRequest (getGlobalDataRequest ());
160+ break ;
117161 }
118162 }
119163
120164 @ Override
121165 public final String toString () {
122- return "QueuedRequest{" + "dataRequest=" + dataRequest + ", id=" + id + '}' ;
166+ StringBuilder result = new StringBuilder ("QueuedRequest{id=" ).append (id ).append (", " );
167+ if (getKind () == Kind .GLOBAL ) {
168+ result .append ("GetSideInput=" ).append (getGlobalDataRequest ());
169+ } else {
170+ KeyedGetDataRequest key = getComputationAndKeyRequest ().request ;
171+ result
172+ .append ("KeyedGetState=[shardingKey=" )
173+ .append (debugFormat (key .getShardingKey ()))
174+ .append ("cacheToken=" )
175+ .append (debugFormat (key .getCacheToken ()))
176+ .append ("workToken" )
177+ .append (debugFormat (key .getWorkToken ()))
178+ .append ("]" );
179+ }
180+ return result .append ('}' ).toString ();
123181 }
124182 }
125183
@@ -128,13 +186,14 @@ public final String toString() {
128186 */
129187 static class QueuedBatch {
130188 private final List <QueuedRequest > requests = new ArrayList <>();
189+ private final HashSet <Long > workTokens = new HashSet <>();
131190 private final CountDownLatch sent = new CountDownLatch (1 );
132191 private long byteSize = 0 ;
133192 private volatile boolean finalized = false ;
134193 private volatile boolean failed = false ;
135194
136195 /** Returns a read-only view of requests. */
137- List <QueuedRequest > requestsReadOnly () {
196+ List <QueuedRequest > requestsView () {
138197 return Collections .unmodifiableList (requests );
139198 }
140199
@@ -155,18 +214,10 @@ Windmill.StreamingGetDataRequest asGetDataRequest() {
155214 return builder .build ();
156215 }
157216
158- boolean isEmpty () {
159- return requests .isEmpty ();
160- }
161-
162217 int requestsCount () {
163218 return requests .size ();
164219 }
165220
166- long byteSize () {
167- return byteSize ;
168- }
169-
170221 boolean isFinalized () {
171222 return finalized ;
172223 }
@@ -176,9 +227,26 @@ void markFinalized() {
176227 }
177228
178229 /** Adds a request to the batch. */
179- void addRequest (QueuedRequest request ) {
230+ boolean tryAddRequest (QueuedRequest request , int countLimit , long byteLimit ) {
231+ if (finalized ) {
232+ return false ;
233+ }
234+ if (requests .size () >= countLimit ) {
235+ return false ;
236+ }
237+ long estimatedBytes = request .byteSize ();
238+ if (byteSize + estimatedBytes >= byteLimit ) {
239+ return false ;
240+ }
241+
242+ if (request .getKind () == QueuedRequest .Kind .COMPUTATION_AND_KEY_REQUEST
243+ && !workTokens .add (request .getComputationAndKeyRequest ().request .getWorkToken ())) {
244+ return false ;
245+ }
246+ // At this point we have added to work items so we must accept the item.
180247 requests .add (request );
181- byteSize += request .byteSize ();
248+ byteSize += estimatedBytes ;
249+ return true ;
182250 }
183251
184252 /**
@@ -227,75 +295,9 @@ void waitForSendOrFailNotification()
227295
228296 private ImmutableList <String > createStreamCancelledErrorMessages () {
229297 return requests .stream ()
230- .flatMap (
231- request -> {
232- switch (request .getDataRequest ().getKind ()) {
233- case GLOBAL :
234- return Stream .of ("GetSideInput=" + request .getDataRequest ().global ());
235- case COMPUTATION :
236- return request .getDataRequest ().computation ().getRequestsList ().stream ()
237- .map (
238- keyedRequest ->
239- "KeyedGetState=["
240- + "shardingKey="
241- + debugFormat (keyedRequest .getShardingKey ())
242- + "cacheToken="
243- + debugFormat (keyedRequest .getCacheToken ())
244- + "workToken"
245- + debugFormat (keyedRequest .getWorkToken ())
246- + "]" );
247- default :
248- // Will never happen switch is exhaustive.
249- throw new IllegalStateException ();
250- }
251- })
298+ .map (QueuedRequest ::toString )
252299 .limit (STREAM_CANCELLED_ERROR_LOG_LIMIT )
253300 .collect (toImmutableList ());
254301 }
255302 }
256-
257- @ AutoOneOf (ComputationOrGlobalDataRequest .Kind .class )
258- abstract static class ComputationOrGlobalDataRequest {
259- static ComputationOrGlobalDataRequest computation (
260- ComputationGetDataRequest computationGetDataRequest ) {
261- return AutoOneOf_GrpcGetDataStreamRequests_ComputationOrGlobalDataRequest .computation (
262- computationGetDataRequest );
263- }
264-
265- static ComputationOrGlobalDataRequest global (GlobalDataRequest globalDataRequest ) {
266- return AutoOneOf_GrpcGetDataStreamRequests_ComputationOrGlobalDataRequest .global (
267- globalDataRequest );
268- }
269-
270- abstract Kind getKind ();
271-
272- abstract ComputationGetDataRequest computation ();
273-
274- abstract GlobalDataRequest global ();
275-
276- boolean isGlobal () {
277- return getKind () == Kind .GLOBAL ;
278- }
279-
280- boolean isForComputation () {
281- return getKind () == Kind .COMPUTATION ;
282- }
283-
284- long serializedSize () {
285- switch (getKind ()) {
286- case GLOBAL :
287- return global ().getSerializedSize ();
288- case COMPUTATION :
289- return computation ().getSerializedSize ();
290- // this will never happen since the switch is exhaustive.
291- default :
292- throw new UnsupportedOperationException ("unknown dataRequest type." );
293- }
294- }
295-
296- enum Kind {
297- COMPUTATION ,
298- GLOBAL
299- }
300- }
301303}
0 commit comments